Low Power/Sleep Library?

Post here first, or if you can't find a relevant section!
victor_pv
Posts: 1257
Joined: Mon Apr 27, 2015 12:12 pm

Re: Low Power/Sleep Library?

Post by victor_pv » Tue Jun 09, 2015 11:38 pm

Initial report:
The example in the first link from Ray's post compiles and toggles the led with a few modifications, since we got rid of toggleLed and a few more things. I think we should not have removed those, now to use all examples you need to go adding them to the sketch :(
Anyway, if you press the button twice, it turns the led off, another 2 times turn it on. I still have to power it thru a resistor and calculate comsumption:

The notes about serialusb and the rest were there already. I have not verify if it works or not yet besides toggling the pin.

Code: Select all

// Engages stop mode on the cpu, wakes up when the onboard button is briefly pressed
// Toggles pin 3 and pin 13 every time the button is pressed/released
// Pin 3 is used to indicate that the main loop has run. It is toggled every time loop() is called.
// Normally this would be constantly flashing on/off so fast it would appear on all the time
// In this case, the loop is only finished when the button has been pressed/released.

// PROBLEMS so far : works as expected,
//                 : note that because it's in stop mode, you may have to
//                 : reset to reprogram.

//                 : SerialUSB.print : NOT WORKING.

#include <stdint.h>
#include <libmaple/pwr.h>
#include <libmaple/scb.h>

#define BOARD_LED_PIN 33
#define BOARD_BUTTON_PIN 32
#define BUTTON_DEBOUNCE_DELAY 1

// These are possibly defined somewhere but I couldn't find them. System Control Register
#define SCB_SCR_SLEEPDEEP 4       // Controls deepsleep(1) or sleep(0)
#define SCB_SCR_SLEEPONEXIT 2     // Controls sleeponexit (not used here)

volatile bool ledState = LOW;    // Used in ISR blinkState()

void togglePin(uint8 pin) {
  if (pin >= BOARD_NR_GPIO_PINS) {
    return;
  }
  gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit);
}


void toggleLED() {
  togglePin(BOARD_LED_PIN);
}

uint8 isButtonPressed(uint8 pin=BOARD_BUTTON_PIN, uint32 pressedLevel=HIGH) {
  if (digitalRead(pin) == pressedLevel) {
    delay(BUTTON_DEBOUNCE_DELAY);
    while (digitalRead(pin) == pressedLevel)
      ;
    return true;
  }
  return false;
}


uint8 waitForButtonPress(uint32 timeout=0) {
  uint32 start = millis();
  uint32 time;
  if (timeout == 0) {
    while (!isButtonPressed())
      ;
    return true;
  }
  do {
    time = millis();
    /* properly handle wrap-around */
    if ((start > time && time + (0xffffffffU - start) > timeout) ||
        time - start > timeout) {
      return false;
    }
  } while (!isButtonPressed());
  return true;
}



void setup()
{
  pinMode(BOARD_LED_PIN, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(BOARD_BUTTON_PIN, INPUT);

  // Just to show that the board has reset (wdt or possibly standby mode(not used here))
  for (int i = 0; i < 20; ++i)
  {
    delay(200);
    toggleLED();
  }

  togglePin(3);

  // Wake up cpu on button press.
  attachInterrupt(BOARD_BUTTON_PIN, blinkState, FALLING);

}

void loop()
{
  //SerialUSB.println("HI!");  delay(100);    // Only works on first iteration, before stop mode

  // Clear PDDS and LPDS bits
  PWR_BASE->CR &= PWR_CR_LPDS | PWR_CR_PDDS;

  // set sleepdeep in the system control register
  SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;

  // Now go into stop mode, wake up on interrupt
  asm("    wfi");

  digitalWrite(BOARD_LED_PIN, ledState);
  togglePin(3);

}

// Interrupt Service Routine (ISR)
void blinkState()
{
  ledState = !ledState;
  waitForButtonPress();    // Dangerous in ISR, I know, but quick demo only so blah.
}
Once I verify it does what it should (sleep the cpu), I will add it to the CoOS idle task and see how it goes in there...

EDIT:
Tested maple mini clone with 1117 regulator.
With 1.2Ohm resistor (supposed to be 1ohm with 5% tolerance...lol)
When booting bootloader and blinking: 40mV, about 33mA
Once in low power mode with led off: 3.3mV. about 2.75mA

Seems like a good saving taking into account I did not disable any peripheral the 1117 quiescent current is estimated at >5mA on most datasheets.
I guess to save more we should disable at the very least USB and SPI which get started every time no matter what. Not sure what other peripherals may get started that we could shutdown... any idea anyone? replace the voltage regulator with a different one with lower quiescent current.

I would suggest that we make a higher level library for this that we can easily include in projects, with friendly names for the modes, and that can possibly save the status of the RCC in RAM or the backup registers before sleeping, and then restore it once it wakes up.

EDIT2:
After reading a bit in the datasheet, looks like the sleep mode using in this example can only be waken by external interrupts, and shuts down all the clocks. After resuming, the program should setup all the clocks again, so this one is not helpful to something that needs to sleep and wakeup every few ms, but more like wake up for a while until a button is pressed or something like it, so I just wont test this version in CoOS.
I may have time over the weekend to look at the details of the other modes and test something out in an RTOS.

If someone decides to use this code, just know that you should:
1.-Reconfigure RCC like if the MCU had been just reset.
2.-If you use SerialUSB, re-enumerate it again (PA12 low for a few ms in generic boards, or toggle discovery pin for a few ms in the Maple boards).

bdbell
Posts: 17
Joined: Tue Apr 28, 2015 7:35 am

Re: Low Power/Sleep Library?

Post by bdbell » Fri Jun 12, 2015 6:04 pm

Want to thank everyone for their feedback on this, I got slammed with work so have not had time to get back to it till now. I have set up a couple of test sketches for my device - one uses the CPU scaling method I mentioned in the OP, and another using the sketch victor_pv provided (thanks!). Here are the results;

Sleep mode - 2.892mA
CPU scaled 256 - 15.954mA
No Sleep or Scale, TFT off - 48.26mA
TFT on - 89.85mA

The device is running off a single 2000mah Lion battery. I am using a Buy-Display.com 2.4" ILI9341 TFT (without shield), my board has both 2.8 and 3.3v regulators (LP3981), a MCP73831 battery charger, DS3231M RTC, EEprom ic, TCS2046 touch controller, BMP180, SHT21, mosfet circuit for checking battery voltage, piezo buzzer and a BT module - I have disabled the buzzer, mosfet circuit, and BT module for the tests, but nothing else so far.

Will do more tests and update post when I have time.

strawberrymaker
Posts: 266
Joined: Wed Apr 29, 2015 4:04 pm
Location: Hamm, Germany
Contact:

Re: Low Power/Sleep Library?

Post by strawberrymaker » Fri Jun 12, 2015 6:54 pm

Well, that already sounds nice :) Im interested into further tests ^^

