1

I have a code here where I collect an array of data and do some data analysis with the data. The only thing I'm struggle with is how to exit the ISR after I am done running my code. I am using a pre-scalar of 256 and running the ISR once (1Hz)

const signed int numReadings = 21;
volatile int gauge0[numReadings];
volatile int gauge1[numReadings];
volatile int add[numReadings];
volatile int deltaGAUGE;
volatile int slopeADD;
volatile int mean;
const int A0_pin = PC0;
const int A1_pin = PC1;
const uint16_t t1_load = 0;
const uint16_t t1_comp = 62500;
void setup() {
 
 //Set A0 and A1 pins as inputs
 DDRC &= ~(1 << A0_pin);
 DDRC &= ~(1 << A1_pin);
 //Reset Timer1 Control Reg A
 TCCR1A = 0;
 //Set CTC mode
 TCCR1B &= ~(1 << WGM13);
 TCCR1B |= (1 << WGM12);
 //Set to prescaler of 1024
 TCCR1B |= (1 << CS12);
 TCCR1B &= ~(1 << CS11);
 TCCR1B &= ~(1 << CS10);
 //Reset Timer1 and set compare value
 TCNT1 = t1_load;
 OCR1A = t1_comp;
 //Enable Timer1 compare interrupt
 TIMSK1 = (1 << OCIE1A);
 //Enable global interrupt
 sei();
 
 Serial.begin(9600);
 Serial.println(" ");
 Serial.println("START");
 Serial.println(" ");
}
ISR(TIMER1_COMPA_vect){
 Serial.println(" ");
 for (unsigned int i=0; i<numReadings; i++)
 {
 gauge0[i] = (analogRead(A0_pin))*(100.00/1024.0);
 gauge1[i] = (analogRead(A1_pin))*(100.00/1024.0);
 add[i] = ((gauge0[i]+gauge1[i]));
 
 deltaGAUGE = abs(add[20] - add[0]);
 slopeADD = abs((add[20]-add[0])/(20-0));
 mean = (add[1]+add[2]+add[3]+add[4]+add[5]+add[6]+add[7]+add[8]+add[9]+add[10]+
 
 add[11]+add[12]+add[13]+add[14]+add[15]+add[16]+add[17]+add[18]+add[19]+add[20])/20;
 if(i == 20)
 { 
 Serial.print("This of the delta AVG reading: ");
 Serial.println(deltaGAUGE);
 Serial.println(" ");
 Serial.print("This of the slope reading: ");
 Serial.println(slopeADD);
 Serial.println(" ");
 Serial.print("This of the mean reading: ");
 Serial.println(mean);
 Serial.println(" ");
 Serial.println("END"); 
 }
 
 delay(50); //wait .05 sec
 
 }
 
}
void loop()
{
}

When I run the circuit, the interrupt keep executing every seconds for an infinite amount of time, while I just want it to run once and exit.

I have tried the exit(0) command but I get an output that looks like this

START
 
This of the delta AVG reading: 0
 
This of t

As you can see, The program does not execute completely. Anyone have any idea how I can fix this, or anyhow I can better my code? thank you.

asked Feb 24, 2021 at 4:49
6
  • 1
    take all the code in ISR and move it into an if block inside loop() ... set a flag inside the ISR ... set the if block to execute when the flag is set Commented Feb 24, 2021 at 5:05
  • 2
    ISRs are time critical and should finish as fast as possible. Yours is taking much too long. Look very critically at what MUST be done when an interrupt occurs and move all other code out of the ISR, especially all of the time consuming Serial.print() and the delay(). Let the main program handle the calculations and the output. The ISR only needs to do the measurements. Commented Feb 24, 2021 at 7:02
  • 1
    Forget about interrupts and read Blink Without Delay. Commented Feb 24, 2021 at 8:14
  • 2
    @StarCat it's even worse. delay and to some extent Serial.print require interrupts to work, but all interrupts are disabled while running your ISR code. So the code will just hang. Commented Feb 24, 2021 at 15:39
  • Why are you using a hardware timer for a long interval like 1 second? Why don't you just use millis() (or micros(), if you need more precision) to time the measurements? That would be way easier Commented Feb 24, 2021 at 21:03

2 Answers 2

1

As some of the comments have suggested, I would either get rid of the ISR or reduce the size significantly. When using ISRs, it is recommended that you keep the code as small as possible. Use it to set variables, for example

//these two variables are global
ISR(TIMER1_COMPA_vect){
 someValue = true;
 numberOfValues++;
}

you should also never use any Serial functions inside an ISR as these use interrupts themselves which can cause all kinds of problems

After using the ISR to update global variables, you can then use if() or while() statements within the loop() function to execute your serial print functions and such

P.S. on a side note, I would recommend changing your code where you calculated mean from

 mean = (add[1]+add[2]+add[3]+add[4]+add[5]+add[6]+add[7]+add[8]+add[9]+add[10]+ 
add[11]+add[12]+add[13]+add[14]+add[15]+add[16]+add[17]+add[18]+add[19]+add[20])/20;

to

for(uint8_t i = 1;i<=20;i++){
 mean += add[i];
}
mean /= 20;
answered Feb 25, 2021 at 13:47
1

Use cli(); to completely disable interrupt. Then use sei(); to re-enable the interrupt if you need it later.

answered Feb 25, 2021 at 17:44

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.