Pico2: A simple MNIST Tutorial#
Deploy your PyTorch models directly to Raspberry Pi Pico2 microcontroller with ExecuTorch.
What You’ll Build#
A 28×28 MNIST digit classifier running on memory constrained, low power microcontrollers:
Input: ASCII art digits (0, 1, 4, 7)
Output: Real-time predictions via USB serial
Memory: <400KB total footprint
Prerequisites#
Refer to this link on how to accept ‘EULA’ agreement and setup toolchain link
Verify ARM toolchain
which arm-none-eabi-gcc # --> arm/ethos-u-scratch/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi/bin/
Step 1: Generate pte from given example Model#
Use the provided example model
python export_mlp_mnist.py # Creates balanced_tiny_mlp_mnist.pte
Note: This is hand-crafted MNIST Classifier (proof-of-concept), and not production trained. This tiny MLP recognizes digits 0, 1, 4, and 7 using manually designed feature detectors.
Step 2: Build Firmware for Pico2#
# Generate model
python export_mlp_mnist.py # Creates balanced_tiny_mlp_mnist.pte
# Build Pico2 firmware (one command!)
./executorch/examples/rpi/build_firmware_pico.sh --model=balanced_tiny_mlp_mnist.pte # This creates executorch_pico.uf2, a firmware image for Pico2
Output: executorch_pico.uf2 firmware file (examples/raspberry_pi/pico2/build/)
Note: ‘build_firmware_pico.sh’ script converts given model pte to hex array and generates C code for the same via this helper script. This C code is then compiled to generate final .uf2 binary which is then flashed to Pico2.
Step 3: Flash to Pico2#
Hold BOOTSEL button on Pico2 Connect USB → Mounts as ^RPI-RP2^ drive Drag & drop ^executorch_pico.uf2^ file Release BOOTSEL → Pico2 reboots with your model
Step 4: Verify Deployment#
Success indicators:
LED blinks 10× at 500ms → Model running ✅
LED blinks 10× at 100ms → Error, check serial ❌
View predictions:
# Connect serial terminal
screen /dev/tty.usbmodem1101 115200
# Expected output:
Something like:
=== Digit 7 ===
############################
############################
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
####
###
Input stats: 159 white pixels out of 784 total
Running neural network inference...
✅ Neural network results:
Digit 0: 370.000
Digit 1: 0.000
Digit 2: -3.000
Digit 3: -3.000
Digit 4: 860.000
Digit 5: -3.000
Digit 6: -3.000
Digit 7: 1640.000 ← PREDICTED
Digit 8: -3.000
Digit 9: -3.000
� PREDICTED: 7 (Expected: 7) ✅ CORRECT!
Memory Optimization Tips#
Pico2 Constraints#
520KB SRAM (runtime memory)
4MB Flash (model storage)
Keep models small:
Common Issues#
“Memory allocation failed” → Reduce model size and use quantization
“Operator missing” → Use selective build: ^–operators=add,mul,relu^
“Import error” → Check ^arm-none-eabi-gcc^ toolchain setup.
In order to resolve some of the issues above, refer to the following guides:
Firmware Size Analysis#
cd <root of executorch repo>
ls -al examples/raspberry_pi/pico2/build/executorch_pico.elf
Overall section sizes
arm-none-eabi-size -A examples/raspberry_pi/pico2/build/executorch_pico.elf
Detailed section breakdown
arm-none-eabi-objdump -h examples/raspberry_pi/pico2/build/executorch_pico.elf
Symbol sizes (largest consumers)
arm-none-eabi-nm --print-size --size-sort --radix=d examples/raspberry_pi/pico2/build/executorch_pico.elf | tail -20
Model Memory Footprint#
Model data specifically
arm-none-eabi-nm --print-size --size-sort --radix=d examples/raspberry_pi/pico2/build/executorch_pico.elf | grep -i model
Check what’s in .bss (uninitialized data)
arm-none-eabi-objdump -t examples/raspberry_pi/pico2/build/executorch_pico.elf | grep ".bss" | head -10
Memory map overview
arm-none-eabi-readelf -l examples/raspberry_pi/pico2/build/executorch_pico.elf
Next Steps#
Scale up your deployment#
Use real production trained model
Optimize further → INT8 quantization, pruning
Happy Inference!#
Result: PyTorch model → Pico2 deployment in 4 simple steps 🚀 Total tutorial time: ~15 minutes
Conclusion: Real-time inference on memory constrained, low power microcontrollers, a complete PyTorch → ExecuTorch → Pico2 demo MNIST deployment