~Straw
Twitter : @maker_berry

User avatar
ahull
Posts: 1509
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: Low Power/Sleep Library?

Post by ahull » Fri Jun 12, 2015 10:18 pm

I'm pretty impressed so far. The voltage regulator will be a significant drain. Waking from sleep can, so far as I understand it be achieved by setting an interrupt from the RTC, as well as a button push and I suspect using the RTC might be one of the most useful method of waking up for most sleeps of significant duration. (i.e. greater than a second).

According to the datasheet it should be possible to get the processors power down to around 6uA with a further 3uA or less for the RTC and battery backed registers. This is with absolutely everything shut down, but presumably this case the processor would have to backup and restore all clocks etc.

As to creating a useful set of library functions for this, I'm open to suggestions. Sleep till a certain time, sleep for n seconds, sleep till interrupt from (event/pin transition) all seem worth while goals.
- Andy Hull -

victor_pv
Posts: 1257
Joined: Mon Apr 27, 2015 12:12 pm

Re: Low Power/Sleep Library?

Post by victor_pv » Sat Jun 13, 2015 2:44 pm

ahull wrote:I'm pretty impressed so far. The voltage regulator will be a significant drain. Waking from sleep can, so far as I understand it be achieved by setting an interrupt from the RTC, as well as a button push and I suspect using the RTC might be one of the most useful method of waking up for most sleeps of significant duration. (i.e. greater than a second).

According to the datasheet it should be possible to get the processors power down to around 6uA with a further 3uA or less for the RTC and battery backed registers. This is with absolutely everything shut down, but presumably this case the processor would have to backup and restore all clocks etc.

As to creating a useful set of library functions for this, I'm open to suggestions. Sleep till a certain time, sleep for n seconds, sleep till interrupt from (event/pin transition) all seem worth while goals.
Wow 9uA would be impressive.
There is a standby mode that is supposed to keep the clocks running, if I have time later I may test how much power is saved that give.
Given that my maple mini seems to drain a few mA just for the regulator, I may not be able to see much difference between deepsleep and standby...

If we could set a library that puts the chip to sleep, wakes it up after X minutes or hours or days and restores the clocks, I think it would be very useful to anyone running on batteries.
I think labmaple has very specific functions for each part that needs initialization called from init(), so we can look there.
One concern is that the deepest sleep mode does not keep the RAM. So to achieve 9uA we may need to use an external memory eeprom or flash to save the state. I just recently discovered FRAM memories, which don't need power to keep data, but are completely random read and write like SRAM, with much lower power requirements to write as it doesn't need to erase whole pages at once.
They are available in parallel, i2c and SPI interfaces. Seems like a lower power option for permanent storage. Save all the important information there, go to sleep, when waking up check if there is a state to restore, and then run from that state.

User avatar
ahull
Posts: 1509
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: Low Power/Sleep Library?

Post by ahull » Sat Jun 13, 2015 7:50 pm

