Help with Low Power Sleep Mode on Atmega328P

While I try and fathom out this problem myself, I thought I would post here to see if anyone has any ideas.

I am trying to put my Atmega328P IC to Sleep using the LowPower.H library and calling this function at the end of the program loop to put the Atmega to sleep for 16 seconds at a time.

// LOW POWER SLEEP FUNCTION - PUTS THE SYSTEM TO SLEEP WHEN NOT IN USE TO SAVE POWER!
  void sleepTime(){
    for (int i = 0; i < 2; i++) { 
       LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); //PowerDown
    }
  }

However, this isn't working as expected...

When I first power up my project, I get a really low current consumption of around 190uA. On my Multimeter, I can see the Atmega periodically waking and going back to sleep with a momentary increase in current consumption to around 2 - 4mA before it drops back to 190uA when it goes back to sleep.

The problem comes when the Atmega has to do something and then go back sleep. What happens here is, the Atmega wakes up, performs its task but then instead of dropping back to using 190uA, it sits drawing more like 4mA - almost like it isn't going back to sleep except I can still see the multimeter fluctuating every 16 seconds indicating the sleep function is being called but it doesn't seem to be working as effectively.

I thought it might be down to pin states but I've checked and I am setting all the pins back to their starting states after the atmega performs it's actions and goes back to sleep so I'm at a loss.

Anyone else experienced this?

Thanks!

Please read the forum guidelines in the sticky post.

(deleted)

Look at this. It is the definitive guide to Arduino Low Power. Set yourself the task of achieving low power using native AVR register settings instead of using libraries then you'll understand much better what is going on in the background.

In your case, there could be something either (a) preventing it going into sleep mode or (b) an external interrupt continually waking it.

My guess is (c) a pin is configured as output and powering something. Or (d) when ATMega wakes up it turns on some other hardware which eats this extra power.

Hi,

I think I've solved or am a good way towards solving this problem now - thanks to all the help, ideas, suggestions!

Basically, I have another problem with my circuit which I thought was unrelated, so I made a separate post about it in the appropriate forum: Paracitic Voltage Drain From Atmega Serial to Module? - General Electronics - Arduino Forum

I was noticing that despite a module in my circuit not being powered up, I was still seeing a small voltage on the module's VCC pin (around 0.2 - 0.9V) which I concluded was being drained from the Serial pin on the Atmega.

The replies in this post and the other post I made linked above swirled around in my head and I started to think that the two problems were probably related and it looks like they are.

Spycatcher2k was bang on the money with his notion that the problem was in my code.

6v6gt also inspired me by linking me to Nick Gammon's forum (I have been over it before with a fine toothed comb but it gave me an idea about writing all the pins to output low in the setup function - I will elaborate more later....

Smajdalf was also correct with their suggestion too!

CONCLUSION:

I did a small experiment using this segment of code I remembered seeing on Nick Gammon's website (which 6v6gt jogged my memory with) in my Setup function. I removed everything that was in Setup including Serial.Begin calls and replaced it with just this.

// WRITE ALL PINS AS OUTPUT LOW UNTIL NEEDED - DEFAULT STARTING STATE - ALLOWS LOW POWER SLEEP - PIN STATES CHANGED LOCALLY AS REQUIRED - MUST WRITE BACK TO OUTPUT LOW BEFORE SLEEP!
    for (byte i = 0; i <= A5; i++){
      pinMode (i, OUTPUT);    // changed as per below
      digitalWrite (i, LOW);  //     ditto
    }

Then in my main code, I only change the pin modes and I/O states as required and then write them back to OUTPUT LOW after use.

Smajdalf mentioned the use of Serial.End in the other thread I linked to above which then got me further thinking...... I went on and looked up Serial End and then the penny dropped... I can't disable / turn off the serial ports until they're regular I/O pins.

So with that in mind, I altered my main code so that I call Serial.Begin just before I need to use it. Then when everything is done, I call Serial.end, then I call on the code above to put all the pins back to OUTPUT LOW and THEN put the Atmega to sleep.

So now, when I first power up my project, it drops straight to 360uA in standby.
Then when it's time to wake up modules and go back sleep, it does go back to 360uA......

