Go Down

Topic: Is there a low power mode? (Read 14656 times) previous topic - next topic

chipwich

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.


chipwich

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?

I appreciate the help.

florinc


chipwich

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.  


 

scottmcphee

#5
Oct 29, 2009, 02:04 am Last Edit: Oct 29, 2009, 02:06 am by scottmcphee Reason: 1
I'm looking for something related to sleep modes.  

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.


Advice?


Coding Badly

#6
Oct 29, 2009, 02:24 am Last Edit: Oct 29, 2009, 02:27 am by bcook Reason: 1
Quote
pins to inputs no pullup

No pullup = floating pins = bad

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1243213127/all

Which sleep mode are you using?

scottmcphee

#7
Oct 29, 2009, 03:59 am Last Edit: Oct 29, 2009, 04:02 am by scottmcphee Reason: 1
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.

Coding Badly

#8
Oct 29, 2009, 05:28 am Last Edit: Oct 29, 2009, 05:36 am by bcook Reason: 1
Quote
I think it is good idea to set unconnected pins to an output state, either high or low

For this topic, input w/ pullup has the same result.

Quote
digital write

A high output pin with a load will consume power even when the processor is put to sleep.

Quote
analog read

Obviously, this turns on the analog comparator circuitry which, I believe, has to be explicitly turned off.

Quote
I'm using the deepest sleep

This shuts off all the timers (except the watchdog) so you shouldn't need to worry about the millis, EEPROM, or UART timers.

scottmcphee

Which brings me back to my post in this thread,

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.  

Does anybody know the list of commands?

Regards
Scott

pluggy

#10
Oct 30, 2009, 01:02 pm Last Edit: Oct 30, 2009, 01:13 pm by stephen_t Reason: 1
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....


moriszen

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.

scottmcphee

#13
Sep 07, 2010, 08:49 pm Last Edit: Sep 07, 2010, 09:01 pm by scottmcphee Reason: 1
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!

Code: [Select]


#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


scottmcphee

#14
Sep 07, 2010, 08:58 pm Last Edit: Sep 07, 2010, 09:05 pm by scottmcphee Reason: 1
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.


Code: [Select]


....  (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.

Code: [Select]

void resleep(){
 // quick death by watchdog
 wdt_enable(WDTO_15MS);
 while(1) {
 }  // loop forever, but watchdog will bust this up

Go Up