Managing power for a solar / battery powered core

I am planning to create a solar-powered greenroof monitor with my spark core to monitor water flow off of a greenroof. Because it is solar powered, I have to worry about the power, and have some questions the how some of the core works, mostly related to this.

  • Is it possible to underclock the cpu? The datasheet for it seems to indicate that it can go all the way down to 8 Mhz, with good power savings all the way down. I am planning to underclock it to 16 Mhz. Will this work?

  • Is it possible to control when the spark core connects to the spark cloud, and to still run code while it is disconnected? I have already worked out a method for it to communicate with my server with raw TCP connections, so the only thing I would use the spark core is for updating the code, and I would want to make sure it only does that when there’s enough battery. ** Never mind, I just found the commented out section in the firmware documentation that explains how to do this** (https://raw.github.com/spark/docs/master/docs/firmware.md lines 158-183)

  • On that subject, why is this part of the documentation commented out? Is it planned to be implemented? (The part about Spark.connect() and Spark.disconnect())

  • Also: why is the part about Spark.sleep(int millis, array peripherals) commented out? Is that planned to be implemented?

  • How much power does the CC3000 module draw while idling (not shut off, but not transmitting or receiving)? I looked at the datasheet for the CC3000, but couldn’t find it.

  • Does the firmware still run while the core is in normal sleep mode (only CC3000 turned off)?

  • Is it possible to toggle CC3000 sleep, instead of requesting it sleep for a specific amount of time?

  • Is it possible to put the spark core into deep sleep until it receives an interrupt, rather than for a specific amount of time? (For instance go into DEEP_SLEEP_UNTIL_INTERRUPT when the battery is almost dead, and attach an interrupt to a pin hooked up to part of the battery controller that would notify it when, for instance battery charge > 10% or something)

  • What’s the minimum voltage that the voltage regulator can take? The datasheet for the voltage regulator linked in the docs says it has an input voltage of 2.1V-6V, but the documentation you have says it takes 3.6V-6V. Which is correct? (if it can take as low as 2.1V, then I can power directly from the battery circuit, without any upconverting) Never mind, just realized the datasheet also says Vin ≥ Vout + Vdropout

  • What would the spark core do if it was powered with too low a voltage? Would it damage it, or would it just shut off, or something else?

  • How much power does the core use under various conditions (running code but not connected to cloud, deep sleep, running code with CC3000 off, etc…)?

  • How much time and power does the core take to wake up from various sleep levels?

  • The ARM chip lists various sleep levels it can go into in its datasheet. Which ones do the Spark.sleep(int seconds) and Spark.sleep(SLEEP_MODE_DEEP, int seconds) put it into?

  • What is the maximum temperature range the core can take? (This thing will be on a NYC rooftop, and I need to know if I need to include some sort of heating for when the temperature drops to around -15C).

2 Likes

First, @g1rocket, I want to thank you for the absolutely top-notch set of questions with thorough research done. Huge props! Since we’re putting so much effort into transparency, and since you’re putting so much effort into research — you’ve basically already found nearly all the info we have! Lots of work is in progress, though, so here we go, bullet by bullet.

  • Underclocking: We haven’t tested it, and there are probably dependencies on the clock speed elsewhere in the microcontroller and the code, like the crystal frequency or the speed of the SPI clock. But feel free to test it and let us know how it goes.
  • Controlling Spark Cloud connection: You found the commented out plans for real-time control of this (more info below). Right now, setup() and loop() do not run until after the Core connects. To disable Wi-Fi entirely, essentially just turning the Core into an Arduino, comment out #define SPARK_WLAN_ENABLE on line 37 of core-common-lib/SPARK_Firmware_Driver/inc/platform_config.h.
  • Why are Spark.connect/disconnect commented out: Because they’re not implemented yet. :smile: Actually, I just checked, and there is an implementation (see spark_utilities.cpp line 419), but we haven’t tested it. Please test and let us know whether it works!
  • Peripheral sleep: Was originally in our plans, but turned out to be too hard. Wi-Fi sleep drastically cuts power draw, and deep sleep is basically as low as you can go. Since we also want to keep the interface simple and clean, we decided those were enough options.
  • Normal CC3000/Core power draw: Our testing hasn’t yielded a super definitive answer, but total normal Core draw is around 150 mA. If you go into Wi-Fi sleep, shutting off the CC3000, the draw is around 10 mA, so the CC3000 itself is somewhere around 140 mA. Once again, if you get a clear answer with solid evidence over many varying usage scenarios about power draw, please share!
  • Does loop() continue to run in Wi-Fi sleep? Yes.
  • Can you toggle CC3000 sleep instead of setting a timeout? Not now, but it’s widely requested. I’ll add it to our backlog now.
  • Can you wake the Core from deep sleep with an interrupt? Ditto. Not now, but widely requested. Added to backlog.
  • Minimum voltage is 3.6V. We have to regulate down to 3.3.
  • If the voltage is near the edge, the Core may fail in odd ways, seeming to work but performing poorly, dropping the Wi-Fi connection, and corrupting data. Below a certain level, the Core just shuts off. Feel free to experiment, but we expect that the Core will be powered with at least 3.6V.
  • Core power draw under various conditions: Short answer, we don’t know. It spikes by hundreds of mA when the CC3000 transmits, and in deep sleep it’s effectively zero. Many possibilities to test. Feel free to test and share!
  • The wakeup time is primarily dictated by the time it takes to connect to Wi-Fi. This can be from about 2 seconds to over 60 seconds, depending on radio conditions and access point hardware. In general I’d recommend you sleep for as long as is reasonable for your application, but no less than 2 minutes because of the extra power draw by the CC3000 while connecting to Wi-Fi.
  • Putting the Core into deep sleep enters STM32 “Standby mode”. See section 5.3.5 of the STM32F103 Reference Manual. Normal Spark.sleep(int seconds) just powers down the CC3000 without entering any STM32 low power mode.
  • Temperature range: The CC3000 is spec’d for -20ÂşC to 70ÂşC. As far as I know that’s the most sensitive component.

Try things out, share results, and we’ll keep updating everyone as we add new features!

Cheers!

2 Likes

Thanks for the quick reply!

Just thought of a couple more things:

  • Is it possible to put the Core into deep sleep, and have it wake up from the deep sleep into Wi-Fi sleep?
  • Is it possible to make the core not turn on Wi-Fi and connect to the cloud on startup, but still be able to do so later in the program?

I can’t wait until my Core arrives!

1 Like

Sure thing!

The answer to both those follow up questions is “Not right now”.

As in all the cases above—the firmware and hardware are both open source, so if you want to make these features possible, go for it!

Once my core arrives, I’ll probably poke around in the source code and try to see if I can get it to work (if it’s not already implemented by then), but I’m not very good at c / c++, so I don’t expect to get very far.

If you do happen to make some improvements, please share them with a pull request on Github! We’re happy to introduce good improvements into our code base.

Any developments with this? I would really love to have a solar powered Core.

Hey @mackinleysmith—plenty of great power management options are available as described in the long posts above. You can absolutely run a Core off a solar panel.

The specific other questions posed by @g1rocket still stand at the same place. In particular, waking the Core from deep sleep with an interrupt is a widely requested feature. It’s not in our short term roadmap, so we’d love a pull request on this if anyone’s excited about it. Cheers!

@mackinleysmith and @zachary My new Spark Core Power Shield will have an input for a solar panel and provide customizable MPPT control to allow peak efficiency. It will have an onboard ultra-low power MCU (MSP430) to control all the charging functions and allow you to do things like completely shut power to the Core off and then turn it back on after a set period of time. The onboard MCU can also capture data from analog and digital sensors while the Core is off and then feed it back into the Core when it’s powered on. The MCU can run at full speed on less than 15mA, but by programming it to come in and out of sleep mode I’ve got it using an average of 900uA!

I’m hoping to have the design nailed down and ready for production by the end of March. It’ll be available on the Spark Store as a replacement for the current battery shield. :smile:

6 Likes

:thumbsup: :+1: :battery: :shipit: :+1: :thumbsup:

We at :spark: are very excited to help @timb get this awesome product out into the world. Highly recommended!

How does one wake the Core up from deep sleep if not by interrupt?

@wdwinder, @timb is not "waking" the Core, he is rebooting it by re-applying power. :smile:

Thanks, but my question is about just using the sleep() function with no parameter. I believe this will put the Core in deep sleep. But documentation does not mention how to wake. I’ve had my Core for less than two days now, so I may be missing something.
Very impressed with the little gadget and the infrastructure behind it already.

@wdwinder, the sleep() must have at least one parameter defining the amount of time to sleep. Sleep(time) will put the WiFi module in standby for “time” seconds. So this is only a wifi module sleep.

Using sleep(SLEEP_MODE_DEEP, time) will put the Core in deep sleep (very low power) and reboot it after “time” seconds. I recently updated the sleep mode documentation so you may want to take a second look. I will be pushing the Spark Team to implement a wake on other events besides time so an interrupt, for example, could also wake the Core from deep sleep. :smile:

@peekay123, got it. thanks. Somehow I had old version or just missed the details on the sidebar. Wake on INTR would be very useful.

@Zachary: Planning to use P1 on battery for an application that samples soil moisture once every hour and transmits it. Trying to conserve as much battery as possible. So if i run this on Sleep mode for most of the day, my power Draw is going to be 10milli amps is it? Can you confirm that?

So going by that calculation, a powerful 2500 mAh will last only for 250 hours it seems.
I am looking at something to power the core for months on low energy operation , transmitting data once in a while.

Do you have any suggestions for that?

@manihk, I am not sure where you got the 10ma draw in sleep mode. Actually, the P1 in deep sleep will draw less than 200ua, a figure that will be confirmed by the Particle team once they have enough production units to get statistically meaningful values. At 200ua and with hourly transmissions, the battery will last a lot longer than 250 hours!

1 Like

Big :+1: to what @peekay123 said. In deep sleep the P1 can use extremely little power. You have to make sure to do the hardware design and testing to get the P1 in the lowest modes and avoid adding extra quiescent current on other components, but the possibilities are very low.

We need to get better data to give accurate numbers, but the P1 datasheet power section currently says:

Deep sleep quiescent current is 80uA typical, 100uA max.

That's based on our not statistically significant tests so far. We'll update with more accurate numbers when we have them. Edited above figures with more statistically significant numbers. This is based on the P1 reference design which uses the same SMSP as the Photon. Keep in mind you can achieve even lower numbers if you pick a SMPS with super low quiescent current.

@zachary & @peekay123 thanks a lot for the clarification. One more question with reference to the datasheet and documentation.
P1 Doc talks about various types of Deep Sleep. One of them is this:

System.sleep(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long seconds)

Doc says the Microcontroller is stopped in this mode and wifi shutdown.
(1) Is this mode available to use in P1 and in Core?
(2) Should i assume that in this mode, since the microcontroller is stopped, it draws much lesser current than the deep sleep mode?

Sorry if the question is basic. Trying to make a purchase decision for 200 units and low power operation is an important criteria.

  1. I believe stop mode with wake-on-interrupt is available both on the P1 & the Core, but @mdma should confirm.
  2. Depends on what you consider much less than deep sleep. My inclination is to say no, that MCU standby mode vs MCU stop mode have similar power consumption in the context of a Wi-Fi device, where Wi-Fi dwarfs all other power consumption, however read on.

Our documentation for firmware sleep calls is here. Read carefully.
http://docs.particle.io/photon/firmware/#system-system-sleep

Using the SLEEP_MODE_DEEP flag, where you can only awake after a certain amount of time, not on an interrupt, uses the MCU's standby mode, technically the lowest power mode. Being able to wake on an interrupt uses the MCU's stop mode, which is slightly different.

Section 4.3.4 of the STM32F205 reference manual says:

The Stop mode is based on the Cortex™-M3 deepsleep mode combined with peripheral clock gating. The voltage regulator can be configured either in normal or low-power mode. In Stop mode, all clocks in the 1.2 V domain are stopped, the PLLs, the HSI and the HSE RC oscillators are disabled. Internal SRAM and register contents are preserved.

Section 4.3.5 then says:

The Standby mode allows to achieve the lowest power consumption. It is based on the Cortex™-M3 deepsleep mode, with the voltage regulator disabled. The 1.2 V domain is consequently powered off. The PLLs, the HSI oscillator and the HSE oscillator are also switched off. SRAM and register contents are lost except for registers in the backup domain (RTC registers, RTC backup register and backup SRAM), and Standby circuitry (see Figure 3).

Ultimately, whatever other hardware you attach to the Core/Photon/P0/P1, combined with broader system architecture decisions (e.g., latency guarantees you make to your users), will probably have a bigger effect than the choice between stop and standby mode. The choice should probably be driven by whether or not you can know before going to sleep how long it is appropriate to sleep.

For example, if your product might need to wake up in 5 minutes one time but then later might be able to sleep for 5 days — and if you have no way to determine that sleep duration in advance — then you probably want to use an interrupt to wake up. If, on the other hand, you can redesign your system, including the way your servers talk to the device, so that you can know in advance a reasonable duration to sleep, then you get the benefits of standby mode. Also, of course, you could use a combination, sometimes sleeping in timed standby, and other times using stop mode and being ready to wake on an interrupt at any moment.

Hope that helps!

Ping @BDub just in case he has has more thoughts here.