Raspberry Pi Pico W: WiFi connection issues after UART reads
I've had trouble getting a Pico W to connect to WiFi after the UART has
received data.
For example the code below often doesn't connect to the network if
serial data is being sent to pin 2 of the Pico (GPIO 1) when it boots.
If you remove this connection the code works as expected and connects
to the WiFi network within 10s.
Annoyingly, it's all a bit flaky: sometimes the code does work, and
sometimes it crashes with an out of memory error. The most common
outcome is that the WiFi simply fails to connect though.
If you ignore the UART until the WiFi network is connected, it all works
happily.
I'm running "MicroPython v1.19.1 on 2022-11-18."
Please does anyone have any advice for how to investigate this.
import network
import rp2
import time
from machine import UART
uart = UART(0)
for i in range(10):
print(uart.read(6))
rp2.country('GB')
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("XXXXXX", "YYYYY")
for i in range(300):
c = wlan.ifconfig()
print(f"{i} {c}")
if c[0] != '0.0.0.0':
break
time.sleep(1)
To generate the serial data, I'm using another Pico running this code:
from machine import UART
uart = UART(0)
while True:
uart.write("Hello\n")
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.