Skip to content

Session 4: Capstone Planning: From Prototype to Robust Async System

Synopsis

Guides learners in defining a substantial final project that integrates asynchronous hardware control, communication, resilience, and maintainable architecture.

Session Content

Session 4: Capstone Planning: From Prototype to Robust Async System

Session Overview

This session helps learners move from a simple MicroPython prototype on the Raspberry Pi Pico 2 W to a more robust asynchronous system design. The focus is on planning a capstone project that uses multiple concurrent tasks, clean code organization, error handling, and responsive I/O.

Duration

~45 minutes

Prerequisites

  • Basic Python knowledge
  • Familiarity with MicroPython on Raspberry Pi Pico 2 W
  • Understanding of asyncio basics from prior sessions
  • A working Pico 2 W flashed with MicroPython
  • Thonny IDE installed and connected to the board

Learning Objectives

By the end of this session, learners will be able to: - Identify the difference between a prototype and a robust embedded system - Plan a capstone project using asynchronous task decomposition - Organize code into modules for maintainability - Add basic error handling and recovery to async programs - Sketch a development plan for integrating sensors, actuators, and Wi-Fi-based IoT features


1. Theory: From Prototype to Robust System

1.1 Prototype vs Robust System

A prototype usually proves an idea quickly: - One sensor - One output - Minimal validation - Often written in a single file

A robust system is designed for: - Reliability over time - Clear separation of concerns - Non-blocking behavior - Recovery from errors - Maintainability and future expansion

1.2 Why Async Matters in Capstone Projects

On the Pico 2 W, asynchronous programming is useful because it allows the device to: - Read sensors regularly - Update displays or LEDs - React to buttons - Communicate over Wi-Fi - Avoid long blocking delays

Instead of writing code that does one thing at a time, async lets you schedule tasks that cooperate.

1.3 Typical Capstone Architecture

A practical asynchronous IoT project may include: - Sensor task: reads temperature, humidity, light, motion, etc. - Actuator task: controls LEDs, buzzer, relay, or fan - Network task: connects to Wi-Fi and sends data to a server - UI task: button input, OLED display, or serial logging - Supervisor task: monitors health, retries failures, and manages state

1.4 Design Principles

  • Keep tasks short and cooperative
  • Avoid time.sleep() in async code
  • Use await asyncio.sleep(...) to yield control
  • Isolate hardware access into small functions or modules
  • Add retries and fallback behavior for Wi-Fi and sensors
  • Use meaningful names for tasks and functions

2. Planning the Capstone

2.1 Example Capstone Ideas

Choose one project concept for the final build:

Option A: Smart Environmental Monitor

  • Reads temperature and humidity
  • Displays status using an LED
  • Sends readings to a cloud endpoint or local web service
  • Alerts if values exceed thresholds

Option B: Motion-Activated Security Node

  • Uses PIR sensor
  • Triggers buzzer and LED
  • Sends alert over Wi-Fi
  • Logs motion events

Option C: Connected Plant Monitor

  • Reads soil moisture
  • Activates pump or warning LED
  • Publishes data to a dashboard
  • Supports manual override button

2.2 Define System Requirements

Before coding, define: - What hardware is included? - What data needs to be read? - What should happen on an alert? - How often should each task run? - What should happen if Wi-Fi is unavailable?

2.3 Example Requirements for a Smart Environmental Monitor

  • Read a DHT22 sensor every 5 seconds
  • Blink a status LED every second
  • Connect to Wi-Fi at startup
  • Send data every 30 seconds
  • Continue reading sensors even if network upload fails

3. Hands-On Exercise 1: Build a Capstone Plan

Goal

Create a project plan for a capstone system with at least three async tasks.

Suggested Template

Fill in the following fields:

Item Example
Project name Smart Environment Monitor
Inputs DHT22, button
Outputs LED, buzzer
Connectivity Wi-Fi
Main tasks sensor_read_task, status_led_task, network_task
Failure handling retry Wi-Fi, keep local logging
Update intervals 5s, 1s, 30s

