volatile boolean variable changing between setup and ISR

Development board: Arduino UNO, Rev: ??, ATMEGA 328P-PU

Generating a PWM output using Timer2.

Goal: Count the number of Timer2 OVerflow's.

  1. I want the volatile boolean variable 'flag' to be toggled in the ISR so I can count it in the void loop().
    The count routine code has not been written yet.
    I used "volatile boolean flag;" "to load the variable from RAM and not from a storage register".

The first time I print 'flag' , in void setup() , it shows zero, which is correct.
When I print 'flag' , in the void loop() , it shows, and remains, the number three.

How/where is 'flag' being changed?

  1. I monitor pin 2 with an oscilloscope to show which part of the if is executed.
    Two pulses are always shown, indicating the else is always taken.
    But, the else sets 'flag' to true (the number one)
    and
    println in void loop() shows 'flag' equal to the number three.

Then why isn't the if taken on the next interrupt?

  1. I apologize, I did not adhere to the "minimal" sketch . I thought it would be better to be complete.

  2. Output to Serial Monitor shown after code.

//  Prescaler at 32
//  Fast PWM
//  Mode 3
//  TOP 0xFF
//  Update of OCR2A at BOTTOM (0x00)
//  TOV flag set on MAX (256)
//  WGM22=0  WGM21=1  WGM20=1
//
void setup()
{                     // Begin Setup
  //                       Put your setup code here, to run once:
  Serial.begin(9600); // open serial port.
  delay(20);          //  Put a delay in to open port.
  //Serial.println(F("Hello World")); // 
  //Serial.println(F(""));            // Blank line.
  //delay(30);                     // Must delay 'some' to allow buffer to be xmtd.
  //
  //      reminder:    long,    4 bytes  -2,147,483,648 to 2,147,483,647
  //                   integer  2 bytes         -32,768 to        32,767
  //                   byte     1 bytes               0 to           255  unsigned number
  //                   boolean  1 byte         true (1, any value but zero)  or false (zero)
  //
  //      Select    Time to Spin Up Rotor  (milliseconds)
  unsigned long SpinUP = 40000L;  // Select   40 seconds to spin up   x 1000 ms/sec
  //
  //      Time for each set of pulses of the same Duty Cycle.  Just  Spin Up Time / 10
  unsigned long PulsePeriod =SpinUP/10L;
  //
  //     Clock Output Freq = 16,000,000 
  //     Timer2 Output Freq = 16,000,000 / (256 x 32) = 1953.125 Hz --> 512 uSec per pulse
  //     Pulses per PulsePeriod:  PulsePeriod / 512 uSec = 4 sec / 512 uSec/pulse = 7812.5 pulses
  //
  unsigned long StartTime;
  unsigned long time;
  StartTime = micros();   //overflows (goes back to zero) after approximately 70 minutes.
  // 
  Serial.print(F("Start Time in microsecs : "));
  Serial.println(StartTime);  
  delay(50);            // Must delay 'some' to allow buffer to be xmtd.
  //
  pinMode(2, OUTPUT);   // Toggle this pin when TOV2 is detected  
  pinMode(3, OUTPUT);   // Connected to  Output Compare   OC2 B  
  pinMode(11, OUTPUT);  // Connected to  Output Compare   OC2 A
  //
  //                       false defined as zero
  //                       true  any integer other than zero  
  volatile boolean flag;          // copied Nick Gammon's code
  flag = false;
  Serial.print(F("in setup flag = "));
  Serial.println(flag,BIN);         // note: Binary
  delay(10);            // Must delay 'some' to allow buffer to be xmtd.
  //
  noInterrupts();        // Turn OFF all interrupts while setting up timers
  //   Clear Timer Control Registers, just in case
  TCCR2A = 0;
  //TCCR2B = 0;          // This will stop the Tclk to Timer 2
  //
  TIMSK2 = _BV (TOIE2);     // TC2 Interrupt Mask Register.  Enable the timer 2 interrupt
  TIFR2  = _BV (TOV2);       //  TC2 Interrupt Flag Register.  Clear TOV2 (by writing a 1)  Overflow Flag
  //    Set up the Timer/Counter Control Register 2, A & B
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  //   CS22=0  CS21=1      CS20=1   prescaler for 32
  TCCR2B = _BV(CS21) | _BV(CS20);   //  This will route Tclk to Timer 2 through scaler
  //    Set up the Output Compare Register 2,   A & B
  OCR2A = 32;         //  This is for monitoring the pin 11
  OCR2B = 64;         //  This is for monitoring the pin  3
  interrupts();         // Turn ON all interrupts
  //
  StartTime = micros();   //overflows (goes back to zero) after approximately 70 minutes.
  // 
}                       // End setup
  //
  //                     Timer2 Over Flow interrupt routine
  //                     Monitor output pin 2 to verify path.
ISR (TIMER2_OVF_vect)     // Timer 2 OVer Flow vector
{
   noInterrupts();        // Turn OFF all interrupts during ISR so  flag  is not changed
   volatile boolean flag;
        if (flag == true)
        {
         flag = false;        // toggle flag's value
         digitalWrite(2, 1);  // 4 pulses, monitor with O-scope
         digitalWrite(2, 0);  // do not use PIND because it uses delay()
         digitalWrite(2, 1);
         digitalWrite(2, 0);
         digitalWrite(2, 1);
         digitalWrite(2, 0);
         digitalWrite(2, 1);
         digitalWrite(2, 0);
        }
        else
        {
         flag = true;         // toggle flag's value
         digitalWrite(2, 1);  // 2 pulses, monitor with O-scope
         digitalWrite(2, 0);
         digitalWrite(2, 1);
         digitalWrite(2, 0);
        }
   interrupts();         // Turn ON all interrupts
}  // end of interrupt routine

void loop() 
     {
  // put your main code here, to run repeatedly:
   volatile boolean flag;
   Serial.print(F("in loop flag = "));
   Serial.println(flag,BIN);          // note: Binary
   delay(10);            // Must delay 'some' to allow buffer to be xmtd.
     }

Serial Monitor shows:

Start Time in microsecs : 20012
in setup flag = 0
in loop flag = 11
in loop flag = 11
in loop flag = 11
(continues repeating)

You have created TWO flags - one in setup(), a second one in your ISR. If you want a variable accessible to both, it must be a global.

Regards,
Ray L.

Remove both lines below from your interrupt routine. Interrupts are already turned off within an interrupt routine.

  noInterrupts();        // Turn OFF all interrupts during ISR so  flag  is not changed
   volatile boolean flag;

Also remove this line from the end of the ISR, or the ISR itself could be interrupted by another.

   interrupts();         // Turn ON all interrupts