Page 1 of 1
pyb.standby() not documented
Posted: Tue Jan 06, 2015 6:54 pm
by eduardo
http://docs.micropython.org/en/latest/l ... yb.standby
also pyb.stop() is not documented
AS I want to run a power concious application, I am very interested in this.
Edmund
Re: pyb.standby() not documented
Posted: Thu Jan 15, 2015 10:32 am
by Damien
pyb.stop() works, and puts the MCU in to low-power sleep. It can be woken by an external interrupt (ExtInt class). Eg, we can use the Switch callback to wake up since that generates an external irq:
Code: Select all
import pyb
sw = pyb.Switch()
sw.callback(lambda:None) # do nothing except wake up
pyb.stop()
# pressing the USR switch will now wake the MCU and it'll continue execution from here
I'm working on getting the RTC to wake the MCU periodically. And then pyb.standby() will also work (but waking from standby resets the MCU so pyb.stop() is probably more useful in your case).
Re: pyb.standby() not documented
Posted: Thu Jan 15, 2015 11:58 pm
by Damien
Ok, I got the wakeup mode working. Here is some code that should work with most versions of the firmware:
Code: Select all
import pyb
import stm
# wut is wakeup counter start value, wucksel is clock source
# counter is decremented at wucksel rate, and wakes the MCU when it gets to 0
# wucksel=0b000 is RTC/16 (RTC runs at 32768Hz)
# wucksel=0b001 is RTC/8
# wucksel=0b010 is RTC/4
# wucksel=0b011 is RTC/2
# wucksel=0b100 is 1Hz clock
# wucksel=0b110 is 1Hz clock with 0x10000 added to wut
# so a 1 second wakeup could be wut=2047, wucksel=0b000, or wut=4095, wucksel=0b001, etc
def wakeup_config(wut, wucksel):
# disable register write protection
stm.mem8[stm.RTC + stm.RTC_WPR] = 0xca
stm.mem8[stm.RTC + stm.RTC_WPR] = 0x53
# clear WUTE
stm.mem32[stm.RTC + stm.RTC_CR] &= ~(1 << 10)
# wait untli WUTWF is set
while not stm.mem32[stm.RTC + stm.RTC_ISR] & (1 << 2):
pass
# program WUT
stm.mem16[stm.RTC + stm.RTC_WUTR] = wut
# program WUCKSEL
stm.mem32[stm.RTC + stm.RTC_CR] |= wucksel & 7
# set WUTE
stm.mem32[stm.RTC + stm.RTC_CR] |= 1 << 10
# set WUTIE to enable interrupts
stm.mem32[stm.RTC + stm.RTC_CR] |= 1 << 14
# enable register write protection
stm.mem8[stm.RTC + stm.RTC_WPR] = 0xff
# enable external interrupts on line 22
stm.mem32[stm.EXTI + stm.EXTI_IMR] |= 1 << 22
stm.mem32[stm.EXTI + stm.EXTI_RTSR] |= 1 << 22
# clear interrupt flags
stm.mem32[stm.RTC + stm.RTC_ISR] &= ~(1 << 10)
stm.mem32[stm.EXTI + stm.EXTI_PR] = 1 << 22
def do_stop():
# stop the MCU
pyb.stop()
# woken; clear interrupt flags
stm.mem32[stm.RTC + stm.RTC_ISR] &= ~(1 << 10)
stm.mem32[stm.EXTI + stm.EXTI_PR] = 1 << 22
Call wakeup_config to set the wakeup timer, then call do_stop to stop the MCU when you are finished processing. Example usage:
Code: Select all
# demo to wakeup every 2 seconds and toggle led
wakeup_config(32767, 0b011)
while True:
do_stop()
pyb.LED(2).toggle()
The above demo should get you around 0.9mA current consumption when the LED is off (and about 3mA when it's on). You can get down to 0.45mA current consumption if you disable the USB (you can't disable USB with the current firmware, that feature will be added very soon!).
If you need even lower power, you need to use pyb.standby(). This has not been tested thoroughly, but in principle the above code should work by simply replacing pyb.stop() with pyb.standby(). Except that when it wakes up it completely resets the MCU. In the future, features will be added so you can detect such a reset and act accordingly. This standby mode can get down to around 10-20uA on the pyboard.
Re: pyb.standby() not documented
Posted: Fri Jan 16, 2015 7:08 pm
by eduardo
Dear Damien,
Thank you very much for your code. It works great after a power up of the board.
But if I bring the board (with the reset button) into normal mode after running your code once, edit the code in the file, save it (over the USB drive mode), and then disconnect the board from the USB and push the reset button, the code does not start.
Only a power up does start the code. A reset (from Terminal or button) from normal mode
would not start the code.
I need to disconnect the board from the power and then connect it again to the
power. Only then the code starts correctly. Is that an intended behaviour?
This behaviour is in no way a problem to me, but appears strange to me.
Thank you very much for your help.
I hope you already got the GSM modem. I found out that the GSM modem can locate itself in the world quite accurately (about 50 meter error) and delivers long lat coordinates.
Re: pyb.standby() not documented
Posted: Sat Jan 17, 2015 6:41 pm
by Damien
eduardo wrote:
Only a power up does start the code. A reset (from Terminal or button) from normal mode
would not start the code.
I need to disconnect the board from the power and then connect it again to the
power. Only then the code starts correctly. Is that an intended behaviour?
It's a bug in the above code. After a hard reset (but with the power still connected) everything should be back to default state. *Except* the RTC which retains its setting across a hard reset. This is the reason it worked on first power up, but not a hard reset.
The issue is that the WAKEUP interrupt was continuing to fire after a hard reset, and was not being acknowledged. Then when you reset it and ran the wakeup code again, the edge level triggering for the external interrupt was not detecting an edge, since the WAKEUP interrupt was already high.
The fix is to clear the WAKEUP interrupt after initialising it. I have added this (and the ext-int irq reset) to the above code and it now works across a hard reset.
I hope you already got the GSM modem. I found out that the GSM modem can locate itself in the world quite accurately (about 50 meter error) and delivers long lat coordinates.
I did not yet receive it...