Task

Write down: 1. Your project goal 2. The hardware components 3. The tasks required 4. The update interval for each task 5. The main failure scenarios

Deliverable

A short project plan that can be used to guide implementation.


4. Code Organization for a Robust Async System

For a capstone project, keep code modular:

main.py
config.py
wifi_manager.py
sensor_task.py
actuator_task.py
utils.py

4.2 Responsibilities

  • main.py: starts the program and creates tasks
  • config.py: stores constants such as SSID, passwords, intervals
  • wifi_manager.py: handles network connection and reconnection
  • sensor_task.py: reads sensors
  • actuator_task.py: controls LEDs, buzzers, relays
  • utils.py: shared helper functions

5. Hands-On Exercise 2: Async Skeleton for a Capstone

Goal

Create a clean asynchronous structure that can later be expanded with sensors and Wi-Fi.

main.py

# main.py
# Basic async application skeleton for a Pico 2 W capstone project.

import asyncio
from machine import Pin

# Built-in LED on Raspberry Pi Pico 2 W
led = Pin("LED", Pin.OUT)

async def blink_status_led():
    """
    Blink the onboard LED every second to show the device is alive.
    """
    while True:
        led.toggle()
        print("Status LED:", led.value())
        await asyncio.sleep(1)

async def monitor_system():
    """
    Placeholder for future sensor and system monitoring logic.
    """
    while True:
        print("Monitor task running...")
        await asyncio.sleep(5)

async def main():
    """
    Create and run concurrent tasks.
    """
    print("Starting capstone async skeleton...")
    asyncio.create_task(blink_status_led())
    asyncio.create_task(monitor_system())

    while True:
        await asyncio.sleep(60)

try:
    asyncio.run(main())
finally:
    asyncio.new_event_loop()

Expected Output

Starting capstone async skeleton...
Status LED: 1
Monitor task running...
Status LED: 0
Status LED: 1
Monitor task running...

Discussion Points

  • asyncio.create_task() runs tasks concurrently
  • await asyncio.sleep() prevents blocking
  • The main loop keeps the program alive

6. Adding Error Handling and Recovery

6.1 Why Error Handling Matters

In embedded systems, failures are normal: - A sensor may return invalid readings - Wi-Fi may disconnect - A network request may fail - A peripheral may stop responding

6.2 Best Practices

  • Use try...except around risky operations
  • Log errors with helpful messages
  • Retry with a delay
  • Keep the rest of the system running if one task fails

7. Hands-On Exercise 3: Add a Resilient Task

Goal

Modify the async skeleton so one task handles errors gracefully.

Example: Simulated Sensor Task

# sensor_task.py
# Simulated sensor task with error handling.

import asyncio
import random

async def read_sensor():
    """
    Simulate reading a sensor value.
    Randomly raises an exception to mimic hardware failure.
    """
    if random.randint(0, 4) == 0:
        raise OSError("Sensor read failed")
    return random.randint(20, 35)

async def sensor_monitor():
    """
    Periodically read a sensor and recover from errors.
    """
    while True:
        try:
            value = await read_sensor()
            print("Sensor value:", value)
        except OSError as e:
            print("Sensor error:", e)
        await asyncio.sleep(3)

Example Integration in main.py

# main.py

import asyncio
from machine import Pin
from sensor_task import sensor_monitor

led = Pin("LED", Pin.OUT)

async def blink_status_led():
    while True:
        led.toggle()
        await asyncio.sleep(1)

async def main():
    asyncio.create_task(blink_status_led())
    asyncio.create_task(sensor_monitor())

    while True:
        await asyncio.sleep(60)

try:
    asyncio.run(main())
finally:
    asyncio.new_event_loop()

Expected Output

Sensor value: 27
Sensor value: 31
Sensor error: Sensor read failed
Sensor value: 24