BUT, now it does something rather odd before going back sleep. It drops to 190uA (where it should be all the while) and then after 20 seconds or so, it returns to 360uA where it stays.

So further investigation is required there but I am getting closer so thank you for all the suggestions and help. I am a lot nearer to solving it than I was a few days ago :slight_smile:

Instead of OUTPUT LOW, configure the pins as INPUT. I think this time you are fighting a pull-up resistor somewhere. You should have defined levels on all pins while awake but it is no problem to let pins float as they wish in sleep. Ofc for "final product" it is better to find which pins are truly unused and configure them INPUT_PULLUP. Or disable digital buffering (only "analog" pins have this feature).

Smajdalf:
Instead of OUTPUT LOW, configure the pins as INPUT. I think this time you are fighting a pull-up resistor somewhere. You should have defined levels on all pins while awake but it is no problem to let pins float as they wish in sleep. Ofc for "final product" it is better to find which pins are truly unused and configure them INPUT_PULLUP. Or disable digital buffering (only "analog" pins have this feature).

Thank you smajdalf, I will investigate those changes and see what happens.
I'm just enjoying a well deserved, celebratory tea break hehe.

Smajdalf:
I think this time you are fighting a pull-up resistor somewhere.

You are bang on the money again Smajdalf!

I tried setting the starting state of the pins to inputs, but that wasn't well received. My standby current shot up to over 10mA so I reverted them back to outputs to get back to my 360uA standby current.

Then what you said about fighting pull up resistors resonated with something in my brain and I remembered that I've got two pull ups in my circuit, one for A4 and one for A5 (SDA and SCL) for my RTC.

The clock gets its power from a Digital Pin on the Atmega which I enable to briefly take the time between sleep calls and then disable again. But I tied the SDA and SCL to the 3V3 line via 10K pullups.

What was happening was the Atmega was waking up, doing its tasks and then writing all the pins low but when the clock function got called, it left the SDA and SCL pins HIGH because I'd forgotten to write them low after use.

Now I've changed the clock function to write SDA and SCL pins LOW after each use, I'm back to a nice 190uA standby current consistently and everything still works as it should (Serial comms, Modules, RTC etc). YAY

190uA is still a lot higher than was predicted when designing my power system, I was actually expecting to be nearer 100uA or less but it's better than the 7mA I started out with initally when designing my project. So I'll take what I can get at this point in time. The important thing is it's stable and it's consistent and on a 7Ah battery, I should see far more standby time than I'll probably likely need.

I estimate (7000mAh / 0.2uA) / 24 = 35,000 Days (almost 4 years) not taking in self discharge, battery efficiency etc in to account. A year would be adequate for my needs so I seem to have blown that target out of the water and am very happy :slight_smile:

Thank you to everyone that's helped me out here, I really appreciate it. I likely wouldn't have worked it out without talking it through with everyone concerned here - or if I had it would have taken considerably longer!

Many thanks!!!!!

Try to NOT pull the I2C lines. ATMega should have sleep current well below 10uA. Maybe ATMega either drains some current from RTC's pull-ups or it keeps RTC's I2C state machine in some active state consuming additional power - idle state for I2C lines is HIGH, not LOW.

Smajdalf:
Try to NOT pull the I2C lines. ATMega should have sleep current well below 10uA. Maybe ATMega either drains some current from RTC's pull-ups or it keeps RTC's I2C state machine in some active state consuming additional power - idle state for I2C lines is HIGH, not LOW.

Hi and thanks for replying Smajdalf.

Maybe it's because it's early morning but I'm not quite following?

I thought I2C had to have pull up resistors or when you say try not to PULL the I2C lines, do you mean try not to pull them low when the Atmega is sleeping?

To be honest, I'm not entirely sure why I can't get the Atmega standby below 190uA. The power supply design for my project was aided by ElCaron in this thread: Low Power Relays? Is There Such a Thing? - General Electronics - Arduino Forum
and we predicted a final current draw of somewhere around 30 - 50uA standby using the recommended parts and design.

ElCaron advised me to use a HT7333 Fixed 3V3 LDO to power the Atmega as it's quite efficient.
I was also advised to break out the Enable pin on the MP1584 buck converters I use to power the modules in my project so I could shut down the buck converters until needed. That was predicted to give me around 30 - 50uA standby current, but for some reason, I'm getting 190uA standby.

It should be a case of just the Atmega and LDO running all the while with everything else shut down until needed including the clock which should only be powered up when it's given power via a digital pin.

This is a quick drawing of the circuit I'm using for the RTC.

Perhaps I should have tied the SDA and SCL pins to the 3V3 power from the digital pin instead of to the 3V3 line from the LDO so the SDA and SCL pins are only active when the clock is powered up?

Cheers!!

Strange. If you write the SDA and SCL of ATMega OUTPUT LOW you should drain 3.3V/5kOhm=660uA. I think active TWI (Atmel's name for I2C) interface prevents you to write the pins low. So if the SDA + SCL is really cause for the increased gain I suspect back powering the RTC chip do this - try to measure voltage on the pull-up resistors. If it is more than a few mV try to remove power from the RTC not by writing the pin LOW but by turning it INPUT.

Smajdalf:
Strange. If you write the SDA and SCL of ATMega OUTPUT LOW you should drain 3.3V/5kOhm=660uA. I think active TWI (Atmel's name for I2C) interface prevents you to write the pins low. So if the SDA + SCL is really cause for the increased gain I suspect back powering the RTC chip do this - try to measure voltage on the pull-up resistors. If it is more than a few mV try to remove power from the RTC not by writing the pin LOW but by turning it INPUT.

Hi,

I've metered out the pull up resistors and there's no voltage present except when the Atmega wakes up and powers the RTC up and then the voltage drops back to 0V when the Atmega goes back to sleep.

BTW, I am using 10K pull ups, not 4.7K. I notice in your formula above you use 5kOhm so I thought I'd mention that in case you didn't spot that in my circuit diagram

Could the reason be because I've tied the SDA & SCL lines to a permanent 3V3 instead of the 3V3 supplied byt the digital pin I use to power the clock? But then I suppose I would be seeing voltage on the pull up resistors all the while if that were the case??

Thanks again!

5k is because you have 2 10k resistors. If there is 0V over the resistors they cannot cause the increased current.

Smajdalf:
5k is because you have 2 10k resistors. If there is 0V over the resistors they cannot cause the increased current.

Ahh, okay, of course, I see :slight_smile:

Well, I've completely removed (unplugged) both the RTC and the MP3 module.

All that's in my circuit now is:

the Atmega328P-PU
The HT7333 3V3 LDO Ultra low quiescent current: 4mA (typ.)
and the two Buck Converters which are both disabled by their EN pins so should only be consuming their sleep / standby current of aprox 12uA each typical (roughly 24uA total).

With the atmega fully asleep, I would expect from the datasheet figures to be getting somewhere in the region of 50 - 70uA standby - so it appears that something is unexpectedly eating a fair chunk of power somewhere.

If the Buck converters are disabled (which I've confirmed with meter readings) and the RTC & MP3 are unplugged, by process of elimination, the issue must lie with either the Atmega or LDO.

For the time being, I'm going to assume the LDO is working as expected since it was recommended by a more experienced and knowledgeable member than I so that leaves the Atmega.

Unless I've got a dodgy Atmega which is possible but probably not likely, I must therefore assume the issue lies in my code - specifically with the handling of the pin states and the sleep mode. So I'm going to go check out my code further and see if I can see anything obvious that I might have overlooked.

I might also try your suggestion of changing the pin mode of the clock power pin to input low and see what happens. Nothing ventured, nothing gained :slight_smile:

Thanks!

Quick question- I thought the LowPower Linrary isn't supported on Arduino UNO (Atmega328p).
Is it supported?

Quick question- I thought the LowPower Linrary isn't supported on Arduino UNO (Atmega328p).
Is it supported?

The problem with the Uno is not low power library support. It is that the Uno has a lot of power hungry components which make any attempt, through a low power library or otherwise, to save power, for example to prolong battery life, a waste of time.
To save power, google for a bare bones Arduino (ATmega328p).

6v6gt:
The problem with the Uno is not low power library support. It is that the Uno has a lot of power hungry components which make any attempt, through a low power library or otherwise, to save power, for example to prolong battery life, a waste of time.

Indeed, a complete waste of time on a UNO in my experience.

However on a bare bones ATmega the low power library will put the processor into a less than 1uA sleep mode.