Go Down

Topic: Atmega328p Power Saving Techniques (Read 6704 times) previous topic - next topic

fungus



So I'm as confused as ever. Going into sleep mode definitely uses less power (I can measure the difference!) but consumption doesn't seem to be anywhere near as low as it should be.


Did you read my reply #18 ?


Yep. I've done it with/without the programmer, it made no real difference.
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

dc42




So I'm as confused as ever. Going into sleep mode definitely uses less power (I can measure the difference!) but consumption doesn't seem to be anywhere near as low as it should be.


Did you read my reply #18 ?


Yep. I've done it with/without the programmer, it made no real difference.



You've misunderstood my reply, I didn't say anything about the programmer. What have you done to ensure that none of the I/O pins is a floating input?
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

fungus


I don't know what your setup looks like to determine what's wrong. It could be a software issue or hardware issue, such as something wrong with the wiring.


There are no wires, just a chip.


Are you asking how to accurately measure current of the chip using a multi-meter or with the 1M Ohmz method Nick showed?


Any method that works.


Here, follow these steps to get your power readings: http://www.gammon.com.au/forum/?id=11497


Yes, I've done ALL of that.


I was able to get the Attiny85V chip down to pretty low power in the uA as well using these steps.


Question is: How do you know? How do you measure it?

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

fungus

#48
Apr 25, 2013, 01:05 pm Last Edit: Apr 25, 2013, 05:45 pm by fungus Reason: 1

You've misunderstood my reply, I didn't say anything about the programmer. What have you done to ensure that none of the I/O pins is a floating input?


I set them to input with pullup resistors. I also set DIDR0 to all 1s for good measure.

Here's the complete sketch I'm using at the moment:

Code: [Select]

#include <Arduino.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/cpufunc.h>
#include <util/delay.h>

/*================================================================
 Go to sleep for 4 seconds
================================================================*/
// Watchdog interrupt vector
ISR (WDT_vect)
{
 WDTCR &= ~(1<<WDIE);    // Disable the watchdog interrupt
}

void doSleep()
{
 // Set watchdog time to 4 seconds
 cli();
 byte b = (1<<WDE)|(1<<WDP3)|(0<<WDP2)|(0<<WDP1)|(0<<WDP0);
 WDTCR = b;
 WDTCR = b|(1<<WDIE);    // Enable watchdog interrupt (this wakes me up!)
 wdt_reset();
 // sleep
 sei();
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 sleep_mode();
}

/*================================================================
 Main program
================================================================*/
void setup()
{
 power_all_disable();
 // All pins input with pullups
 DDRB = 0;
 PORTB = 0x1f;
 // Do these achieve anything? They don't seem to...
 ADCSRA = 0;
 DIDR0 = 0x3c;
}

// Alternate between sleep/work (the reading on the multimeter will switch every 4s...)
void loop()
{
 // Sleep for 4s
 doSleep();
 // Work for 4s
 _delay_ms(4000);
}



With a 10k resistor in series with the 5V supply the voltage across the resistor changes between 2.2V (sleep mode) and 3.6V (in _delay_ms()). That corresponds to currents of 220uA and 360uA - two orders of magnitude more than what I should be getting.
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

fungus

#49
Apr 25, 2013, 01:14 pm Last Edit: Apr 25, 2013, 01:59 pm by fungus Reason: 1

...with the 1M Ohmz method Nick showed?


Aside: I don't understand that method. With a 1M resistor on a 5V supply you can never measure than 5uA no matter what the chip is doing. It's Ohms law.
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

fungus

This is the complete circuit I'm using to get the 2.2/3.6V readings:

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

dc42

Try adding a 0.1uF decoupling capacitor between the Vcc and ground pins of the chip. Without it, the chip may misbehave.

btw I just found this in the attiny datasheet:

Quote
10.2.5 Digital Input Enable and Sleep Modes
As shown in Figure 10-2, the digital input signal can be clamped to ground at the input of the
schmitt-trigger. The signal denoted SLEEP in the figure, is set by the MCU Sleep Controller in
Power-down mode to avoid high power consumption if some input signals are left floating, or
have an analog signal level close to VCC/2.
SLEEP is overridden for port pins enabled as external interrupt pins. If the external interrupt
request is not enabled, SLEEP is active also for these pins. SLEEP is also overridden by various
other alternate functions as described in "Alternate Port Functions" on page 59.


So it looks like setting the pins to inputs with pullups enabled isn't necessary on the attiny. It might even be worth trying without the internal pullups enabled.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

fungus

#52
Apr 25, 2013, 02:59 pm Last Edit: Apr 25, 2013, 03:14 pm by fungus Reason: 1