8. Wi-Fi Planning for IoT Integration

8.1 What to Consider

For Wi-Fi-based capstone functionality: - Should the device connect at startup only? - Should it retry indefinitely? - Should it keep running offline? - Should it buffer data locally?

8.2 Robust Connection Strategy

A good strategy is: - Attempt Wi-Fi connection - Retry a few times if needed - Keep core tasks running even if online features fail - Reconnect in the background if connection drops


9. Hands-On Exercise 4: Planning a Wi-Fi Task

Goal

Design a network task that can be added to a capstone project.

Sample Planning Checklist

  • Connect using SSID and password
  • Wait for connection
  • Print IP address when connected
  • Retry after failure
  • Avoid blocking other tasks

Example Skeleton

# wifi_manager.py

import asyncio
import network

async def connect_wifi(ssid, password, retries=5):
    """
    Attempt to connect to Wi-Fi with retries.
    """
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)

    if wlan.isconnected():
        print("Wi-Fi already connected")
        return wlan

    print("Connecting to Wi-Fi...")
    wlan.connect(ssid, password)

    for attempt in range(retries):
        if wlan.isconnected():
            print("Connected:", wlan.ifconfig())
            return wlan
        print("Retry", attempt + 1)
        await asyncio.sleep(2)

    print("Wi-Fi connection failed")
    return wlan

Example Usage

import asyncio
from wifi_manager import connect_wifi

async def main():
    wlan = await connect_wifi("YourSSID", "YourPassword")
    print("Connected status:", wlan.isconnected())

asyncio.run(main())

Example Output

Connecting to Wi-Fi...
Retry 1
Retry 2
Connected: ('192.168.1.42', '255.255.255.0', '192.168.1.1', '8.8.8.8')
Connected status: True

10. Capstone Development Workflow

Suggested Workflow

  1. Define the problem
  2. Choose sensors and outputs
  3. Write a task list
  4. Build each task independently
  5. Combine tasks into main.py
  6. Test locally on the Pico
  7. Add Wi-Fi and cloud features
  8. Add recovery and logging
  9. Refactor into modules
  10. Finalize the demonstration

Incremental Build Strategy

Start small: - Blink LED - Read one sensor - Add one async task - Add one network task - Add alerts - Add recovery


11. Mini Design Challenge

Challenge

Design a capstone for a connected room monitor.

Requirements

  • Monitor temperature
  • Show system alive with onboard LED
  • Send readings over Wi-Fi
  • Continue operating if network is unavailable

Learner Task

Write a brief answer for: - Tasks needed - Hardware required - Failure handling plan - Data transmission plan


12. Session Summary

In this session, learners planned how to transform a prototype into a robust async system by: - Defining system requirements - Identifying concurrent tasks - Organizing code into modules - Adding error handling and recovery - Planning Wi-Fi integration for IoT functionality


13. Suggested Capstone Next Steps

For the next session or final project build: - Select one capstone idea - Create a full task diagram - Implement sensor reading - Add actuator control - Add Wi-Fi upload - Test failure recovery and reconnection


14. Quick Reference: Async Design Checklist

  • Use asyncio for concurrent tasks
  • Keep tasks short and non-blocking
  • Use await asyncio.sleep() instead of blocking delays
  • Separate hardware and network logic
  • Add error handling with retries
  • Keep the system alive even when one feature fails

15. Environment Setup Reminder

  • Install Thonny
  • Select MicroPython interpreter for Raspberry Pi Pico 2 W
  • Connect Pico via USB
  • Save files directly to the device
  • Use the Thonny Shell for output and debugging

  • https://github.com/micropython/micropython/wiki
  • https://docs.micropython.org/en/latest/rp2/quickref.html
  • https://www.raspberrypi.com/documentation/microcontrollers/micropython.html
  • https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html#pico2

Back to Chapter | Back to Master Plan | Previous Session