Volatile variable value do not change in ISR

Hi!

I’m using ATtiny13a and in my project I wanted to implement sleeping and waking up using watchdog timer. However the variable I declared as volatile does not hold its value in ISR so I can not wait longer than 8 seconds. Is there any points I miss? Any help appreciated.

#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#define BUZZER_PIN PB1

volatile uint8_t count = 0;

ISR(WDT_vect)
{
  count++;
  if (count > 1)
  {
    PORTB ^= _BV(BUZZER_PIN); // Toggle Port
  }
}

void setup()
{
  // initialize the digital pin as an output.
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);

  wdt_enable(WDTO_8S); //Set watchdog timer to 8 seconds

  WDTCR |= (1 << WDTIE); // Enable watchdog timer interrupts
  sei();                 // Enable global interrupts
  // Use the Power Down sleep mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  for (;;)
  {
    sleep_mode(); // go to sleep and wait for interrupt...
  }
}
// the loop routine runs over and over again forever:
void loop()
{
}
ISR(WDT_vect)
{
  count++;
  if (count > 1)
  {
    PORTB ^= _BV(BUZZER_PIN); // Toggle Port
  }
}

Shouldn't you set 'count' back to 0 when toggling the buzzer pin? Otherwise, it will just keep counting and will always be "> 1" on every interrupt.

Note: There is a special feature of the PIN (Port INput) register that will toggle an output pin if you write 1 to it:

    PINB = _BV(BUZZER_PIN); // Toggle the buzzer pin

johnwasser:

ISR(WDT_vect)

{
 count++;
 if (count > 1)
 {
   PORTB ^= _BV(BUZZER_PIN); // Toggle Port
 }
}




Shouldn't you set 'count' back to 0 when toggling the buzzer pin? Otherwise, it will just keep counting and will always be "> 1" on every interrupt.

Note: There is a special feature of the PIN (Port INput) register that will toggle an output pin if you write 1 to it:


PINB = _BV(BUZZER_PIN); // Toggle the buzzer pin

Yes, you are right. However, the point here is it never goes into the if statement without increasing count variable to exceed the limit in the first place.

ISR(WDT_vect)

{
 count++;
 if (count > 1)
 {
   PORTB ^= _BV(BUZZER_PIN); // Toggle Port
 }
}

Are you sure ISR(WDT_vect) is called at all?

What happens when you change that to

ISR(WDT_vect)
{
  PORTB ^= _BV(BUZZER_PIN); // Toggle Port
}

?

Erik_Baas:
Are you sure ISR(WDT_vect) is called at all?

What happens when you change that to

ISR(WDT_vect)

{
 PORTB ^= _BV(BUZZER_PIN); // Toggle Port
}



?

Yes, it does. Even if I change count++ to count+=2 the pin toggles.

Is it possible the watchdog timer does not only call the ISR, but also resets the ATTiny? I know it can do that, but I don't know how... Could you add a Serial.println("test") or something like that to void setup() to check that?

And how about Serial.println(count) once every second in void loop() ?

Have you tried clearing the count as I suggested?

ISR(WDT_vect)
{
  count++;
  if (count > 1)
  {
    count = 0;  //------------  ADD THIS LINE -----------------
    PORTB ^= _BV(BUZZER_PIN); // Toggle Port
  }
}

Erik_Baas:
Is it possible the watchdog timer does not only call the ISR, but also resets the ATTiny? I know it can do that, but I don’t know how… Could you add a Serial.println("test") or something like that to void setup() to check that?

And how about Serial.println(count) once every second in void loop() ?

Thanks a lot for this. Apparently wde_enable(WDTO_8S) was causing the watchdog to be in interrupt and reset mode and causing attiny to reset after each interrupt. I have used

WDTCR = (1 << WDTIE) | (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (1 << WDP0); //8 Seconds

instead of wde_enable(WDTO_8S) and it works now.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.