Re: Watchdog Timer & ATtiny85

Hi everyone

I’m starting to play with a ATtiny85, and what I wanted this little guy to do is a very simple task, yet I’m having a difficult time making it happen. All I want is have the ATtiny85 run from a 3.7v lipo in order to blink an LED (connected to pin 0) just once (on for only 1 sec), and then have the ATtiny85 go to sleep for 1 hour (using the Watchdog Timer). After the 1hr, it would wake itself up and start the process all over again.

One of the things that I would like is to minimize as much as possible the power consumption so that the battery lasts longer, and therefore:

  1. making the AT sleep in “power down mode”
  2. disable the peripherals that are not being used
  3. disable the brown-out protection
  4. no need to change the clock speed yet (unless it is super easy & safe) :slight_smile:

I’ve looked online at many excellent examples in order to try implementing this in my own ATtiny85, but I find them a bit confusing because either the articles were written with an ATmega328 in mind, or in some cases (e.g.: http://www.surprisingedge.com/low-power-atmegatiny-with-watchdog-timer/), the author just shows “pieces” of the code, making it hard for a “noob” like me to reconstruct.

Anyone has any thoughts & suggestions on how I could make my ATtiny85 work as I need it?

I’ve tried working of some examples to “try” to get on the right track. Here’s what I have so far, but it only sleeps for 9 seconds (as a test, in the script I’m trying to make it sleep for 18 sec). I wonder if I should start from scratch?

Any advice & suggestions would be really helpful… thanks! :slight_smile:

#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 = 0;
volatile boolean f_wdt = 1;

void setup(){
  pinMode(pinLed,OUTPUT);
  setup_watchdog(9); // approximately 8 seconds sleep 
}


void loop(){
  //=============SLEEP ROUTINES========================================================================
  for (int myLoop= 0; myLoop < 2; myLoop++) // loop around and give delay of 2 * 9sec = 18 sec 

  {

  if (
  f_wdt==1) {  // wait for timed out watchdog / flag is set when a watchdog timeout occurs
    f_wdt=0;       // reset flag

    digitalWrite(pinLed,HIGH);  // let led blink
    delay(1000);
    digitalWrite(pinLed,LOW);

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

}


// 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
}

Basic ATtiny85 sleep code: https://gist.github.com/JChristensen/5616922

An ATtiny85 project that sleeps in power-down mode, uses the watchdog timer to wake every 8 seconds (this is the maximum), and either goes back to sleep, or flashes some LEDs at random intervals: https://github.com/JChristensen/millionOhms_SW

HTH

Awesome info. I was looking at the sketch you made for making the LED light for 10 seconds, and have the ATtiny85 go to sleep when a button is pushed (https://gist.github.com/JChristensen/5616922).

I've been reading through it, though, but I can't figure out what I need to change in order to substitute the "push button" action so as to make the ATtiny85 sleep for 18 sec (equivalent to 2 8-second cycles), wake up, flash the LED for 10 seconds, and then go back to sleep.

Any suggestions on how I could change this? Thanks

Did you check the second link? It uses the watchdog to sleep for some random amount of time, between about 10 and 30 minutes. So the watchdog wakes the MCU every 8 seconds. Every time it wakes it increments a counter, and if it's not time to wake up it just goes back to sleep. This is fast and takes almost no power.

I might modify the gotoSleep() function to accept an argument which is the number of seconds (or number of watchdog periods) to sleep. Dispense with the random business, and that will simplify things.

I see... I will check the sketch out and amend as needed. Thanks again for the advice! This is just the info I was looking for :)

Have fun and let us know if you get stuck.