Run PyTorch models on Arduino microcontrollers using ExecuTorch.
This directory contains everything needed to package ExecuTorch as an Arduino library. A build script vendors the runtime sources from this repository into a self-contained library that Arduino users install through the Library Manager or by copying into their libraries folder.
PyTorch Model ──► torch.export ──► .pte file ──► model.h (C array)
│
Arduino Sketch (.ino)
#include <ExecuTorchArduino.h>
#include "model.h"
│
arduino-cli compile ──► Upload ──► Runs on board
-
The library (
arduino_lib/ExecuTorchArduino/) — the ExecuTorch runtime, CMSIS-NN kernels, and portable ops packaged for the Arduino build system. Generated bybuild_arduino_library.sh; not checked in. -
The model (
model.h) — a.ptefile converted to a C byte array. Each user brings their own model, exported from PyTorch with the Cortex-M backend. -
The sketch (
.ino) — a standard Arduino program that loads the model, feeds it input, and reads the output. Uses the native ExecuTorch C++ API (Program::load,Method::execute, etc.).
| Board | MCU | Status |
|---|---|---|
| Arduino Uno Q | STM32U585 (Cortex-M33) | Tested |
| Arduino Nano 33 BLE | nRF52840 (Cortex-M4F) | Untested |
| Arduino Giga R1 WiFi | STM32H747 (Cortex-M7) | Untested |
| Arduino Portenta H7 | STM32H747 (Cortex-M7) | Untested |
CMSIS-NN accelerated ops work on any board with an ARM Cortex-M processor with DSP extensions. Portable ops work on any architecture.
cd examples/arduino
./build_arduino_library.shThis copies the required ExecuTorch sources from the repository into
arduino_lib/ExecuTorchArduino/, ready for Arduino.
Copy the generated library into your Arduino libraries folder:
cp -r arduino_lib/ExecuTorchArduino ~/Arduino/libraries/Or with arduino-cli:
arduino-cli lib install --zip-path arduino_lib/ExecuTorchArduinoExport a PyTorch model to .pte format with Cortex-M quantization, then
convert to a C header:
python export_model.py --model my_model.pt --target cortex-m33 --output model.hOr use one of the pre-exported models in the examples/ directory.
#include <ExecuTorchArduino.h>
#include "model.h"
using executorch::extension::BufferDataLoader;
using executorch::runtime::Error;
using executorch::runtime::HierarchicalAllocator;
using executorch::runtime::MemoryAllocator;
using executorch::runtime::MemoryManager;
using executorch::runtime::Method;
using executorch::runtime::MethodMeta;
using executorch::runtime::Program;
using executorch::runtime::Result;
using executorch::runtime::Span;
alignas(16) uint8_t method_pool[64 * 1024];
alignas(16) uint8_t temp_pool[8 * 1024];
void setup() {
Serial.begin(115200);
delay(2000);
executorch::runtime::runtime_init();
auto loader = BufferDataLoader(model_pte, model_pte_size);
Result<Program> program = Program::load(&loader);
if (!program.ok()) {
Serial.println("Failed to load program");
return;
}
// ... load method, set inputs, execute, read outputs
// See examples/ for complete working sketches.
}
void loop() {
// Run inference periodically
delay(2000);
}The sketch uses the native ExecuTorch C++ API — the same API used on Linux, Android, and bare-metal targets. No wrapper layer, no Arduino-specific abstractions.
arduino-cli compile --fqbn arduino:zephyr:unoq MySketch
arduino-cli upload --fqbn arduino:zephyr:unoq -p /dev/ttyUSB0 MySketchThe build_arduino_library.sh script assembles these components from
the ExecuTorch repository:
| Component | Source in repo | Purpose |
|---|---|---|
| ET Runtime | runtime/executor/, runtime/core/, runtime/kernel/, runtime/platform/ |
Model loading, memory management, op dispatch |
| Portable Ops | kernels/portable/ |
Software op implementations (any CPU) |
| Cortex-M Ops | backends/cortex_m/ops/ |
CMSIS-NN accelerated int8 ops |
| CMSIS-NN | fetched by cmake / Zephyr module | ARM's optimized DSP kernels |
| flatcc | third-party/flatcc/ |
.pte file parsing |
| flatbuffers | third-party/flatbuffers/ |
Schema headers |
| c10 | runtime/core/portable_type/c10/ |
Core type definitions |
The library uses no external dependencies beyond what the Arduino board core provides.
The build script applies these patches to make ExecuTorch compile under Arduino's build system:
-
#include <exception>before<variant>— Arduino's custom<new>header omits<exception>, breakingstd::bad_variant_access. -
cmake_macros.hstub — c10/torch headers expect a cmake-generated file. The stub definesC10_USING_CUSTOM_GENERATED_MACROS. -
platform_stubs.c— provides_Exit()andfprintf()for the LLEXT environment on boards that lack them.
After modifying ExecuTorch sources, regenerate the library:
./build_arduino_library.sh # rebuild
./build_arduino_library.sh --clean # remove generated outputarduino-cli compile --fqbn arduino:zephyr:unoq examples/HelloExecuTorch
arduino-cli upload --fqbn arduino:zephyr:unoq -p /dev/ttyUSB0 examples/HelloExecuTorch
arduino-cli monitor -p /dev/ttyUSB0 --config baudrate=115200The library is published by adding its repository URL to the Arduino Library Registry. After the initial registration, new git tags are picked up automatically.
Tested on Arduino Uno Q (STM32U585, Cortex-M33 @ 160 MHz):
- 390+ source files compile with zero errors
- Flash: 106 KB used (13% of 786 KB)
- RAM: 91 KB used (69% of 131 KB)
- Model: DS-CNN keyword spotting, int8 quantized via CMSIS-NN, 52.6 KB