Skip to content

Commit b30ad01

Browse files
authored
Add Pico2 Tutorials on Raspberry Pi (#15188)
### Summary Add Pico2 Tutorials on Raspberry Pi [PLEASE REMOVE] See [CONTRIBUTING.md's Pull Requests](https://github.com/pytorch/executorch/blob/main/CONTRIBUTING.md#pull-requests) for ExecuTorch PR guidelines. [PLEASE REMOVE] If this PR closes an issue, please add a `Fixes #<issue-id>` line. [PLEASE REMOVE] If this PR introduces a fix or feature that should be the upcoming release notes, please add a "Release notes: <area>" label. For a list of available release notes labels, check out [CONTRIBUTING.md's Pull Requests](https://github.com/pytorch/executorch/blob/main/CONTRIBUTING.md#pull-requests). ### Test plan [PLEASE REMOVE] How did you test this PR? Please write down any manual commands you used and note down tests that you have written if applicable.
1 parent ace0bf0 commit b30ad01

File tree

3 files changed

+224
-16
lines changed

3 files changed

+224
-16
lines changed

docs/source/embedded-section.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ Start here for C++ development with ExecuTorch runtime APIs and essential tutori
2626

2727
- {doc}`tutorial-arm-ethos-u` — Export a simple PyTorch model for the ExecuTorch Ethos-U backend
2828
- {doc}`raspberry_pi_llama_tutorial` — Deploy a LLaMA model on a Raspberry Pi
29+
- {doc}`pico2_tutorial` — Deploy a demo MNIST model on the Raspberry Pi Pico 2
30+
2931

3032
```{toctree}
3133
:hidden:
@@ -38,3 +40,4 @@ using-executorch-building-from-source
3840
embedded-backends
3941
tutorial-arm-ethos-u
4042
raspberry_pi_llama_tutorial
43+
pico2_tutorial

docs/source/pico2_tutorial.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# Pico2: A simple MNIST Tutorial
2+
3+
Deploy your PyTorch models directly to Raspberry Pi Pico2 microcontroller with ExecuTorch.
4+
5+
## What You'll Build
6+
7+
A 28×28 MNIST digit classifier running on memory constrained, low power microcontrollers:
8+
9+
- Input: ASCII art digits (0, 1, 4, 7)
10+
- Output: Real-time predictions via USB serial
11+
- Memory: <400KB total footprint
12+
13+
## Prerequisites
14+
15+
- [Environment Setup section](https://docs.pytorch.org/executorch/1.0/using-executorch-building-from-source.html)
16+
17+
- Refer to this link on how to accept 'EULA' agreement and setup toolchain [link](https://docs.pytorch.org/executorch/1.0/backends-arm-ethos-u.html#development-requirements)
18+
19+
- Verify ARM toolchain
20+
21+
```bash
22+
which arm-none-eabi-gcc # --> arm/ethos-u-scratch/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi/bin/
23+
```
24+
25+
## Step 1: Generate pte from given example Model
26+
27+
- Use the [provided example model](https://github.com/pytorch/executorch/blob/main/examples/raspberry_pi/pico2/export_mlp_mnist.py)
28+
29+
```bash
30+
python export_mlp_mnist.py # Creates balanced_tiny_mlp_mnist.pte
31+
```
32+
33+
- **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.
34+
35+
## Step 2: Build Firmware for Pico2
36+
37+
```bash
38+
# Generate model
39+
40+
python export_mlp_mnist.py # Creates balanced_tiny_mlp_mnist.pte
41+
42+
# Build Pico2 firmware (one command!)
43+
44+
./executorch/examples/rpi/build_firmware_pico.sh --model=balanced_tiny_mlp_mnist.pte # This creates executorch_pico.uf2, a firmware image for Pico2
45+
```
46+
47+
Output: **executorch_pico.uf2** firmware file (examples/raspberry_pi/pico2/build/)
48+
49+
**Note:** 'build_firmware_pico.sh' script converts given model pte to hex array and generates C code for the same via this helper [script](https://github.com/pytorch/executorch/blob/main/examples/raspberry_pi/pico2/pte_to_array.py). This C code is then compiled to generate final .uf2 binary which is then flashed to Pico2.
50+
51+
## Step 3: Flash to Pico2
52+
53+
Hold BOOTSEL button on Pico2
54+
Connect USB → Mounts as ^RPI-RP2^ drive
55+
Drag & drop ^executorch_pico.uf2^ file
56+
Release BOOTSEL → Pico2 reboots with your model
57+
58+
## Step 4: Verify Deployment
59+
60+
**Success indicators:**
61+
62+
- LED blinks 10× at 500ms → Model running ✅
63+
- LED blinks 10× at 100ms → Error, check serial ❌
64+
65+
**View predictions:**
66+
67+
```bash
68+
# Connect serial terminal
69+
screen /dev/tty.usbmodem1101 115200
70+
# Expected output:
71+
72+
Something like:
73+
74+
=== Digit 7 ===
75+
############################
76+
############################
77+
####
78+
####
79+
####
80+
####
81+
####
82+
####
83+
####
84+
####
85+
####
86+
####
87+
####
88+
####
89+
####
90+
####
91+
####
92+
####
93+
####
94+
####
95+
####
96+
####
97+
####
98+
####
99+
####
100+
####
101+
####
102+
###
103+
104+
Input stats: 159 white pixels out of 784 total
105+
Running neural network inference...
106+
✅ Neural network results:
107+
Digit 0: 370.000
108+
Digit 1: 0.000
109+
Digit 2: -3.000
110+
Digit 3: -3.000
111+
Digit 4: 860.000
112+
Digit 5: -3.000
113+
Digit 6: -3.000
114+
Digit 7: 1640.000 ← PREDICTED
115+
Digit 8: -3.000
116+
Digit 9: -3.000
117+
118+
� PREDICTED: 7 (Expected: 7) ✅ CORRECT!
119+
```
120+
121+
## Memory Optimization Tips
122+
123+
### Pico2 Constraints
124+
125+
- 520KB SRAM (runtime memory)
126+
- 4MB Flash (model storage)
127+
- Keep models small:
128+
129+
### Common Issues
130+
131+
- "Memory allocation failed" → Reduce model size and use quantization
132+
- "Operator missing" → Use selective build: ^--operators=add,mul,relu^
133+
- "Import error" → Check ^arm-none-eabi-gcc^ toolchain setup.
134+
135+
In order to resolve some of the issues above, refer to the following guides:
136+
137+
- [ExecuTorch Quantization Optimization Guide](https://docs.pytorch.org/executorch/1.0/quantization-optimization.html)
138+
- [Model Export & Lowering](https://docs.pytorch.org/executorch/1.0/using-executorch-export.html) and
139+
- [Selective Build support](https://docs.pytorch.org/executorch/1.0/kernel-library-selective-build.html)
140+
141+
### Firmware Size Analysis
142+
143+
```bash
144+
cd <root of executorch repo>
145+
ls -al examples/raspberry_pi/pico2/build/executorch_pico.elf
146+
```
147+
148+
- **Overall section sizes**
149+
150+
```bash
151+
arm-none-eabi-size -A examples/raspberry_pi/pico2/build/executorch_pico.elf
152+
```
153+
154+
- **Detailed section breakdown**
155+
156+
```bash
157+
arm-none-eabi-objdump -h examples/raspberry_pi/pico2/build/executorch_pico.elf
158+
```
159+
160+
- **Symbol sizes (largest consumers)**
161+
162+
```bash
163+
arm-none-eabi-nm --print-size --size-sort --radix=d examples/raspberry_pi/pico2/build/executorch_pico.elf | tail -20
164+
```
165+
166+
### Model Memory Footprint
167+
168+
- **Model data specifically**
169+
170+
```bash
171+
arm-none-eabi-nm --print-size --size-sort --radix=d examples/raspberry_pi/pico2/build/executorch_pico.elf | grep -i model
172+
```
173+
174+
- **Check what's in .bss (uninitialized data)**
175+
176+
```bash
177+
arm-none-eabi-objdump -t examples/raspberry_pi/pico2/build/executorch_pico.elf | grep ".bss" | head -10
178+
```
179+
180+
- **Memory map overview**
181+
182+
```bash
183+
arm-none-eabi-readelf -l examples/raspberry_pi/pico2/build/executorch_pico.elf
184+
```
185+
186+
## Next Steps
187+
188+
### Scale up your deployment
189+
190+
- Use real production trained model
191+
- Optimize further → INT8 quantization, pruning
192+
193+
### Happy Inference!
194+
195+
**Result:** PyTorch model → Pico2 deployment in 4 simple steps 🚀
196+
Total tutorial time: ~15 minutes
197+
198+
**Conclusion:** Real-time inference on memory constrained, low power microcontrollers, a complete PyTorch → ExecuTorch → Pico2 demo MNIST deployment

examples/raspberry_pi/pico2/README.md

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,48 @@ This document outlines the steps required to run a simple MNIST digit recognitio
44

55
## Demo Model: Hand-crafted MNIST Classifier
66

7-
The included `export_mlp_mnist.py` creates a demonstration model with hand-crafted weights (not production-trained). This tiny MLP recognizes digits 0, 1, 4, and 7 using manually designed feature detectors.
7+
The included `export_mlp_mnist.py` (in examples/raspberry_pi/pico2) creates a demonstration model with hand-crafted weights (not production-trained). This tiny MLP recognizes digits 0, 1, 4, and 7 using manually designed feature detectors.
88
Note: This is a proof-of-concept. For production use, train your model on real MNIST data.
99

10-
## Bring Your Own Model
10+
## Bring Your Own Model and Deploy
1111

1212
This demo demonstrates ExecuTorch's ability to bring your own PyTorch model and deploy it to Pico2 with one simple script. The complete pipeline works from any PyTorch model to a runnable binary:
1313

14-
### Train your PyTorch model
14+
- Use existing demo model (examples/raspberry_pi/pico2/export_mlp_mnist.py) or bring your own model
15+
- Build firmware with one command and pass the model file (.pte) as an argument
16+
- Deploy directly to Pico2
1517

16-
Export using `torch.export()` and `to_edge()`
17-
Build firmware with one command
18-
Deploy directly to Pico2
18+
### Important Caveats
1919

20-
#### Important Caveats:
21-
22-
- Memory constraints - Models must fit in 520KB SRAM
20+
- Memory constraints - Models must fit in 520KB SRAM (Pico2)
2321
- Missing operators - Some ops may not be supported
24-
- Selective builds - Include only operators your model uses
22+
- Selective builds - Include only operators your model uses if you want to reduce binary size
2523

2624
## Memory Constraints & Optimization
2725

28-
- Critical: Pico2 has limited memory:
29-
- 520KB SRAM (on-chip static RAM)
30-
- 4MB QSPI Flash (onboard storage)
26+
- Critical: Pico2 has limited memory
27+
- 520KB SRAM (on-chip static RAM)
28+
- 4MB QSPI Flash (onboard storage)
3129

3230
### Always apply optimization techniques on large models that do not fit in Pico2 memory:
3331

3432
Large models will not fit. Keep your `.pte` files small!
33+
3534
- Quantization (INT8, INT4)
3635
- Model pruning
3736
- Operator fusion
3837
- Selective builds (include only needed operators)
39-
For more details , refer to the [ExecuTorch Quantization Optimization Guide](https://docs.pytorch.org/executorch/1.0/quantization-optimization.html), [Model Export & Lowering](https://docs.pytorch.org/executorch/1.0/using-executorch-export.html) and [Selective Build support](https://docs.pytorch.org/executorch/1.0/kernel-library-selective-build.html)
38+
39+
For more details , refer to the following guides:
40+
41+
- [ExecuTorch Quantization Optimization Guide](https://docs.pytorch.org/executorch/1.0/quantization-optimization.html)
42+
- [Model Export & Lowering](https://docs.pytorch.org/executorch/1.0/using-executorch-export.html) and
43+
- [Selective Build support](https://docs.pytorch.org/executorch/1.0/kernel-library-selective-build.html)
4044

4145
## (Prerequisites) Prepare the Environment for Arm
4246

4347
Setup executorch development environment. Also see instructions for setting up the environment for Arm.
44-
Make sure you have the toolchain configured correctly. Refer to this [setup](https://docs.pytorch.org/executorch/1.0/backends-arm-ethos-u.html#development-requirements) for more details.
48+
Make sure you have the toolchain configured correctly. Refer to this [setup](https://docs.pytorch.org/executorch/main/backends-arm-ethos-u.html#development-requirements) for more details.
4549

4650
```bash
4751
which arm-none-eabi-gcc
@@ -73,6 +77,7 @@ Hold the BOOTSEL button on Pico2 and connect to your computer. It mounts as `RPI
7377
### Verify Execution
7478

7579
The Pico2 LED blinks 10 times at 500ms intervals for successful execution. Via serial terminal, you'll see:
80+
7681
```bash
7782
...
7883
...
@@ -134,9 +139,11 @@ Running neural network inference...
134139
### Debugging via Serial Terminal
135140

136141
On macOS/Linux:
142+
137143
```bash
138144
screen /dev/tty.usbmodem1101 115200
139145
```
146+
140147
Replace `/dev/tty.usbmodem1101` with your device path. If LED blinks 10 times at 100ms intervals, check logs for errors, but if it blinks 10 times at 500ms intervals, it is successful!
141148

142-
Result: A complete PyTorch → ExecuTorch → Pico2 demo neural network deployment! 🚀
149+
Result: A complete PyTorch → ExecuTorch → Pico2 demo MNIST deployment! 🚀

0 commit comments

Comments
 (0)