Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Entire forum
➜ Electronics
➜ Microprocessors
➜ Saving power
Postings by administrators only.
Refresh page
Posted by
| Nick Gammon
Australia (23,120 posts) Bio
Forum Administrator |
Date
| Mon 30 May 2011 06:18 AM (UTC) Amended on Sat 14 Jan 2012 09:52 PM (UTC) by Nick Gammon
|
Message
| I had a question on the Arduino forum about saving power for a battery-powered chip mounted in a hard-to-get-at place.
Apart from suggesting a larger battery, the code below shows how you can make the processor go into a "power down" sleep, and let the watchdog timer wake it up some seconds later.
This code also illustrates polling a DS1307 clock chip to find the time of day. The idea being (in this case) that you might only want to do something during business hours (or daytime, or nighttime or whatever). So by checking the time you work out whether we need to do whatever-it-is right now.
To save power the clock itself is powered from a digital pin (pin 5 in this case) so we turn the clock on by setting pin 5 high, read the time, and then power it down again. The clock board itself has a small battery on it which lets it remember the time over something like 10 years.
This is my example board, with the clock mounted:
That board is described here:
http://www.gammon.com.au/forum/?id=11109
This is the sketch:
// Example of sleeping and saving power, and reading a clock
//
// Author: Nick Gammon
// Date: 25 May 2011
#include <Wire.h>
#include "RTClib.h"
#include <avr/sleep.h>
#include <avr/wdt.h>
RTC_DS1307 RTC;
#define CLOCK_POWER 5
#define LED 13
// watchdog interrupt
ISR(WDT_vect) {
wdt_disable(); // disable watchdog
}
void myWatchdogEnable(const byte interval) { // turn on watchdog timer; interrupt mode every 2.0s
MCUSR = 0; // reset various flags
WDTCSR |= 0b00011000; // see docs, set WDCE, WDE
WDTCSR = 0b01000000 | interval; // set WDIE, and appropriate delay
wdt_reset();
byte adcsra_save = ADCSRA;
byte prr_save = PRR;
// disable ADC
ADCSRA = 0;
// power reduction register
// Bit 7 - PRTWI: Power Reduction TWI
// Bit 6 - PRTIM2: Power Reduction Timer/Counter2
// Bit 5 - PRTIM0: Power Reduction Timer/Counter0
// Bit 4 - Res: Reserved bit
// Bit 3 - PRTIM1: Power Reduction Timer/Counter1
// Bit 2 - PRSPI: Power Reduction Serial Peripheral Interface
// Bit 1 - PRUSART0: Power Reduction USART0
// Bit 0 - PRADC: Power Reduction ADC
// turn off various modules
PRR = 0b11101111;
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_mode(); // now goes to Sleep and waits for the interrupt
// stop power reduction
ADCSRA = adcsra_save;
PRR = prr_save;
}
void setup()
{
pinMode (CLOCK_POWER, OUTPUT);
digitalWrite (CLOCK_POWER, HIGH); // power up clock
delay (1);
Wire.begin();
RTC.begin();
// set time in clock chip if not set before
if (! RTC.isrunning()) {
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
digitalWrite (CLOCK_POWER, LOW); // power down clock
} // end of setup
void loop()
{
// power up clock
digitalWrite (CLOCK_POWER, HIGH); // power up clock
delay (1); // give it time to stabilize
// activate I2C and clock
Wire.begin();
RTC.begin();
// find the time
DateTime now = RTC.now();
// time now available in now.hour(), now.minute() etc.
// finished with clock
digitalWrite (CLOCK_POWER, LOW);
// turn off I2C pull-ups
digitalWrite (A4, LOW);
digitalWrite (A5, LOW);
// turn off I2C
TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
// -------- do something here if required by the time of day
// in my case flash an LED for 5 seconds
pinMode (LED, OUTPUT);
digitalWrite (LED, HIGH);
delay (5000);
digitalWrite (LED, LOW);
// sleep bit patterns:
// 1 second: 0b000110
// 2 seconds: 0b000111
// 4 seconds: 0b100000
// 8 seconds: 0b100001
// sleep for a total of 20 seconds
myWatchdogEnable (0b100001); // 8 seconds
myWatchdogEnable (0b100001); // 8 seconds
myWatchdogEnable (0b100000); // 4 seconds
} // end of loop
It uses about 19 mA when awake (some of which would be the LED) but only 25 uA (0.025 mA) when asleep. 25 uA isn't much, and would not drain your battery very quickly.
Measurements indicate that the clock chip was powered up for 2 ms (1 one of which was the delay for it to get ready) so that means that (during the 8 second cycles) the higher power consumption only applied for 1/4000 of the duty cycle.
[EDIT] Further tests show that if you disable the brown-out detection (by changing a fuse byte) you can greatly save power, especially in sleep mode. With brown-out detection disabled power consumption goes down to around 6 uA. This is because the brown-out detection needs an internal voltage reference to be running.
For more information about power saving:
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| David DeFilippis
(4 posts) Bio
|
Date
| Reply #1 on Fri 02 Dec 2011 07:59 PM (UTC) |
Message
| I cannot get this code to compile to an Arduino Mega 2560. The board runs on the Amtel ATmega2560. I do not have a lot of experience in computer sciences but I am assuming that the avr/wdt.h library doesn't cover this chip. If there is any advice or help that you could give me it would be greatly appreciated.
here is a link to the chip's datasheet http://www.atmel.com/dyn/resources/prod_documents/doc2549.PDF
here is the error that I get from the compiler
sketch_dec02a.cpp: In function 'void myWatchdogEnable(byte)':
sketch_dec02a:30: error: 'PRR' was not declared in this scope
Thank you for your time,
David DeFilippis | Top |
|
Posted by
| Nick Gammon
Australia (23,120 posts) Bio
Forum Administrator |
Date
| Reply #2 on Sat 03 Dec 2011 09:01 AM (UTC) |
Message
| Did you search the data sheet for PRR? It looks like the 2560 has PRR0 and PRR1 (because it has more things in it).
By the looks of it, PRR0 has the same functionality of PRR on the smaller chips. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
23,920 views.
Postings by administrators only.
Refresh page
top