Go Down

Topic: Arduino and SLEEP_MODE_IDLE (Read 3523 times) previous topic - next topic

totopz

Hello,

I'm newbie with the arduino and with the electronics. But I try to do some projects with my new arduino.

I'm trying to put the arduino to sleep so that his timer0 will stay working and millis() will count. I try to use SLEEP_MODE_IDLE sleep mode, but without big success. I have an arduino standalone on a breadboard and a LED attached to arduino pin 13 (pin 19 on Atmega328). When I execute the code which hate to put arduino on sleep nothing happens. The LED continue to blink and the current consumption is the same.

Here is my sleepNow() function:
Code: [Select]
void sleepNow()
{
  set_sleep_mode(SLEEP_MODE_IDLE);   // sleep mode is set here
 
  sleep_enable();
                             
  attachInterrupt(0,wakeUpNow, LOW);
                             
  power_adc_disable();
  power_spi_disable();
  //power_timer0_disable();            //millis() clock
  power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();
                                       
  sleep_mode();

  //Wake up
  sleep_disable();

  power_adc_enable();
  power_spi_enable();
  power_timer1_enable();
  power_timer2_enable();
  power_twi_enable(); 

                           
  detachInterrupt(0);
}


If I uncomment the line
Code: [Select]
//power_timer0_disable();            //millis() clock
arduino is going to sleep, but in this case millis() are not working.

I'm using 12V DC with 7805 regulator. Here are my current measurements on +12V line:
7805 itself is using round 5 mA
LED ON - round 29 mA
LED OFF - 21 mA

After sleepNow() is called the current remain the same. If I uncomment the line
Code: [Select]
//power_timer0_disable();            //millis() clock
when arduino sleeps the consumption is round 11 mA.

Can you help me and tell me what I'm doing wrong and what exactly have to do to put arduino on sleep in SLEEP_MODE_IDLE and millis() function to work?

bHogan

#1
Jan 27, 2011, 04:47 pm Last Edit: Jan 27, 2011, 04:49 pm by BroHogan Reason: 1
Why do you need millis() to run in sleep mode?
If it's to wake up at a certain interval, the watchdog timer is generally used for that.

Here's a link that may be helpful . . .
http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

totopz

Thank you about the link. I will review it.

Actually I'm not sure whether I will use millis(), but I wonder why my code is not working. I just want to put arduino on sleep with working millis() and to measure consummated current. Then I will decide whether to use SLEEP_MODE_IDLE or some other sleep mode.

Coding Badly

Quote
The LED continue to blink and the current consumption is the same.


The processor sleeps until an interrupt occurs.  Timer 0 generates an interrupt roughly every millisecond.  Basically, the processor is taking very short naps.

The LED blinks because the processor wakes every millisecond.

With the current consumption changing so quickly it can be difficult to measure with a multimeter.  I use a "battery drain" test in these circumstances.

totopz

Coding, thank you about the explanation. Now I understand what happens.

In this case SLEEP_MODE_IDLE and millis() can't be used together? Or the processor will sleep and will wake up each 1 second and this will result in low power consumption?

Maybe I have to implement WDT interrupt and to wake up on each 8 seconds. I have to count big periods of time like an hour, 2.5 hours, etc...in that case I think WDT inaccuracy will not be big problem for me.

Actually I'm trying to do something like car board computer and I want it to resets itself if the vehicle is not running for user defined time. The time can be set in half hour steps. I want my device to be powered on always even when the vehicle is not running and I need low power consumption otherwise my device will discharge the battery really fast.

Coding Badly

In this case SLEEP_MODE_IDLE and millis() can't be used together?


They can be used together.  It's just that the processor takes short naps.  It does actually help extend battery life.

Quote
Or the processor will sleep and will wake up each 1 millissecond and this will result in low power consumption?


Everything you do to save power helps.  Even short naps.

Quote
Maybe I have to implement WDT interrupt and to wake up on each 8 seconds.


That certainly works.  Bear in mind that the watchdog timer clock rate varies by voltage and temperature.  When you sleep for "8 seconds" the actual time could be 8.1867 seconds or 7.9881 seconds or anything else around 8 seconds.

Quote
I have to count big periods of time like an hour, 2.5 hours, etc...in that case I think WDT inaccuracy will not be big problem for me.


For minimizing power consumption, the "power down" sleep mode with the watchdog timer is very difficult to beat.

Quote
Actually I'm trying to do something like car board computer and I want it to resets itself if the vehicle is not running for user defined time. The time can be set in half hour steps. I want my device to be powered on always even when the vehicle is not running and I need low power consumption otherwise my device will discharge the battery really fast.


Sounds like power down + watchdog is a good choice.  Just bear in mind that the processor clock is stopped in power down mode.  Only "asynchronous interrupts" and the watchdog timer will wake it.

You should also consider using a lower voltage and a lower clock speed.

totopz

I implemented WDT wake up after 8 seconds logic and here are my results:

When in SLEEP_MODE_PWR_DOWN the current is only 5.8 mA
Even if I disconnect the Atmega328 from 7805 regulator there are 5.4 mA
When wake up the current is round 20-21 mA

I'm happy with these results. I think on 44 Ah battery this 5.8 mA are small load and will not discharge the battery quickly.

About the WDT accuracy I will calculate the worst case (8.1867 seconds instead of 8 sec):
60 / 8 = 7.5 times WDT will overflow for a minute
7.5 * 0.1867 = 1.40025
there are 1.4 seconds error on each minute

If my calculations are correct we have:
For an hour the error will be 60 * 1.4 = 84 seconds.
For 10 hours the error will be 14 minutes.
I think in my case the error is not a problem.

Coding Badly

When in SLEEP_MODE_PWR_DOWN the current is only 5.8 mA
Even if I disconnect the Atmega328 from 7805 regulator there are 5.4 mA
When wake up the current is round 20-21 mA


It is possible to do much better.  But it requires work to get there.

Quote
About the WDT accuracy I will calculate the worst case (8.1867 seconds instead of 8 sec):


I should have mentioned that the "8.1867" value was obtained by poking random characters on my keyboard.  You will have to measure the sleep time to determine what it is for your processor (there are manufacturing variations).

totopz

Quote
It is possible to do much better.  But it requires work to get there.

I'm newbie in the electronics and my knowledges are ending with the using of 7805 as 5 volts voltage regulator. I think there is nothing more that I have to do with the arduino. If I have to do something better I have to work on 7805 regulator high power consumption.

I did a little program to measure the WDT overflow period with prescaler set for 8 seconds:
Code: [Select]
void loop()
{
  if (resetTimeWDT == 0) {
    wdt_reset();
    resetTimeWDT = micros();
  }
 
  if (overflowWDT > 0) {
    Serial.println(overflowWDT - resetTimeWDT);
   
    overflowWDT = 0;
    resetTimeWDT = 0;
  }
}

ISR(WDT_vect)
{
  overflowWDT = micros();
}


Here are some of the results:
8690588
8690084
8689688
8690220
8689876
8689576

So you are right. WDT accuracy is really bad. Maybe I have to calibrate it somehow in each 10 or 30 minutes.

Coding Badly

The spread on those values is 0.012%.  At ten minuts that's a range of 0.07 seconds.  At 30 minutes that's a range of 0.21 seconds.  For one day that's a range of ten seconds.

How accurate do you need?

totopz

For one day that's a range of ten seconds.

It is very well for my project.
I need to reset some variables after an hour or after 10, 20 hours...in each case the error is too small to be a problem.

Go Up