Reducing power consumption

Hi, I’m working on a solar powered project that monitors an I2C magnetometer and publishes events to the cloud when its heading changes.

I’ve got the WiFi on/off side of things working satisfactorily, but I’m finding that even with WiFi turned off the core still draws about 40mA. This is a lot given that my solar cell can only deliver ~50mA in full sunlight. Ideally I would like to keep average current draw down to a few mA so that it will still function on cloudy days and build up enough charge to connect the WiFi every now and then.

I could sample the magnetometer every second and put the core into a deep sleep between samples, but I am concerned about boot-up time and also that I will also have to use non-volatile storage for local variables since these get forgotten in deep sleep.

Is there another way to sleep the core without losing all the local variables? I believe the STM32 has low power “sleep” and “stop” modes that stop the system clock but keep the SRAM register contents. The “standby” mode is a little over the top for my needs. Is there any way we can access this functionality in our applications yet?

So the Spark API sleep methods keep usercode running but turn off WiFi, which DRAMATICALLY improve runtime on a battery. If you sampled once a second, averaged over 10 seconds, then sent data once every 10 minutes or so, I think you would get a lot of life out of even a small battery. You may want to look at SPI flash devices, as even very inexpensive ones can store 1MB of data for just a few cents.

If your solar panel is so small, I would recommend a larger battery, so that you can get many days runtime in cloudy weather.

If you can get a slightly larger solar panel, that would be also be something to look into, I think.

edit: so I answered your title, but not your actual question. In the short term you’ll have to use the 100bytes of available flash, I think.

Have you seen the EEPROM emulated in Flash in the base firmware?

http://docs.spark.io/firmware/#other-functions-eeprom

You could store all of your data there but you need some sort of cold-boot/warm-boot signal stored as well to know if the EEPROM is currently valid or not.

2 Likes

@megabyte, the Core’s support for STOP mode does not “stop” the user code then restart after some definable time. Instead, the Core must reset and then go into STOP mode. I do not believe that RAM content is maintained through the reset though that would have to be tested (anyone?).

The issue is due to the IWDG watchdog timer which, once started, cannot be stopped. So the reset is needed to boot without enabling the watchdog timer. I believe the approach will be considerably different in the new Photon/Electron since they will be running FreeRTOS. :smile:

2 Likes

There’s a lot more then 100 bytes of flash available but it’s not wrapped in easy to use EEPROM methods. You’ll have to dig into the forums to use it

No, this has not been implemented. If you use the current Spark sleep modes when the core resumes from sleep mode it will behave like it has been rebooted.

If you directly manage the WiFi connection and use SYSTEM_MODE(MANUAL) then your boot up time will be extremely fast and predictable.

I suggest you design your app such that you save the data in external flash, you will have to be creative in how you determine the time when you wake - you could add an I2C RTC (fairly inexpensive w/ coin cell backup - they last years). Then you can just get the time from the RTC, collect your data, push it to external flash, determine if its time to connect and publish your data, then go to sleep. Seems like this would be very efficient way of managing your power.

1 Like

Thanks for the suggestions @naikrovek, a bigger solar panel or battery would indeed help.

@bko thanks for pointing me back to the EEPROM function. The documentation claims “flash doesn’t suffer from write wear” and originally I kind of rolled my eyes and moved on but in retrospect it can probably do the job ok. I’ve been playing with the FLASHEE-EEPROM library so far and this might still be the easiest way to go if I store all my settings into a struct. I just wished there was an easier way to save power that didn’t require deep sleep.

@peekay123 thanks for the detailed insight. I can’t wait for the photon to arrive :smile:

^^ this. Great news. Yes I'm using SEMI_AUTOMATIC system mode, so I think I will just wake, read configuration from flash, compare with current sensor values and either post data to the cloud or go back to sleep if nothing has changed.

EDIT:

Argh, I just realised you're right on this too! I can check the sensor every second and publish data if anything has happened using:

Spark.sleep(SLEEP_MODE_DEEP, 1);

But I also need to connect to the cloud every 600 seconds or so to announce that the core is still alive. I believe millis() resets every time you deep sleep, so I'd need to persist a counter into flash that would increment every time it deep sleeps, and without complicated wear levelling algorithms this would wear out the 10,000 guaranteed write cycles within 3 hours.

An RTC could do it. A bigger solar panel could do it. An external AVR could do it. I just wish there were a better way to lower the idle power consumption. I believe zachary once said it used about 10mA when WiFi is off but I'm measuring 38mA. I give up. I'm building a new prototype with a bigger solar panel! At least this way I'll be able to poll the sensor more than once every second. :smiling_imp:

1 Like

Yes, flash suffers from write wear, but it is usually in the tens of thousands of cycles before that happens. So, for a device with 50k writes per block, you can write 45 times a day for three years to the same block before you reach that limit.

I will never reach that many writes on any flash device that I own. Never. Most won't.

Are you going to write to the flash device more than that?

Yep. I was going to have to write it every time the core wakes from deep sleep (every second) so that it could increment a non-volatile counter in the flash. That way when it gets up to (say) 600 it would know that 10 minutes have passed and it's time to connect to the cloud and announce that it's still alive. At this rate the flash could wear out in a matter of hours. It certainly wouldn't be a wise design for something that's meant to last many years unattended in the great outdoors.

There are plenty of possible solutions using external hardware. I just wish the core wasn't such a power hog so I could keep the design simple! :smile:

The EEPROM emulation in the core is wear-leveled using the ST Micro recommended algorithm for their device.

If you search the forum for “endurance” you will find a lot of discussion this topic. You do have to be careful with the data sheets because as I recall the external FLASH has a guaranteed minimum number of erase cycles in a table and a much larger typical (i.e. marketing) number of erase cycles in a large font on the front cover.

Interesting. I caught the discussions regarding the endurance specs in the data sheets, but I didn’t realise there was a wear levelling algorithm going on in the background. Thanks for the tip!

@megabyte, there is also another option using FRAM which has, for all intents and purposes, infinite read/write cycles. :smile:

2 Likes

If you just want to know when 10 minutes have passed, can’t you just use Time.now() or something?

Using flash to keep track of time… that seems excessive. Is there more than that?

@naikrovek, since there is no VBAT on the Core, the RTC does not run during deep sleep. So using Time.now() will not work unless you do a Cloud time sync. And that means waiting for the Core to connect to WiFi, the Cloud and then do a Time sync. All together, that takes easily over 5 seconds so sampling every second will not be possible. :stuck_out_tongue_winking_eye:

1 Like

Well, in that case, I’m glad the Photon has a VBAT pin.

I had (falsely) assumed that since the Core was powered, even when under deep sleep, that the RTC would keep running.

1 Like