Try adding a 0.1uF decoupling capacitor between the Vcc and ground pins of the chip. Without it, the chip may misbehave.


I was actually doing most of the tests in the little PCB shown below which has a capacitor. The breadboard was a paranoia test. :)

(No, there's no difference in readings...)


btw I just found this in the attiny datasheet:

...

So it looks like setting the pins to inputs with pullups enabled isn't necessary on the attiny. It might even be worth trying without the internal pullups enabled.


I just tried it...maybe a tiny bit lower without pullups, but background noise level.

There's a definite difference between sleep/awake (220uA vs. 360uA) so I'm fairly confident that the 'sleep' code is doing something.

This makes me think something is left switched on, something that uses 220uA. I don't know what it might be though, there's only four things you can switch off and I've done all of them (individually, all at once, it's the same).
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

dc42

#53
Apr 25, 2013, 03:20 pm Last Edit: Apr 25, 2013, 03:23 pm by dc42 Reason: 1
I built an attiny-based remote control a while ago, and I seem to be using different sleep code. This is what I use:

Code: [Select]

// Wait for button to be pressed
do
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
if (PORTB & 0b00000100)
{
GIMSK = _BV(INT0);
sleep_enable();
sei();
sleep_cpu();
sleep_disable();
}
sei();
uint32_t now = micros();
while ((micros() - now) < 5000) {}
} while (PORTB & 0b00000100);


Ignore the PORTB stuff, it checks that a button isn't pressed. I can't remember why I used sleep_enable(), sleep_cpu() and sleep_disable() rather than sleep_mode(), but I expect there was a reason (possibly to do with using an interrupt to wake up from sleep mode, but maybe not).

What does the current drop to if you don't use the watchdog?
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

fungus


I built an attiny-based remote control a while ago, and I seem to be using different sleep code. This is what I use:

Code: [Select]

sleep_enable();
sei();
sleep_cpu();
sleep_disable();



The only difference between that and "sleep_mode()" is the "sei()" in the middle.

I tried it but it makes no difference (not really surprising because I powered down all the timers so there's no interrupts.



What does the current drop to if you don't use the watchdog?


If I go to sleep and never wake up? No difference.

The watchdog is designed for this usage, I doubt it's responsible for the 220uA.

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

dc42


The watchdog is designed for this usage, I doubt it's responsible for the 220uA.


It certainly shouldn't be, the datasheet shows the power-down current @ 3V to be about 0.4uA with watchdog enabled and 0.2uA with watchdog disabled.

I might just try this out tonight. What fuse settings are you using? Have you tried it with more than one attiny chip?
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

fungus


I might just try this out tonight. What fuse settings are you using?


My boards.txt has:
Code: [Select]

attiny85.name=ATtiny85 (internal 1 MHz clock)
attiny85.bootloader.low_fuses=0x62
attiny85.bootloader.high_fuses=0xd7
attiny85.bootloader.extended_fuses=0xff
...



Have you tried it with more than one attiny chip?


Yes.

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

tim7

#57
Apr 25, 2013, 06:04 pm Last Edit: Apr 25, 2013, 06:23 pm by tim7 Reason: 1
Are you sure the watchdog is being set correctly?  Normally you need to set WDCE before changing WDE or the prescaler bits.

BTW, after the watchdog interrupt WDIF is cleared automatically (so you don't need to do it in the ISR).  Meanwhile the WDT is still running, and may reset the processor before the 4s delay finishes (not that it matters much in this case).

I also noticed that you're not switching the ADC off after disabling it (power reduction register, PRR).

fungus


Are you sure the watchdog is being set correctly?  Normally you need to set WDCE before changing WDE or the prescaler bits.


Not if the WDTON bit is set in the fuses (bit 4 of fuse high byte)...


BTW, after the watchdog interrupt WDIF is cleared automatically (so you don't need to do it in the ISR).  Meanwhile the WDT is still running, and may reset the processor before the 4s delay finishes (not that it matters much in this case).


This is still a bit mysterious to me. I checked the MCUSR:WRDF flag in setup() but I never had the watchdog cause a reset, only interrupts.

I need to investigate further but I'm more worried about the power consumption at the moment.


I also noticed that you're not switching the ADC off after disabling it (power reduction register, PRR).


The "power_all_disable()" does that.
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

tim7


The "power_all_disable()" does that.


Are you sure?  The datasheet makes a point of saying that the ADC must be disabled (ADCSRA) before being shutdown (PRR).  You commented that disabling the ADC doesn't seem to do anything, but it should make a noticeable difference.

Go Up