Pages: [1]   Go Down
Author Topic: Any library with delay() implemented by switching to low-power-mode w/ WDT  (Read 569 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 117
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there any simple/easy-to-use library that implements delay() (or similar function, that allows millisecond resolution sleeps), which would switch Arduino to low-power sleep mode. I'd expect it to be implemented using the WDT, to wake up and resume functioning.

br,
-f74
Logged

0
Offline Offline
Shannon Member
****
Karma: 200
Posts: 11694
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The watchdog timer is not very accurate, so it depends what you mean by "millisecond resolution", but it ought to be possible by rewriting the code for delay() or by using something like Jeelabs Sleep class.
Logged

[ I won't respond to messages, use the forum please ]

0
Offline Offline
Full Member
***
Karma: 0
Posts: 117
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks @MarkT. Had only read some fleeting mention of WDT in the scope of low-power operation, and wasn't aware that they aren't very accurate.
Found very useful information here thanks to your reference.

Maybe a dumb question - wondering if the AVR timer (Timer0?) continues ticking, when the system is in low-power mode ? I.e. will the standard Arduino time functions, like -- millis() & micros() return the elapsed time since the sketch started, or they would report elapsed time while system is in full power mode ? If it is the former, i.e. Timer0 ticks even in low-power mode, the Jeenode Sleepy class seems to be a fairly good enough for what I am trying to do. What I would like to do is to sleep as much as possible, not wake up early-enough (and frequently enough) to check for some data-pattern in a patch of memory. That patch gets over-written by noise all the time, and it is critical for me to check for valid data, frequently, lest I miss it.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A writeup on low power modes:

http://www.gammon.com.au/forum/?id=11497

Only IDLE mode keeps Timer 0 running. So in the lower-power modes you won't know elapsed time (without an external clock).

You could implement your own timing with Timer 2 and then use "power save" mode. In fact if you used an interrupt with that, then that is your "watchdog" timer. So just let Timer 2 wake you up at whatever intervals you (reasonably) want.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is an example of what I am talking about:

Code:
#include <avr/sleep.h>

volatile unsigned long ms;

ISR (TIMER2_COMPA_vect)
{
  ++ms;
  digitalWrite (9, !digitalRead (9));
}  // end of TIMER2_COMPA_vect

void setup () {
  
   // reset Timer 2
  TCCR2A = 0;
  TCCR2B = 0;

  // Timer 2 - gives us our 1 mS counting interval
  // 16 MHz clock (62.5 nS per tick) - prescaled by 128
  //  counter increments every 8 uS.
  // So we count 125 of them, giving exactly 1000 uS (1 mS)
  TCCR2A = _BV (WGM21) ;   // CTC mode
  OCR2A  = 124;            // count up to 125  (zero relative!!!!)

  // Timer 2 - interrupt on match (ie. every 1 mS)
  TIMSK2 = _BV (OCIE2A);   // enable Timer2 Interrupt
  TCNT2 = 0;    

  // Reset prescalers
  GTCCR = _BV (PSRASY);        // reset prescaler now
  // start Timer 2
  TCCR2B =  _BV (CS20) | _BV (CS22) ;  // prescaler of 128
  
  pinMode (9, OUTPUT);
} // end of setup

void loop () {
 
  set_sleep_mode (SLEEP_MODE_PWR_SAVE);  
  sleep_enable();
  sleep_cpu ();  
  sleep_disable ();


  // should be here after 1 mS
    
}   // end of loop

This uses an average of around 1.7 mA. However it behaves in a slightly strange way. According to my calculations it should wake up (and leave "loop") every 1 mS, but it actually does it every 2 mS.

With the sleep_cpu() line commented out, it does it every 1 mS. So somehow sleep is causing the clock to run slower. I'm not sure why at this stage. However even as it is, it shows how you can be in low power mode most of the time, but still count elapsed time accurately.
« Last Edit: January 17, 2012, 01:21:23 am by Nick Gammon » Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 199
Posts: 12768
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
According to my calculations it should wake up (and leave "loop") every 1 mS, but it actually does it every 2 mS.

The clock select / BOD fuse settings may be the culprit.  It looks like the delay-from-wake time can be as long as 65ms.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh yeah, lol, it was that.

Well, this modified setup behaves as predicted:

Code:
void setup () {
 
   // reset Timer 2
  TCCR2A = 0;
  TCCR2B = 0;

  TCCR2A = _BV (WGM21) ;   // CTC mode
  OCR2A  = 155;   // zero relative

  // Timer 2 - interrupt on match
  TIMSK2 = _BV (OCIE2A);   // enable Timer2 Interrupt
  TCNT2 = 0;     

  // Reset prescalers
  GTCCR = _BV (PSRASY);        // reset prescaler now
  // start Timer 2
  TCCR2B =  _BV (CS20) | _BV (CS21) | _BV (CS22) ;  // prescaler of 1024
 
  pinMode (9, OUTPUT);
} // end of setup

Theory: 62.5 nS * 1024 * 156 = 9.984 mS. That pretty-much agrees with measured results. In other words, a wake-up 100 times a second. Count those, and you know how much time has elapsed.
Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 199
Posts: 12768
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Oh yeah, lol, it was that.

Seriously?  I was correct?

I ask because there did not appear to be a combination that would explain exactly what you were seeing.  It looks like the possibilities are 3ms to a bit over 4ms or close to 65ms.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Seriously?  I was correct?

Of course. Trying to catch 1 mS interrupts with a 65 mS spool-up time was a bit silly of me. I'm surprised it worked as well as it did. (In fact, that is the mystery - maybe it had a maximum 65 mS start-up time).

Oh well, that will teach me to read the data sheet more closely. smiley-wink

At least it confirms my belief that these things work, as long as you understand exactly what they are supposed to do.
Logged

Pages: [1]   Go Up
Jump to: