Pico W won't run program after reconnection

I’m having a problem. Everything is great until I lose WiFi connection, then my Pico W won’t run the function defined in on_every_connect.

I am building a temp/humidity measurement thing with a DHT22 and TM1637 LED display.

I want the code to refresh the LED’s data every second, but only upload data to Anvil every five.

The program works great until it disconnects from WiFi (because of a bad connection), then when it reconnects, it successfully auths, but never runs the function start_log()

I referred to this post, which has a similar issue to me: Anvil Pico W fails to run main program after reconnection

However, I couldn’t get that solution to work. Here’s my code:


tm = tm1637.TM1637(clk=Pin(16), dio=Pin(17))
dht22 = dht.DHT22(Pin(10))


async def start_log():
    time_elapsed = 0
    colon_blinker = True  # True = on, False = off. To blink colon in display

    while True:
        try:
            dht22.measure()
            t = int(dht22.temperature())
            h = int(dht22.humidity())
            colon_blinker = not colon_blinker

            tm.numbers(t, h, colon_blinker)

            if time_elapsed >= 5:
                print(f"temp:{t}, humidity:{h}, time_elapsed:{time_elapsed}")
                x = await anvil.pico.call("log_dht22", t, h)
                time_elapsed = 0
                tm.show('logg')

            time_elapsed += 1
            time.sleep(1)

        except Exception as e:
            print(e)
            tm.show('errr')


anvil.pico.connect(UPLINK_KEY,
                   on_every_connect=start_log())

I am not sure if this has anything to do with it, but you might try changing your

time.sleep(1)
to
uasyncio.sleep(1)

Also, despite the intention, do you need to actually run your start_log() function every time the connection is made?

It looks to me like an async task, that gets turned into a running coroutine by the anvil code, that contains a while loop that never returns anything.
So, I’m wondering if it is still running even after you lose wifi connection and reconnect, meaning running it again is not what is actually desired, and you might try on_first_connect instead?

These are all just some guesses though.

also, does the colon actually stop blinking if the wifi disconnects? (Or is it missing because you are telling to write our ‘errr’?)

What happens if you also wrap the

x = await anvil.pico.call("log_dht22", t, h)

line in a try/except block also, allowing it to run without wifi. (maybe have the display say tm.show('wifi') if the exception block is reached or something)

If you look at your code, you have put the time.sleep(1) and time_elapsed += 1 inside the try/except block, this also means that if theres a problem with await anvil.pico.call("log_dht22", t, h) it will try over and over again at unlimited speed in a while loop.

Since the variables dht22 and tm are declared as globals outside of the start_log() scope, it is very possible that this could be blocking the processor from doing much else.

I would do this:

tm = tm1637.TM1637(clk=Pin(16), dio=Pin(17))
dht22 = dht.DHT22(Pin(10))


async def start_log():
    time_elapsed = 0
    colon_blinker = True  # True = on, False = off. To blink colon in display

    while True:
        try:
            dht22.measure()
            t = int(dht22.temperature())
            h = int(dht22.humidity())
            colon_blinker = not colon_blinker

            tm.numbers(t, h, colon_blinker)

            if time_elapsed >= 5:
                print(f"temp:{t}, humidity:{h}, time_elapsed:{time_elapsed}")
                try:
                    x = await anvil.pico.call("log_dht22", t, h)
                    tm.show('logg')
                except Exception as e:
                    print(e)
                    tm.show('wifi')
  
              time_elapsed = 0

        except Exception as e:
            print(e)
            tm.show('errr')

        time_elapsed += 1
        uasyncio.sleep(1)


anvil.pico.connect(UPLINK_KEY,
                   on_first_connect=start_log())

I’ve done a fair bit of experimentation with the Anvil-Pico-W firmware and have concluded that it cannot maintain the websocket connection to Anvil over long periods. So my approach these days is just to use it for getting config or connection strings in the startup function and use urequests in the main function for calling http endpoints on anvil. This sadly means I no longer have two way anvil-communication, so I had to drum up an mqtt client or use a gateway to talk to Anvil. Overall, i’m not sure this is an Anvil-PicoW-Firmware problem as similar issues have been raised by others using pure Micropython for this. See details here and here for possible solution to maintaining long term wifi connections with the pico-w.

Just want to say I appreciate it!

@edmondssesay Didn’t expect you to post here. I read your post and realized that there’s a solution marked, so I thought it’s not the software, it’s me. I suppose I’m not really sure with your reply.

The good thing to know here is that my project only requires one way comms (to send dht22 data to Anvil).

@ianbuywise

I tried your solution, but they didn’t work. I did notice something. Anvil actually only notices that my WiFi is disconnected when I try to connect to the server. Meaning that if I ran some code to refresh the LED display with updated temp/humidity values, it will run forever.

However, if I try to log these data to Anvil’s Data Table, AND if my WiFi connection is out, then it will start the reconnection to WiFi, succeed and then not run the program defined in on_every_connect (or on_first_connect).

Wrapping x = await anvil.pico.call("log_dht22", t, h) in a try/except block does nothing. I never see it go into the except block (where the LED display should say WIFI).

Won’t run after reconnection : You certainly know this, but in case not,
In the pico you need 2 programs boot.py and main.py and eventual libraries.
When the pico is only powered and not connected to an IDE, it only starts on boot.py and thereafter runs on main.py.
So the main program must in main.py and boot.py is to set up the connection.

In my program I logged only every 2 seconds. How much you need to do in loop, how much time you have to sleep to ensure a good execution.

This is a part of my program for the DHT22, which works fine:

import anvil.pico
import uasyncio as a
from machine import Pin
import dht

UPLINK_KEY = "***************************”

sensor = dht.DHT22(Pin(2))
async def show_data():
while True:
sensor.measure()
temp = sensor.temperature()
hum = sensor.humidity()
print("Temperature: {}°C Humidity: {:.1f}% ".format(temp, hum))
await anvil.pico.call(“DHT22_show”, temp, hum)
await a.sleep(2) # every 2 seconds

anvil.pico.connect(UPLINK_KEY, on_first_connect=show_data())

Thanks for your reply. I’m guessing your program runs properly even after WiFi reconnection?

yes, it runs directly as soon as I supply my pico. But I had also issues when I had poor wifi. So the wifi must be really strong to start and keep the connection.

I have a few pico W’s and still have not had time to mess with any of them, but I have some experience writing software to deal with constant wifi interruptions on many many different devices over the years. When I find a few round tuits I will try to replicate the problem and post any solutions I can find here.

1 Like