Session 4: Connection Resilience and Reconnection Strategies
Synopsis
Focuses on detecting dropouts, retry backoff, state recovery, and designing network-aware applications that remain useful when connectivity is unreliable.
Session Content
Session 4: Connection Resilience and Reconnection Strategies
Duration: ~45 minutes
Focus: Building reliable IoT applications on Raspberry Pi Pico 2 W using MicroPython with robust Wi-Fi connection handling, retry logic, and automatic reconnection strategies.
1) Session Goals
By the end of this session, learners will be able to:
- Detect Wi-Fi connection failures in MicroPython
- Implement retry loops with backoff
- Reconnect automatically after a dropped Wi-Fi connection
- Structure code to keep trying without freezing the main application
- Apply resilience patterns to simple Pico 2 W IoT projects
2) Prerequisites
- Raspberry Pi Pico 2 W
- USB cable
- Thonny IDE installed
- MicroPython firmware flashed to the Pico 2 W
- Basic understanding of:
- Python syntax
machinenetworktime
3) Development Environment Setup
Thonny Setup
- Open Thonny
- Go to Run > Select interpreter
- Choose:
- MicroPython (Raspberry Pi Pico)
- Select the correct serial port for the Pico 2 W
- Confirm the REPL is visible in the shell pane
Recommended Workflow
- Save reusable code as
main.pyon the Pico - Use
boot.pyfor startup Wi-Fi setup if needed - Test small pieces in the REPL before saving full programs
4) Theory: Why Connection Resilience Matters
Wireless connections are not always stable. A Pico 2 W may experience:
- Weak Wi-Fi signal
- Router restarts
- Temporary network congestion
- DHCP delays
- Access point changes
- Power interruptions
If your program assumes Wi-Fi will always work, it may:
- Stop sending sensor data
- Freeze in a blocking loop
- Lose MQTT or web service connectivity
- Fail silently
Resilience Techniques
Common strategies include:
- Retry with limit: try several times before giving up
- Backoff delay: wait a little longer after each failed attempt
- Recheck connection state: verify connection before network activity
- Auto-reconnect loop: reconnect when the link drops
- Non-blocking structure: keep the rest of the program running
5) Key Concepts
5.1 Basic Wi-Fi Connection Flow
Typical connection logic:
- Activate the wireless interface
- Start connection attempt
- Wait for connection to complete
- Confirm IP address assignment
- Proceed with network tasks
5.2 Connection Status Checks
Useful checks:
wlan.isconnected()wlan.status()wlan.ifconfig()
5.3 Retry with Backoff
A simple resilience pattern:
- Attempt 1: wait 1 second
- Attempt 2: wait 2 seconds
- Attempt 3: wait 4 seconds
This reduces network hammering and gives the router time to recover.
6) Hands-On Exercise 1: Reliable Wi-Fi Connection Function
Objective
Create a reusable function that connects to Wi-Fi with retries and backoff.
Hardware
- Raspberry Pi Pico 2 W
- No additional hardware required
Code: main.py
import network
import time
# Replace with your Wi-Fi credentials
SSID = "YOUR_WIFI_NAME"
PASSWORD = "YOUR_WIFI_PASSWORD"
def connect_wifi(ssid, password, max_attempts=5):
"""
Connect to Wi-Fi with retry and backoff.
Returns:
network.WLAN object if connected, otherwise None
"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# If already connected, return immediately
if wlan.isconnected():
print("Already connected")
print("Network config:", wlan.ifconfig())
return wlan
attempt = 0
delay = 1
while attempt < max_attempts:
attempt += 1
print("Connecting to Wi-Fi... attempt", attempt)
try:
wlan.connect(ssid, password)
except Exception as e:
print("Connection call failed:", e)
timeout = 10
start = time.ticks_ms()
while not wlan.isconnected():
if time.ticks_diff(time.ticks_ms(), start) > timeout * 1000:
print("Timeout waiting for connection")
break
time.sleep(0.2)
if wlan.isconnected():
print("Connected successfully")
print("Network config:", wlan.ifconfig())
return wlan
print("Retrying in", delay, "seconds...")
time.sleep(delay)
delay = min(delay * 2, 16)
print("Failed to connect after", max_attempts, "attempts")
return None
wlan = connect_wifi(SSID, PASSWORD)
if wlan:
print("Wi-Fi ready for use")
else:
print("Wi-Fi unavailable")
Example Output
Connecting to Wi-Fi... attempt 1
Timeout waiting for connection
Retrying in 1 seconds...
Connecting to Wi-Fi... attempt 2
Connected successfully
Network config: ('192.168.1.45', '255.255.255.0', '192.168.1.1', '8.8.8.8')
Wi-Fi ready for use
Exercise Tasks
- Replace the SSID and password with your network values
- Change
max_attemptsto3and test behavior - Observe how the delay increases after each failure
- Disconnect the router or use the wrong password to see failure handling
7) Theory: Designing for Reconnection
A single successful connection is not enough for IoT systems. Your application should keep checking whether the connection is still valid.
Common Reconnection Pattern
- Before every network request, check
isconnected() - If disconnected, call a reconnection function
- Retry the main task only after connection is restored
Good Practice
Keep reconnection logic separate from application logic. This makes the code easier to maintain and reuse.
8) Hands-On Exercise 2: Auto-Reconnect Network Monitor
Objective
Create a program that continuously monitors Wi-Fi and reconnects automatically if the link drops.
Code: main.py
import network
import time
SSID = "YOUR_WIFI_NAME"
PASSWORD = "YOUR_WIFI_PASSWORD"
class WiFiManager:
def __init__(self, ssid, password):
self.ssid = ssid
self.password = password
self.wlan = network.WLAN(network.STA_IF)
self.wlan.active(True)
def connect(self, max_attempts=5):
if self.wlan.isconnected():
return True
attempt = 0
delay = 1
while attempt < max_attempts:
attempt += 1
print("Wi-Fi connect attempt", attempt)
try:
self.wlan.connect(self.ssid, self.password)
except Exception as e:
print("Connect error:", e)
timeout = 10
start = time.ticks_ms()
while not self.wlan.isconnected():
if time.ticks_diff(time.ticks_ms(), start) > timeout * 1000:
break
time.sleep(0.2)
if self.wlan.isconnected():
print("Wi-Fi connected")
print("IP:", self.wlan.ifconfig()[0])
return True
print("Waiting", delay, "seconds before retry")
time.sleep(delay)
delay = min(delay * 2, 16)
print("Wi-Fi connection failed")
return False
def ensure_connection(self):
if not self.wlan.isconnected():
print("Wi-Fi lost, reconnecting...")
return self.connect()
return True
def status(self):
return self.wlan.isconnected()
wifi = WiFiManager(SSID, PASSWORD)
if wifi.connect():
print("Starting monitor loop")
while True:
if wifi.ensure_connection():
print("Connection OK")
else:
print("Still disconnected")
time.sleep(5)
Example Output
Wi-Fi connect attempt 1
Wi-Fi connected
IP: 192.168.1.45
Starting monitor loop
Connection OK
Connection OK
Wi-Fi lost, reconnecting...
Wi-Fi connect attempt 1
Wi-Fi connected
IP: 192.168.1.45
Connection OK
Exercise Tasks
- Run the monitor loop
- Turn off the router briefly and observe behavior
- Reduce the loop interval to
2seconds - Add a print statement for the current RSSI if supported by your MicroPython build
9) Theory: Avoiding Blocking Code
A common mistake is using long blocking waits that stop the rest of the program. If your app also reads sensors or drives LEDs, you want those tasks to continue even if Wi-Fi is unstable.
Better Approach
- Keep connection attempts short
- Check connection periodically
- Let the main loop continue working
10) Hands-On Exercise 3: LED Status Indicator for Connection Health
Objective
Use the Pico 2 W onboard LED to display connection status: - On solid: connected - Blinking: trying to reconnect - Off: disconnected after repeated failure
Hardware
- Raspberry Pi Pico 2 W
Code: main.py
import network
import time
from machine import Pin
SSID = "YOUR_WIFI_NAME"
PASSWORD = "YOUR_WIFI_PASSWORD"
led = Pin("LED", Pin.OUT)
class WiFiManager:
def __init__(self, ssid, password):
self.ssid = ssid
self.password = password
self.wlan = network.WLAN(network.STA_IF)
self.wlan.active(True)
def connect(self, max_attempts=3):
attempt = 0
delay = 1
while attempt < max_attempts:
attempt += 1
print("Attempt", attempt)
led.value(1) # LED on while attempting
try:
self.wlan.connect(self.ssid, self.password)
except Exception as e:
print("Connect error:", e)
timeout = 8
start = time.ticks_ms()
while not self.wlan.isconnected():
if time.ticks_diff(time.ticks_ms(), start) > timeout * 1000:
break
time.sleep(0.2)
if self.wlan.isconnected():
print("Connected:", self.wlan.ifconfig())
led.value(1)
return True
print("Retry in", delay, "seconds")
led.value(0)
time.sleep(delay)
delay = min(delay * 2, 8)
led.value(0)
return False
def ensure_connection(self):
return self.wlan.isconnected() or self.connect()
wifi = WiFiManager(SSID, PASSWORD)
while True:
if wifi.ensure_connection():
print("Wi-Fi connected")
led.value(1)
else:
print("Wi-Fi unavailable")
for _ in range(3):
led.toggle()
time.sleep(0.2)
led.value(0)
time.sleep(4)
Example Output
Attempt 1
Connected: ('192.168.1.45', '255.255.255.0', '192.168.1.1', '8.8.8.8')
Wi-Fi connected
Wi-Fi connected
Wi-Fi connected
Exercise Tasks
- Watch the LED behavior during connection attempts
- Simulate failure with the wrong password
- Adjust blink timing to make the status more visible
11) Mini Project: Resilient Sensor Reporting Skeleton
Objective
Combine connection resilience with a periodic task, preparing for sensor-to-cloud projects.
Code: main.py
import network
import time
SSID = "YOUR_WIFI_NAME"
PASSWORD = "YOUR_WIFI_PASSWORD"
class WiFiManager:
def __init__(self, ssid, password):
self.ssid = ssid
self.password = password
self.wlan = network.WLAN(network.STA_IF)
self.wlan.active(True)
def connect(self):
if self.wlan.isconnected():
return True
try:
self.wlan.connect(self.ssid, self.password)
except Exception as e:
print("Connect error:", e)
return False
timeout = 10
start = time.ticks_ms()
while not self.wlan.isconnected():
if time.ticks_diff(time.ticks_ms(), start) > timeout * 1000:
return False
time.sleep(0.2)
return True
def ensure_connection(self):
if not self.wlan.isconnected():
print("Reconnecting Wi-Fi...")
return self.connect()
return True
wifi = WiFiManager(SSID, PASSWORD)
while True:
if wifi.ensure_connection():
# Placeholder for reading a sensor and sending data
print("Ready to send data")
print("IP address:", wifi.wlan.ifconfig()[0])
else:
print("Network down, skipping data send")
time.sleep(10)
Example Output
Ready to send data
IP address: 192.168.1.45
Ready to send data
IP address: 192.168.1.45
Reconnecting Wi-Fi...
Network down, skipping data send
Ready to send data
IP address: 192.168.1.45
12) Best Practices Checklist
- Keep Wi-Fi connection code in a dedicated function or class
- Always check
isconnected()before network operations - Use bounded retries to avoid infinite hangs
- Add a timeout for each connection attempt
- Use backoff delays to reduce network pressure
- Keep the main loop alive even if Wi-Fi fails
- Provide status feedback using the LED or serial output
- Avoid repeating
connect()too rapidly
13) Common Mistakes
- Hard-coding Wi-Fi credentials in shared code repositories
- Blocking forever in a connection loop
- Reconnecting on every iteration even when already connected
- Ignoring
Noneor failed return values - Using large delays that make the system unresponsive
- Mixing application code and connection management in the same block
14) Knowledge Check
- Why is retry logic important in wireless IoT devices?
- What is the purpose of exponential backoff?
- How can
wlan.isconnected()help prevent failures? - Why should reconnection logic be separated from sensor-reading logic?
- What happens if your code blocks forever while waiting for Wi-Fi?
15) Wrap-Up
What You Learned
- How to detect Wi-Fi failures
- How to implement connection retries
- How to automatically reconnect
- How to structure resilient Pico 2 W code for IoT applications
Next Session Preview
In the next session, you will use these resilience techniques to build a small networked IoT application that reads data and sends it to an online service reliably.