victor_pv wrote: One concern is that the deepest sleep mode does not keep the RAM. So to achieve 9uA we may need to use an external memory eeprom or flash to save the state. I just recently discovered FRAM memories, which don't need power to keep data, but are completely random read and write like SRAM, with much lower power requirements to write as it doesn't need to erase whole pages at once.
They are available in parallel, i2c and SPI interfaces. Seems like a lower power option for permanent storage. Save all the important information there, go to sleep, when waking up check if there is a state to restore, and then run from that state.
My understanding is that the power domain for the RTC/Ram is separate from the processor, so you can elect to shut it down separately, or not depending on your application (hence the separate 3uA figure for the RTC/Ram), but I'll re-read that part of the datasheet to make sure I am not barking up the wrong tree.

EDIT: However the F-ram idea sounds pretty interesting and they look to be very similar in footprint to the venerable 24c04/8/16/64 series EEROMS.
Datasheet for a typical device here..
Last edited by ahull on Sat Jun 13, 2015 8:27 pm, edited 1 time in total.
- Andy Hull -

victor_pv
Posts: 1257
Joined: Mon Apr 27, 2015 12:12 pm

Re: Low Power/Sleep Library?

Post by victor_pv » Sat Jun 13, 2015 8:13 pm

ahull wrote:
My understanding is that the power domain for the RTC/Ram is separate from the processor, so you can elect to shut it down separately, or not depending on your application (hence the separate 3uA figure for the RTC/Ram), but I'll re-read that part of the datasheet to make sure I am not barking up the wrong tree.
I understand the RTC and Backup registers are a separate domain, that stays powered with vBAT, but not the normal RAM. If the MCU goes to Standby mode, that is the lowest consumption mode then RAM and MCU state are lost, and the MCU boots like from a reset.
So that mode is great for leaving the system powered that can be woken with a button, but off otherwise, but is not so helpful if you need to do a task, sleep for a day, continue the task sleep for a day.
Now, the backup registers would be kept, so it the application doesn't need to keep more data from run to run that what fits there, then all is good.

I was having a good look at the datasheet, and seems like putting the MCU in deepsleep (clocks are lost, all peripherals shutdown, but RAM is kept) can bring the current down to 14uA to a max of 340uA. The next mode would be standby, that loses RAM.

If we can make a library that saves the state of the peripherals and the clocks in RAM, and then put the chip in deepsleep mode, and upon wake up restores the clocks an peripherals, I think it could achieve huge savings for any sketch that needs to keep RAM.

User avatar
ahull
Posts: 1509
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: Low Power/Sleep Library?

Post by ahull » Sat Jun 13, 2015 8:40 pm

victor_pv wrote: I was having a good look at the datasheet, and seems like putting the MCU in deepsleep (clocks are lost, all peripherals shutdown, but RAM is kept) can bring the current down to 14uA to a max of 340uA. The next mode would be standby, that loses RAM.
340uA would still be pretty impressive, my back of the envelope calculation gives me an estimated 245 days of standby from a typical single 2000mA 18650 LiPo cell. Note: This is the standby time, the actual duration of the battery life would obviously depend on the application and how much runtime the processor, peripherals and any other circuitry required to perform each task. Long sleeps and short tasks, say to latch up a relay, or read a sensor would however make for runtime in the order of many months.
If we can make a library that saves the state of the peripherals and the clocks in RAM, and then put the chip in deepsleep mode, and upon wake up restores the clocks an peripherals, I think it could achieve huge savings for any sketch that needs to keep RAM.
I agree, the scenario you describe would probably be the most useful mode. Deepsleep would only be required for extreme cases (very long sleeps, or relatively small backup batteries).
- Andy Hull -

strawberrymaker
Posts: 266
Joined: Wed Apr 29, 2015 4:04 pm
Location: Hamm, Germany
Contact:

Re: Low Power/Sleep Library?

Post by strawberrymaker » Sat Jun 13, 2015 9:05 pm

ahull wrote:
victor_pv wrote:
If we can make a library that saves the state of the peripherals and the clocks in RAM, and then put the chip in deepsleep mode, and upon wake up restores the clocks an peripherals, I think it could achieve huge savings for any sketch that needs to keep RAM.
I agree, the scenario you describe would probably be the most useful mode. Deepsleep would only be required for extreme cases (very long sleeps, or relatively small backup batteries).
Wouldnt it be a bit unnecessary to save the clock and then stopping it?

~Straw
Twitter : @maker_berry

victor_pv
Posts: 1257
Joined: Mon Apr 27, 2015 12:12 pm

Re: Low Power/Sleep Library?

Post by victor_pv » Sun Jun 14, 2015 2:26 am

[quote="strawberrymakerWouldnt it be a bit unnecessary to save the clock and then stopping it?

~Straw[/quote]
The idea is saving the state of all the peripheral clocks so after the sleep mode stops them all, on wake up you can restore the same settings.
Of course you can just go and run the initial setup of clocks as if the system was just booting from reset, but what happens then if your sketch has been purposely stopping some clocks or reducing the speed on others?
I understand the deep sleep mode does not preserve the status of the main clock at the very least:
"When exiting Stop mode by issuing an interrupt or a wakeup event, the HSI RC oscillator is
selected as system clock. "

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest