Hi. I'm new to arduino, having moved this direction from Picaxe projects. On the Picaxe, my project were often solar powered. And even for the battery powered projects, I almost never used an on/off switch since I could place the device in sleep mode (using nanowatts) and occasionally do a button check to see if I should power-up again.
The Arduino seems to be more power hungy, with little attention paid to power saving sleep/nap modes, underclocking, brownout fuse bypass, etc. I'd like to be able to do small solar powered projects and use device on-off via software instead of a swtich. Am I missing something in this area? Are very low-power applications possible? Thanks.
Thank you for the reference. It's nice to know that the device can power down to 1 uA if the design permits it.
Unfortunately, my arduino boards (all boards?) are based on a 16MHz clock so there's considerably increased power consumption right there. I can change out the clock crystal, but that would almost definitely break the serial communications including IDE downloads.
It also doesn't look like the sleep modes, the brownout fuse disable, and other power saving features are exposed to the programmer using the standard arduino IDE. Are they?
Thanks! It's a little cumbersome, but the nightingale example looks quite workable as a method of using the watchdog timer to wake up the device. I suppose that explicitly (re)setting the watchdog timer before each sleep provides a method of making the device sleep for X milliseconds upon request.
I'd like to know the list of Arduino commands that I can execute just prior to a sleep, to know (guarantee) that all features, devices, and pins I've used in the program get return to the default / idle / off state.
Why? I have built a battery powered application that has a strange power consumption. I have built a target board, so now the chip is not socketed onto Arduino board, but rather my board. When I apply power, the program starts, which is to setup both external interrupt buttons to input w/ pullup, then sleep. The idle consumption in this state is 0.11 mA. It stays this way until one of the interrupt buttons (I use both) is pressed, then it goes into action and transmits over a radio, spiking up to 45mA when doing that, then I sleep the radio (it's active low), and change all the atmega pins to inputs no pullup, except for pullups on the interrupt buttons... Then I call a reset routine (jump to address 0). Now, power consumption is 0.29mA, and it doesn't drop below that. The cycle can be repeated of pushing buttons, spike, settle... but never again down to 0.11mA. Unless I remove power from the board, and reapply... then it starts at 0.11mA
So, I'd like to run all commands necessary to force the chip into the state it was in when power was first applied. I'll run these commands as the last step before I call the reset routine - that promptly leads to a sleep.
First thing to know is I don't use any bootloader so it can't potentially be mucking with pins, it's just my main program flashed directly into chip using a programmer. It's just my code.
AVR chip power on default is pin = input no pullup. (Hi-Z state).
And with a fresh power on the only pins I change are two inputs, I apply the internal pullups, and I get 0.11mA. I'd be happy with this consumption. Better is better, but .. that's good enough.
I think it is good idea to set unconnected pins to an output state, either high or low. The only risk is accidental short of something on the board, touching a pin, and the MCU trying to sink or source current into that short.
I can play around with pin mode and see if my current consumption can be hammered down, but I was also wondering if there are on-chip features that start consuming power that I could intentionally power down.
In my program I use, digital read/write of course, and analog read, and analog write, shift out, I read millis, I use EEPROM, serial read and write (UART), ... just wonder if some of these Arduino commands have compiled in power enabling features that I should manually power off.
And to answer your question, I'm using the deepest sleep, that only an external interrupt pin can wake up.
I'd like to know the list of Arduino commands that I can execute just prior to a sleep, to know (guarantee) that all features, devices, and pins I've used in the program get return to the default / idle / off state.
I'd be tempted to use a PICAXE to switch the power on and off to the Arduino. You'd only need an 8 pin cheapo with a transistor to switch the current. The basic sleep mode on the picaxe 08 is a few tens of microamps and less than a milliamp fully running. Its not like they are expensive....
Scott ,
I am too attempting to make a battery powered Atmega device (I removed it from the Arduino like you so I don't waist the power on the 7805) and I am ruining at 3.3V.
The thing is that I want to track time correctly (I am using the TIME libraries and I want to "wake up" and log events with their correct time but I notice I loose track of time when in sleep mode.
Thanks again
Moris.
Here are relevant parts of code for how I achieved 3.9uA current consumption for a mega 328P based design (chip is placed on its own PCB, not in any Arduino board). 3.9uA IS AS GOOD AS IT GETS for resting design so I'm happy!
Application is a remote transmitter, has no power switch, just two buttons. Sleeps until a button is pressed... does it job (transmits) then goes to sleep again.
Runs off 3 x AA batteries, and spends most of its time doing nothing, so basically the unit has power for the shelf life of the batteries!
#include <avr/sleep.h>
#include <avr/wdt.h>
void buttonRedInt() {
signalBits = B00100000 ;
// there is no return for functions attached to an interrupt, they get RETI inserted
}
void buttonGreenInt() {
signalBits = B10000000 ;
}
void setup() {
noInterrupts();
// turn off watchdog, prevent interrupting, don't change order of anything in this block of code:
wdt_reset();
MCUSR = 0;
WDTCSR |= _BV(WDCE) | _BV(WDE);
WDTCSR = 0;
// change button I/O pins to input w/pullups
pinMode(buttonRed, INPUT);
digitalWrite(buttonRed, HIGH); // enable internal pullup
pinMode(buttonGreen, INPUT);
digitalWrite(buttonGreen, HIGH);
// set I/O pins to a state with least power consumed, this will depend on your h/w design
DDRD = 0b00010000 ; // direction 0 input
PORTD = 0b11101111 ; // 1 pullups
DDRB = 0b00000000 ;
PORTB = 0b11111111 ;
DDRC = 0x00 ;
PORTC = 0xFF ;
// turn OFF analog parts
ACSR = ACSR & 0b11110111 ; // clearing ACIE prevent analog interupts happening during next command
ACSR = ACSR | 0b10000000 ; // set ACD bit powers off analog comparator
ADCSRA = ADCSRA & 0b01111111 ; // clearing ADEN turns off analog digital converter
PRR = PRR | 0b00000001 ; // set PRADC shuts down power to analog digital converter
/* Now it is time to enable an interrupt. In the function call
* attachInterrupt(A, B, C)
* A can be either 0 or 1 for interrupts on pin 2 or 3.
*
* B Name of a function you want to execute while in interrupt A.
*
* C Trigger mode of the interrupt pin. can be:
* LOW a low level trigger
* CHANGE a change in level trigger
* RISING a rising edge of a level trigger
* FALLING a falling edge of a level trigger
*
* In all but the IDLE sleep modes only LOW can be used.
*/
attachInterrupt(0, buttonRedInt, LOW);
attachInterrupt(1, buttonGreenInt, LOW);
/* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*/
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable(); // enables sleep bit in mcucr register, a safety pin
interrupts();
sleep_mode(); // here the device is actually goes to sleep, saving power
Here's the code after the sleep statement that shows the house keeping for waking up... continuing from previous post in this thread.
Note, I found the 328P waking up by itself when waving hands over the PCB, etc. Even after ensuring solid pullup resistors were attached to the I/O pins associated with the low level interrupts having the buttons on them. This was too flaky for belief, so I solved the problem using standard software debounce methods. Phantom button presses did not endure long enough (delay 5)... so the program just went back to sleep for those cases.
.... (within setup)
sleep_mode(); // here the device is actually goes to sleep, saving power
// THE PROGRAM CONTINUES HERE AFTER WAKING UP and running the attached interrupt routine.
// first thing after waking from sleep is disable sleep interrupts
noInterrupts();
sleep_disable();
detachInterrupt(0);
detachInterrupt(1);
interrupts();
// de-bounce / double-check here that button is still being pressed
delay(5); // bit of debounce time
if ( signalBits == B00100000 ) { // red button was pressed
if ( digitalRead(buttonRed) != LOW ) resleep(); // double check
if ( digitalRead(buttonRed) != LOW ) resleep(); // triple check
}
else if ( signalBits == B10000000 ) { // green button was pressed
if ( digitalRead(buttonGreen) != LOW ) resleep(); // double check
if ( digitalRead(buttonGreen) != LOW ) resleep(); // triple check
}
else resleep(); // transient interrupt didn't last as long as startup time, no button was pressed!
// I use the ADC, so I re-power the analog digital converter portion of MCU to get ready to read a POT
PRR = PRR & 0b11111110 ; // clear PRADC bit powers up this section of chip
ADCSRA = ADCSRA | 0b10000000 ; // set ADEN enables analog digital converter
.... (now do the real work of what your program is supposed to do)
And here's the resleep() routine, surprise, just sicks the watchdog to force a reset... and the setup begins again, going to sleep.
void resleep(){
// quick death by watchdog
wdt_enable(WDTO_15MS);
while(1) {
} // loop forever, but watchdog will bust this up
Even after ensuring solid pullup resistors were attached to the I/O pins....
I have not looked it up, but I suspect the internal pull-ups will no longer be powered in deep sleep mode. However this does not explain the situation with "solid" pull-ups....
Note, I found the 328P waking up by itself when waving hands over the PCB, etc
The UART may need to be disabled / powered-off. I can't remember if the startup code always initializes the UART or only initializes it when Serial.begin is called. That may explain the unexpected waking.
Runs off 3 x AA batteries
You can lower the full-power consumption considerably by running at a lower voltage. You will also have to run at a lower clock frequency. (8MHz internal oscaillator / 3V seems to be a nice sweet spot)
3.9uA current consumption
Seems a bit high to me (but still very good). I was able to get the sleep consumption below 2uA (the limit of my meter). The datasheet claims 1uA and I believe that to be accurate.
I suspect the internal pull-ups will no longer be powered in deep sleep mode