I'm working on a low-power project. I basically have to wake up Arduino once every ~10 minutes, and go through a loop that takes ~20 ms. This should allow me to run it on 3 AA batteries for many years.
However, the problem is that in order to sleep, I do this:
for (int i=0; i <70; i++) {
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
The issue is that Arduino wakes up every 8 seconds, executes the for() loop, and gets back to sleep. Which each time takes an agonizing 300ms on my Arduino Pro Mini. So even though my main loop is only 20ms every 10 minutes, I end up spending 21000ms on checking that for() loop.
Any suggestions how can I put my Arduino to sleep for 10 minutes without waking up every 8 seconds?
I don't understand why it takes 300 milliseconds to wake up, increment 'i', and go back to sleep when it only takes 20 milliseconds to wake up, do your task, and go back to sleep. How did you get these measurements?
Perhaps you could avoid using the library and do all the sleep/wake up code optimization manually?
Then time of execution until get to sleep can be much shorter. This way also you may turn off all modules you do not need and left only these you need to wake up every 8 seconds, then after 10 minutes to activate all modules you need to perform what is necessary, turn off all these modules you do not need again - and so on.
That way you will have faster wake up time, need only to decrease briefly a counter (10×60/8=75 cycles) until get to sleep mode again and you will save some more battery energy.
Wake up from sleep
Increment a counter
Check to see if the counter > 75 (10 minutes in 8 second chunks)
If counter > 75 do what needs doing and set the counter back to 0
I'm sure there are better ways than that, but that's simple to do.
I was in process of measuring all this when producing a LoRa and BME280 sensor transmitter application, its for a LoRa library I am writing.
The sensor transmitter uses a bare bones ATmega328P, with regulator, LoRa module and BME280 sensor. In sleep mode that lot uses 6.5uA with the watchdog timer running.
With the sleep time set to use the lowpower library to sleep in units of 8 seconds, and adding the measured startup current pulse that occurs every 8 seconds and adding the average of that in, I get a total average sleep current of 8.5uA, which is not bad using just whats provided by the ATmega.
How is it? I've given a possible solution to the problem of needing to sleep for 10 minutes. It's possibly not the best solution but it's another approach. OP can decide which answer is best for him/her. Other readers can decide for themselves which answer is best for them.
Does anyone read previous posts before they actually post their own?
That's a fair point and I am guilty of not reading every last comment. The problem is there is a question then there might be loads of replies, possibly too many to wade through so I read enough to, hopefully, get the general idea. I probably miss something. If I have something to add I add it, if not I move on. I hope my comment helps someone, if not the OP then maybe someone else reading later on. Such is the way with any forum.
noob314:
That way you will have faster wake up time, need only to decrease briefly a counter (10×60/8=75 cycles) until get to sleep mode again and you will save some more battery energy.
The savings to be made there can be minor.
The time you cannot normally reduce, is the time the processor allows for startup from the internal watchdog timing out and the processor executing code.
On a Pro Mini for instance this startup can be 16K cycles, as set by the programming fuses.
johnwasser:
I don't understand why it takes 300 milliseconds to wake up, increment 'i', and go back to sleep when it only takes 20 milliseconds to wake up, do your task, and go back to sleep. How did you get these measurements?
It takes around ~320 ms to wake up, do my task, and go back to sleep. it takes around 300ms to wake up and go back to sleep. So the code that actually does something useful only takes 20ms.
cadence22:
It takes around ~320 ms to wake up, do my task, and go back to sleep. it takes around 300ms to wake up and go back to sleep. So the code that actually does something useful only takes 20ms.
I think most people have lost intrest in the thread, one poster deemed some post(s) as 'off topic' and made a suggestion that the moderator ought to delete them.
cadence22:
It takes around ~320 ms to wake up, do my task, and go back to sleep. it takes around 300ms to wake up and go back to sleep. So the code that actually does something useful only takes 20ms.
Using that library may produce that overheat...
Why not take a look in these Nick Gammon's articles and take some of suitable approaches suggested there?
Perhaps you could avoid using the library and do all the sleep/wake up code optimization manually?
Then time of execution until get to sleep can be much shorter. This way also you may turn off all modules you do not need and left only these you need to wake up every 8 seconds, then after 10 minutes to activate all modules you need to perform what is necessary, turn off all these modules you do not need again - and so on.
I was hoping someone already figured this out. I don't have the right equipment to monitor power usage at millisecond level. And I don't know what modules are needed to just go right back to sleep. I don't really even need to increment anything, since instead of the for() loop I could just paste the same code many times to go right back to sleep, if that would decrease the energy usage.
The article you linked doesn't really provide much information about minimizing wake-up times between the 8 seconds watchdog timer periods. It just says that you need to take it into account and that it can take up to 65ms (for me it seems to be taking longer), but it doesn't explain what to do to minimize it, other than turn off brownout detection via fuse, which only shaves 65 micro seconds out of 65 milliseconds (so less than 1% overall gain, which is not much).
Riva:
Maybe the TPL5110 or TPL5111 is the answer your looking for.
Thanks, I will look into these. One potential problem I see there looking at the specification, is that these take around 20 micro amperes constantly, which will almost double my current power usage during sleep. Is should be still better than waking up every 8 seconds, though. I would need to do some tests with these.
noob314:
Using that library may produce that overheat...
Why not take a look in these Nick Gammon's articles and take some of suitable approaches suggested there?
Yeah, I will try that to see if I can minimize time between wakeups. Although I was hoping that someone figured this out already. Unfortunately, I don't have the right hardware to monitor microamperes at milliseconds resolutions, which makes this task quite difficult and error-prone for me.
How do you get that 300ms figure? Are you monitoring the current? Or are you timing how long the sleep lasts? IIRC the WDT isn't calibrated very carefully, and may be off from the target speed by a few percent.
DrAzzy:
How do you get that 300ms figure? Are you monitoring the current? Or are you timing how long the sleep lasts? IIRC the WDT isn't calibrated very carefully, and may be off from the target speed by a few percent.
Yes, this might be my problem. I'm monitoring the time, not the current. I don't have equipment to monitor current. Maybe the problem is smaller than I expected.
It seems that if I want to do it correctly, I need to figure out how to monitor current changes down to millisecond, so that I can get an accurate picture.
So i think my next step is to buy something like this: SparkFun Current Sensor Breakout - INA169 - SEN-12040 - SparkFun Electronics
If I'm reading the specs[1] correctly, it can detect current above 3.5 mA and can respond to current changes within 5 microseconds. Since my Arduino uses around 5 mA when it is powered on, it should be able to detect it. I could then very accurately tell how much time my Arduino spends taking more than 3.5 mA between the sleep cycles.
It is trivial to extend on desired 10 min. I'm interested to see your measurements.
"
Example of watchdog timer interrupt
...
The above code, running on a "bare bones" board (that is, without voltage regulator, USB interface etc.) uses the following:
With LED lit: 19.5 mA
Awake, with LED off: 16.5 mA
Asleep: 6 uA (0.006 mA)
"
Another way to approach this is to go into deep sleep mode with all oscillators off (sleep current less than 1µA), but with one pin set up to interrupt when it changes state, which wakes up the processor. Then a very low power external device such as an RTC module or a TPL5110 is set to trigger that interrupt periodically.
Taking that a step further, the external device could turn on the entire power supply to the processor periodically. This is what the TPL5110 does, running at 35nA. An RTC would perform the same function, and would be programmable over I2C as to the time the next powerup should take place.
In either case you would also need a P-channel mosfet and a resistor, and the circuit would become a bit more complicated if the battery voltage being switched is above about 6V. But for a single Li-ion or LIPO, that wouldn't be necessary. The TPL5110 looks ideal for this for regular awakenings.