Raspberry Pi Pico W network becomes inaccessible when not used for some time
Using MicroPython v1.19.1 on 2022-09-20; Raspberry Pi Pico W with RP2040, Pico W loses network operation (though seemingly not AP connection since there is typically still an IP address) if no network operations are performed for some time. The maximum non-operating interval between network operations is typically about 5 minutes with Power-Saving on, and at least 10 minutes with Power-Saving off (more testing continues with this mode). The failure mode is typically OSError: -2.
If some operation, say a ping is done frequently, the network operation is preserved and more complex transactions (e.g., sockets) can be done with much longer intervals.
Code:
import time
import machine
import network
import urequests as requests
TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("ssid", "passw0rd")
while not wlan.isconnected() and wlan.status() >= 0:
print(f"Connected? {wlan.isconnected()} Status? {wlan.status()}")
time.sleep(1)
print(wlan.ifconfig()[0])
# increase delay between requests each time
interval_sec = 0
increment_sec = 60
timer_sec = time.time() - interval_sec
while True:
if time.time() - timer_sec > interval_sec:
try:
r = requests.get(TEXT_URL)
print(f"{interval_sec:>5} {r.status_code} {r.reason.decode()} {r.content}")
r.close()
interval_sec += increment_sec
except OSError as e:
print(e)
machine.reset()
timer_sec = time.time()
Output:
Connected? False Status? 1
192.168.6.198
0 200 OK b'This is a test of Adafruit WiFi!\nIf you can read this, its working :)'
60 200 OK b'This is a test of Adafruit WiFi!\nIf you can read this, its working :)'
120 200 OK b'This is a test of Adafruit WiFi!\nIf you can read this, its working :)'
180 200 OK b'This is a test of Adafruit WiFi!\nIf you can read this, its working :)'
240 200 OK b'This is a test of Adafruit WiFi!\nIf you can read this, its working :)'
-2
Possibly related to power-saving mode (wlan.config(pm = 0xa11140)) described in section 3.6.3 here.
Addendum: Pinging the device periodically from an external source also seems to extend accessibility of the network.
Addendum 2: Toggling the LED via the wifi module gives mixed results keeping the network alive, other factors may be at work. But the early test with network failure in Power-Saving off mode was perhaps spurious. A subsequent run has shown a longer interval possible between network operations.
The SDK doc indicates "Both the low level cyw43_driver and the lwIP stack require periodic servicing" (p.265), but it's not clear to me what those intervals are or how to recover the network from lack of servicing without a hard reset of the board after an OSError: -2.
Using requests via interrupt breaks things - OSError: [Errno 103] ECONNABORTED
No GPIO attached hardware required
Boards: PICO W / Wiznet W5500-EVB-Pico
Firmware:
- https://micropython.org/download/W5500_EVB_PICO/
- https://micropython.org/download/rp2-pico-w/
- MicroPython v1.19.1 on 2022-10-11; Raspberry Pi Pico W with RP2040
Issues:
- PICO W gives errors on failure and keep running
- Wiznet W5500-EVB-Pico hard locks without any error shown
Core 2 runs a loops that toggles a pin that is being listened to triggering core 0's interrupt, this will generate a network request that will fail in less than 12 connections
1/2 this code is just connection to the network, set board on line 8
from time import sleep_ms
from machine import Pin
from _thread import start_new_thread as newThread
import urequests # https://github.com/micropython/micropython-lib/blob/master/python-ecosys/urequests/urequests.py
import network
# 1 = Wiznet W5500-EVB-Pico; 0 = PICO W
board=0
if board:
# Wiznet W5500-EVB-Pico - https://micropython.org/download/W5500_EVB_PICO/
nic=network.WIZNET5K()
nic.active(True)
nic.ifconfig("dhcp")
else:
# PICO W - https://micropython.org/download/rp2-pico-w/
from wifi_auth import ssid, password # be sure to set your wifi login...
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.config(pm = 0xa11140)# Power management is very very bad, ping time is around 1000x worse and packet loss insane
wlan.connect(ssid, password)
while True:
wstat=wlan.status()
if wstat < 0 or wstat >= 3:
break
print('Waiting for WiFi connection...')
sleep_ms(1000)
if wlan.status() != 3:
raise RuntimeError('Network connection failed!')
else:
print('Connected')
def http(pin):
#print("print works...")#this will NOT crash
print("sending request...")
r=urequests.get("http://10.0.0.69:8080/die.php")#<?php die("OK"); ?>
print("urequest -",r.status_code,":",r.content)
r.close()# should not be necessary
r=None# should not be necessary
def core1_job():
while True:
sleep_ms(5000)
print('tripping interupt...')
http_pin.toggle()
http_pin=Pin(0,Pin.OUT,value=0)
http_pin.irq(handler=http, trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING) # this will crash maybe 25% of hte time
newThread(core1_job,())
while True:
sleep_ms(1000)
#http(0)# this will work without crashing
