Deployment Guide
How to get code onto your robot - from simple USB to wireless OTA.
The Journey
Start simple, graduate to wireless when you're comfortable.
Method 1: USB with mpremote (Labs 1-2)
Run Code Directly
Best for quick testing - code runs but isn't saved to Pico:
Save Code to Pico
To make code run on boot:
# Copy file to Pico (as main.py = runs on boot)
mpremote connect /dev/ttyACM0 cp my_script.py :main.py
# Copy library to lib folder
mpremote connect /dev/ttyACM0 mkdir lib
mpremote connect /dev/ttyACM0 cp picobot.py :lib/picobot.py
Interactive REPL
# Start interactive Python shell
mpremote connect /dev/ttyACM0 repl
# Shortcuts:
# Ctrl+C - Stop running code
# Ctrl+D - Soft reset
# Ctrl+X - Exit mpremote
Common mpremote Commands
mpremote connect /dev/ttyACM0 ls # List files on Pico
mpremote connect /dev/ttyACM0 cat main.py # View file contents
mpremote connect /dev/ttyACM0 rm main.py # Delete file
mpremote connect /dev/ttyACM0 reset # Reboot Pico
Method 2: WiFi with OTA (Labs 3+)
Once you've set up WiFi, you can deploy wirelessly!
First-Time Setup (via USB)
Upload the OTA server and WiFi boot code:
# 1. Upload OTA server library
mpremote connect /dev/ttyACM0 cp ota.py :ota.py
# 2. Create boot.py with WiFi + OTA
mpremote connect /dev/ttyACM0 cp boot_wifi.py :boot.py
boot.py template:
import network
import time
from ota import OTAServer
# Connect to WiFi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
# Wait for connection
for _ in range(10):
if wlan.isconnected():
break
time.sleep(1)
if wlan.isconnected():
print(f"Connected: {wlan.ifconfig()[0]}")
# Start OTA server
ota = OTAServer()
else:
print("WiFi failed - USB only mode")
ota = None
Using OTA Client
Once your Pico is on WiFi, find its IP (shown on boot or use OLED):
# Check if robot is reachable
python ota_client.py 192.168.1.100 ping
# Upload your code
python ota_client.py 192.168.1.100 upload main.py
# Upload and restart
python ota_client.py 192.168.1.100 upload main.py
python ota_client.py 192.168.1.100 restart
# List files on Pico
python ota_client.py 192.168.1.100 list
# Delete a file
python ota_client.py 192.168.1.100 delete old_file.py
# Execute code remotely
python ota_client.py 192.168.1.100 exec "machine.freq()"
OTA Protocol
The OTA server uses UDP port 5007:
| Command | Description |
|---|---|
PING |
Check if robot is online |
UPLOAD:<file>:<size> |
Upload file |
LIST |
List files |
DELETE:<file> |
Delete file |
RESTART |
Soft reboot |
EXEC:<code> |
Run Python code |
Quick Deploy Script
For common workflows, create a simple deploy script:
deploy.sh:
#!/bin/bash
# Quick deploy to robot
ROBOT_IP="${ROBOT_IP:-192.168.1.100}"
PICO_PORT="${PICO_PORT:-/dev/ttyACM0}"
# Try WiFi first, fall back to USB
if python ota_client.py "$ROBOT_IP" ping 2>/dev/null | grep -q PONG; then
echo "Deploying via WiFi..."
python ota_client.py "$ROBOT_IP" upload "$1"
python ota_client.py "$ROBOT_IP" restart
else
echo "WiFi unavailable, using USB..."
mpremote connect "$PICO_PORT" cp "$1" :main.py
mpremote connect "$PICO_PORT" reset
fi
Usage:
pico-deploy Tool
For a more integrated experience, use the pico-deploy tool:
# Install (one-time)
pip install pico-deploy # or copy from tools/
# Basic usage
pico-deploy run my_script.py # Run without saving
pico-deploy push my_script.py # Save as main.py
pico-deploy push -l picobot.py # Save to lib/
pico-deploy repl # Interactive shell
pico-deploy ls # List files
# Automatic connection (tries WiFi, falls back to USB)
pico-deploy --auto push main.py
Configuration (~/.pico-deploy.yaml):
# Default connection settings
usb_port: /dev/ttyACM0
wifi_ip: 192.168.1.100
# Auto mode: wifi_first or usb_first
auto_mode: wifi_first
# Known robots (for multi-robot setups)
robots:
red: 192.168.1.101
blue: 192.168.1.102
Troubleshooting
USB Issues
| Problem | Solution |
|---|---|
| "Device not found" | Check USB cable, try different port |
| "Permission denied" | Add user to dialout group: sudo usermod -a -G dialout $USER |
| "Device busy" | Close other programs (Thonny, etc.) |
WiFi Issues
| Problem | Solution |
|---|---|
| "Timeout" | Check robot is on, correct IP |
| "No response" | Verify WiFi connection, check boot.py |
| Robot IP unknown | Connect via USB, check wlan.ifconfig() |
Recovery Mode
If your Pico won't boot (bad boot.py):
- Hold BOOTSEL button while connecting USB
- Pico appears as USB drive
- Copy new MicroPython UF2 to reflash
- Or use
mpremoteto fix boot.py
Workflow Summary
Development Cycle:
┌─────────────────────────────────────────────────┐
│ │
│ Edit code → Deploy → Test → Iterate │
│ ↑ │ │
│ └──────────────────────────────┘ │
│ │
│ Lab 1-2: mpremote run script.py │
│ Lab 3+: ota_client.py upload + restart │
│ │
└─────────────────────────────────────────────────┘
Key insight: You don't need to constantly swap USB cables once WiFi is set up. Just edit, upload, restart - all wirelessly!