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.

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
    – jsotola
    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.
    – StarCat
    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.
    – Gerben
    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
    – chrisl
    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;
1

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

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.