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.

    Main.py

    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()
    

    Boot.py

    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 then main.py



  • @YoungChul i have the same problem on LoPy board


Log in to reply
 

Pycom on Twitter