Deepsleep stops execution of main
-
Hello Pycom
I am currently working on reducing the amount of power that my SiPy uses.
I am making periodic readings and uploading to a database using MQTT and a wifi connection. Once done uploading i want to have my device in deepsleep for a period of time before redoing the whole proces again.
The code functions like i want it to with one exception: After completing a deepsleep my SiPy stops executing main.py in >95% of the cases, but every now and then it functions properly, restarting main.py once it has finished a deepsleep.
According to the documentation deepsleep is supposed to: "resume execution from the main script just as with a reset" Which i assume means that it will execute the script from the top starting over.
Most of the time, my result is that it runs the code once and then does nothing.
Below is my code for main.py and boot.py and at the bottom is the output from the Pymakr console.import machine from machine import I2C import time import pycom from simple import MQTTClient from network import WLAN DISCONNECTED = 0 CONNECTING = 1 CONNECTED = 2 DEVICE_ID = "4D2A4D" HOST = "xxxxxxxxx.iot.eu-west-1.amazonaws.com" #not real endpoint! TOPIC = "myThingName" WLANNAME = "SDU-GUEST" state = DISCONNECTED connection = None deepSleep = 5000 counter = 0 wlan = WLAN(mode=WLAN.STA) pycom.heartbeat(False) i2c = I2C(0) i2c.init(I2C.MASTER, baudrate=9600, pins=("P9", "P19")) def run(): global deepSleep global state global connection global counter while True: while state != CONNECTED: while not wlan.isconnected(): nets = wlan.scan() for net in nets: if net.ssid == 'SDU-GUEST': print('Network found!') wlan.connect(net.ssid, auth=(net.sec, ''), timeout=30000) while not wlan.isconnected(): machine.idle() # save power while waiting print('WLAN connection succeeded!') break try: state = CONNECTING print("CONNECTING TO MQTT") connection = MQTTClient(client_id=DEVICE_ID, server=HOST, port=8883, keepalive=10000, ssl=True, ssl_params={"certfile":"/flash/cert/cert.pem", "keyfile":"/flash/cert/private.key", "ca_certs":"/flash/cert/ca.pem"}) connection.connect() print("MQTT CONNECTED") state = CONNECTED except: print('ERROR') time.sleep(2) continue while state == CONNECTED: counter += 1 if counter >= 10: deepSleep = 1800000 print("COUNTER: %i"%(counter)) #Does it save values in ram during deepsleep? I dont think so. i2c.writeto_mem(112, 0x00, b'\x51') # wait for the sensor to complete its reading time.sleep(0.1) x = i2c.readfrom_mem(112, 0x02, 2) time.sleep(0.01) dist = x[1] | x[0] << 8 print("DISTANCE: %i"%(dist)) msg = '{"device":"%s", "DeepsleepDuration":"%i" ,"Data":"%s"}'%(DEVICE_ID,deepSleep, dist) connection.publish(topic=TOPIC, msg=msg, qos=0) print('SENDING: %s'%(msg)) time.sleep(5.0) print("DEEPSLEEPING FOR: %i"%(deepSleep)) machine.deepsleep(deepSleep) print("continue?") time.sleep(5) run()
known_nets = [('AndroidAP', 'zvxs8927'), ('SDU-GUEST', '')] # change this line to match your WiFi settings import machine import os uart = machine.UART(0, 115200) # disable these two lines if you don't want serial access os.dupterm(uart) if machine.reset_cause() != machine.SOFT_RESET: # needed to avoid losing connection after a soft reboot from network import WLAN wl = WLAN() # save the default ssid and auth original_ssid = wl.ssid() original_auth = wl.auth() wl.mode(WLAN.STA) available_nets = wl.scan() nets = frozenset([e.ssid for e in available_nets]) known_nets_names = frozenset([e[0] for e in known_nets]) net_to_use = list(nets & known_nets_names) try: net_to_use = net_to_use[0] pwd = dict(known_nets)[net_to_use] sec = [e.sec for e in available_nets if e.ssid == net_to_use][0] wl.connect(net_to_use, (sec, pwd), timeout=10000) except: wl.init(mode=WLAN.AP, ssid=original_ssid, auth=original_auth, channel=6, antenna=WLAN.INT_ANT)
Here is a dump of what pymakr gets over the UART connection when i run my code.
Running main.py I (1425042) wifi: sleep disable CONNECTING TO MQTT MQTT CONNECTED COUNTER: 1 DISTANCE: 0 SENDING: {"device":"4D2A4D", "DeepsleepDuration":"5000" ,"Data":"0"} DEEPSLEEPING FOR: 5000 I (1439918) wifi: state: run -> init (0) I (1439918) wifi: n:1 0, o:1 0, ap:255 255, sta:1 0, prof:6 I (1439919) wifi: pm stop, total sleep time: 0/1424973621 E (1439922) wifi: esp_wifi_connect 806 wifi not start ets Jun 8 2016 00:22:57 rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0x00 clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:QIO, clock div:2 load:0x3fff9010,len:8 load:0x3fff9018,len:248 load:0x40078000,len:4056 load:0x4009fc00,len:920 entry 0x4009fde4 I (1541) wifi: wifi firmware version: 2a22b2d I (1557) wifi: pp_task_hdl : 3ffd6bfc, prio:23, stack:8192 I (1557) wifi: Init lldesc rx mblock:10 I (1557) wifi: Init lldesc rx ampdu len mblock:7 I (1559) wifi: Init lldesc rx ampdu entry mblock:4 I (1564) wifi: sleep disable I (2552) wifi: frc2_timer_task_hdl:3ffdcc4c, prio:22, stack:2048 I (2556) wifi: mode : softAP (24:0a:c4:00:f6:1d) I (2610) wifi: mode : sta (24:0a:c4:00:f6:1c) I (2610) wifi: sleep disable MicroPython v1.8.6-493-g99ac80fe on 2017-03-03; SiPy with ESP32 Type "help()" for more information. >>> I (4940) wifi: n:1 0, o:6 0, ap:255 255, sta:1 0, prof:6 I (4941) wifi: state: init -> auth (b0) I (4942) wifi: state: auth -> assoc (0) I (4945) wifi: state: assoc -> run (10) I (4945) wifi: connected with SDU-GUEST, channel 1 I (14945) wifi: pm start, type:0
It looks like it boot.py always runs after a deepsleep, as the wifi connection gets reset after deepsleeping.
If anyone knows how to make sure that main.p resumes after deepsleeping i would very much appreciate the help.
Thanks for reading :)
-
@jcaron - I don't really have the facility to capture the actual Wifi messaging, but this may highlight the issue. I'm not using any other radios and primarily using and external antenna, but tried the internal too. The WDT in the boot.py seems to be working well - been running for 24 hours and keeps reporting - previously rarely got more than an hour. I can see the WDT kicking in and doing it's job. I guess this is the sort of thing the WDT was designed for!! Thanks for your help.
-
@guyadams99 I don't use Wi-Fi much on the LoPy so I can't help much there.
I guess it would be interesting to capture the Wi-Fi traffic and see what's happening exactly.
Are you using any other radios on the module? Internal or external antenna?
-
@jcaron - I'm using the RGB LED and a colour sequence through the boot to achieve a similar thing to the 'boot_state' you suggested and I've been able to narrow it down to the "while not wlan.isconnected():" in this snip from boot.py:
if not wlan.isconnected(): # change the line below to match your network ssid, security and password wlan.connect('Hansen2.5G', auth=(WLAN.WPA2, 'xxxx'), timeout=5000) connectcount = 0 while not wlan.isconnected(): connectcount += 1 print("idling count:" + str(connectcount)) machine.idle() # save power while waiting
Most times you see "idling count: 1" and "idling count: 2" and so on - usually up to around 100, but then it moves on through the boot. However say 1 time in 20 (although this frequency is highly variable), this step just stops - wlan.isconnected never returns true and the board basically sits in this while loop forever.
I am using the WDT, but I don't set this up until the start of main.py, so one way (hack) around this may be to get the WDT init'd earlier in boot.py, and since I'm not feeding it in this loop, it should kick in and reset, but this doesn't really solve the solution properly, at least in my mind. I'm using a pretty good Ubiquiti access point and the management systems shows the WiPy connected at -25dBm (I'm REALLY close to the AP - about 3 feet with a directional antenna) while in this loop.
So far I have tried not enabling low power wifi mode (which I did have on) and disabling the external antenna I was using, but no joy. The only other thing I can think now is to add a clause for the idling counter here to say 2000 and at that point bail out and try the wlan.connect again (basically wrap the wlan.connect in a loop to keep trying until it works) but again, this is just really putting a sticky plaster over the problem.
Any thoughts? many thanks in advance - Guy
-
@guyadams99 Not waking properly usually means you have something in your code that throws and exception and stops execution. You would then be in the REPL when you connect to the board.
This is not always easy to diagnose as you won't have USB active during deep sleep, so one solution is simply to store state in a variable so you can check it afterwards. You could even store logs.
For instance, you could have
boot_state = 0 ... do some stuff boot_state = 1 ... do more stuff boot_state = 2 yet more stuff boot_state=3
Then, when you find the board still running and in the REPL, just print
boot_state
to know where it stopped. Once you've pin-pointed which part of the code is the culprit, you can add further logs (stored in a variable rather than just sent to the console) to find the actual issue.
-
Did you get any resolution on this - I am having the same issue - my code works fine with sleep at the end of each 'measure and send' cycle and works for a period of time with deep sleep but then just stops. Rather than not coming out of deep sleep, when it fails it appears to start to boot but then stop, possibly between boot and main
-
@_peter
this is not the issue.
Deepsleep work like "reset" with one exception - you can use pin hold to "remember pin state" but whole programm start as fresh
boot.py
thenmain.py
-
@YoungChul i have the same problem on LoPy board