Watchdog Timer with Attiny 85

Hello all,

I am trying to use watchdog timer with my code and i have some questions (please note that this is the first time that i work with watchdog timer so sorry if i ask stupid questions). My code is simple there are 3 light sensors and and LED and Buzzer. when the sensors detect light the LED and buzzer go on for a sec then the whole system shuts down for 4 sec. So i thought that i could use watchdog timer to make the the whole system to sleep during these 4 secs to save battery life.

After i tried coding the watchdog timer it seem to work but the problem is that it looks the the system looks for light and if there is not the system goes to sleep for 4 secs...then wakes up to look again then goes to sleep for 4secs again.

But what i want is when the system goes to sleep, after 4 secs it doesn't wake up again till it detects light again. (so after the LED and buzzer go off the system should go to sleep for 4 secs and after that it will stay in sleep mode till light is detected again)

(So sorry if my explaining is bad and thank you all in advance.)

Here is the code I'm using:

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

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

//int pinLed = 4;
int ledPin = 1; //PB3
int buzzPin = 0; //PB0
int sensorReading1 = 0;
int sensorReading2 = 0;
int sensorReading3 = 0;
int sensitvety = 60;
int turnOn = 0;
int sensor1 = 1; //PB5
int sensor2 = 2; //PB4
int sensor3 = 3; //PB2
volatile boolean f_wdt = 1;

void setup(){
  //pinMode(pinLed,OUTPUT);
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(sensor3, INPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(buzzPin, OUTPUT);
}

void loop(){
  if (f_wdt==1) {  // wait for timed out watchdog / flag is set when a watchdog timeout occurs
    f_wdt=0;       // reset flag
    
    sensorReading1 = (analogRead(sensor1)/4);
    sensorReading2 = (analogRead(sensor2)/4);
    sensorReading3 = (analogRead(sensor3)/4);

    
     if(sensorReading1 > sensitvety || sensorReading2 > sensitvety || sensorReading3 > sensitvety){
    turnOn = 1;
        }
  
      if(turnOn){
      delay(100);
      digitalWrite(buzzPin, HIGH);
      digitalWrite(ledPin, HIGH);
  
      delay(25);
      digitalWrite(buzzPin, LOW);
      delay(200);
      digitalWrite(ledPin, LOW);
      setup_watchdog(8); // approximately 4 seconds sleep
      turnOn = 0; 
  }

    //pinMode(pinLed,INPUT); // set all used port to intput to save power
      pinMode(ledPin, INPUT);
      pinMode(buzzPin, INPUT);
      system_sleep();
      //pinMode(pinLed,OUTPUT); // set all ports into state before sleep
      pinMode(ledPin, OUTPUT);
      pinMode(buzzPin, OUTPUT);
  }
}

// set system into the sleep state 
// system wakes up when wtchdog is timed out
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out 
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}
  
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) {
  f_wdt=1;  // set global flag
}

You can also wake up when pin PB2 changes state (using INT0 interrupt)

But ... maybe it's easier just to sleep for less than 4 seconds.

eg. 0.25 seconds should work.

You can also wake up when pin PB2 changes state (using INT0 interrupt)

is it possible to set a specific sate to wake it up?

But ... maybe it's easier just to sleep for less than 4 seconds.

eg. 0.25 seconds should work.

The problem is those 4 secs are essential to the my project

iA2K:
The problem is those 4 secs are essential to the my project

I don't think I understand the problem.

It doesn't matter if the chip keeps on waking up and going straight back to sleep again.

I don't think I understand the problem.

It doesn't matter if the chip keeps on waking up and going straight back to sleep again.

During those 4 secs even if there was light i want the chip to do nothing (that is the idea of my circuit)
i could use delay to make the chip do nothing but that will affect battery life....i'm really trying to make it as power efficient as possible

Why not use AC to DC converters and a power plug ? It's definitely more economic and you wouldn't have to worry about battery life and etc etc etc .

Why not use AC to DC converters and a power plug ? It's definitely more economic and you wouldn't have to worry about battery life and etc etc etc .

thanks fro the advice but the circuit has the run on batteries since i want it to be mobile and i want it to be pretty small

iA2K:
During those 4 secs even if there was light i want the chip to do nothing (that is the idea of my circuit)

Isn't it already doing that?

I don't understand what the problem is.

I believe that once it is in SLEEP mode , only an interrupt on pin-2 (INT0) can wake it up. You need to modify the circuit to change the state on pin-2 when light is detected before you can proceed. (it can't run any code when it is asleep)

I believe that once it is in SLEEP mode , only an interrupt on pin-2 (INT0) can wake it up. You need to modify the circuit to change the state on pin-2 when light is detected before you can proceed. (it can't run any code when it is asleep)

So only an interrupt from pin 2 can wake it up? it doesn't work for other pins?
Once again sorry if my questions seem stupid

raschemmel:
I believe that once it is in SLEEP mode , only an interrupt on pin-2 (INT0) can wake it up. You need to modify the circuit to change the state on pin-2 when light is detected before you can proceed. (it can't run any code when it is asleep)

Even if you do that, the difference in total power consumption will be too small to make a difference. A Tiny85 which wakes up for 100 microseconds every 4 seconds is still sleeping for 99.9975% of the time. It's the difference between the battery lasting a year and lasting one year and 13 minutes - simply not worth bothering with.

In fact ... doing it with interrupts might be much worse because you have to leave the light sensors powered up all the time.

This leads to the next question: How much power do the light sensors consume and can you switch them off? If you can't then you're not even looking at the right problem.

iA2K:
So only an interrupt from pin 2 can wake it up? it doesn't work for other pins?

Yes.

Wake-up sources are shown on the first page of the "Power Management and Sleep Modes" section of the datasheet (chapter 7)

Isn't it already doing that?

I don't understand what the problem is.

the problem with the current code is that it checks for light then goes to sleep for 4 secs, then wakes up and checks again then goes to sleep for another 4 secs...and so on ( so if i put a light on it sometimes it won't light up due to that fact that it is in 4 sec sleep mode)

what i want is:
it checks for light and if there is light it will go to sleep for 4secs, then after 4 secs it checks again for light but this time it stays in sleep mode until light is detected. so after the 4 sec sleep it should stay in sleep till light is detected again. as soon as light is detected the led will light then goes back to sleep (think of the 4 sec sleep as a delay)

sorry if my explaining is bad

In fact ... doing it with interrupts might be much worse because you have to leave the light sensors powered up all the time.

This leads to the next question: How much power do the light sensors consume and can you switch them off? If you can't then you're not even looking at the right problem.

I'm starting to see the problem here. I don't think that you can turn of the light sensors because i'm using simple Photocell (CdS photoresistor). so i guess i'm going to just put the system to sleep for 4 secs after it detects light then after it wakes up it will stay awake till it detects light again.

thank you

iA2K:
so i guess i'm going to just put the system to sleep for 4 secs after it detects light then after it wakes up it will stay awake till it detects light again.

??

After it wakes up you can put it back to sleep again whether there's any light or not.

After it wakes up you can put it back to sleep again whether there's any light or not.

and when it's sleep mode how do i wake it up (other than using the timer)?

iA2K:

After it wakes up you can put it back to sleep again whether there's any light or not.

and when it's sleep mode how do i wake it up (other than using the timer)?

Use the timer.

raschemmel:
I believe that once it is in SLEEP mode , only an interrupt on pin-2 (INT0) can wake it up.

From a power down sleep... Level interrupt on INT0#. Pin change interrupts will wake it. The watchdog will wake it.

# Jack Christensen has discovered the documentation is wrong for some (all?) processors. Change interrupt may also work.

From a power down sleep... Level interrupt on INT0#. Pin change interrupts will wake it. The watchdog will wake it.

Jack Christensen has discovered the documentation is wrong for some (all?) processors. Change interrupt may also work.

so i can use INTO# for more than one pin to wake it up?
and can you choose a specific value to wake it up?

Take a look at Jack Christensens demo sleep code

http://forum.arduino.cc/index.php?topic=167467.0