Object Detection on MCU: YOLO-Nano, TinyYOLO
Compare TinyYOLO and YOLO-Nano architectures for MCU object detection, with memory, MAC, and frame-rate sizing for Cortex-M targets.
Contents & prerequisites
Object detection — drawing bounding boxes around multiple classes of interest, not just classifying a whole frame — is an order of magnitude harder than image classification, yet products increasingly demand it on sub-$5 MCUs: smart doorbells that must distinguish "person" from "package" from "cat," industrial cameras counting parts on a line, drones avoiding obstacles. Running this on a Cortex-M7 or an M55+Ethos-U55 with 256 KB–2 MB of SRAM and no OS-level GPU means every layer, every anchor box, and every byte of activation memory has to be justified. This article covers the two model families that made MCU-class detection practical — TinyYOLO (YOLOv2/v3-derived) and YOLO-Nano-style architectures — and the engineering tradeoffs behind deploying them.
Why Standard YOLO Doesn't Fit
Full YOLOv3/v4/v5 models run 30–200M parameters and multiple GFLOPs per inference — fine for a desktop GPU at 100+ fps, impossible on an MCU that might deliver 0.5–5 GFLOPs/s of actual sustained throughput (CMSIS-NN INT8 kernels on a 400 MHz Cortex-M7 land around 1–2 GMAC/s). Three things have to shrink simultaneously:
- Parameter count — must fit in flash (typically 256 KB–2 MB available for weights after RTOS/app code).
- Activation memory — the largest intermediate feature map, not the model size, usually determines whether it runs at all in 256–512 KB of SRAM.
- Compute — total MACs must map to a frame time the application tolerates (often 5–15 fps for a doorbell, 1–2 fps for a battery-powered sensor node).
TinyYOLO and YOLO-Nano attack all three by cutting depth, channel width, and input resolution, and by simplifying the detection head.
TinyYOLO: Architecture and Scaling
TinyYOLO (v2 and v3 variants) is a truncated version of the full YOLO backbone: 9–13 convolutional layers instead of 53+, with max-pooling for downsampling instead of strided residual blocks. A representative TinyYOLOv3 config:
Input: 416×416×3 (or 320×320 for MCU targets)
Conv 16 → Pool → Conv 32 → Pool → Conv 64 → Pool
→ Conv 128 → Pool → Conv 256 → Pool → Conv 512
→ Conv 1024 → Conv 256 (bottleneck)
→ two detection heads at 13×13 and 26×26 grid resolution
Parameters: ~8.9M (TinyYOLOv3, 416² input) — still too large for most MCU flash budgets without quantization. At INT8, that's ~8.9 MB, which forces either external QSPI flash/XIP or aggressive width scaling (e.g., 0.5× or 0.25× channel multipliers, bringing it to 2–4M params).
Detection head mechanics (shared with full YOLO): each grid cell predicts B anchor boxes, each with (x, y, w, h, objectness, class_probs[C]). For B=3 anchors and C=20 classes, each cell outputs 3×(5+20) = 75 values. Output tensor for a 13×13 grid: 13×13×75 ≈ 12,675 floats — small compared to early-layer feature maps, so the head itself is rarely the memory bottleneck; the first few conv layers' activations are.
YOLO-Nano: Purpose-Built for the Edge
YOLO-Nano (and related "nano"/"tiny-nano" designs from academic and industry work) isn't a truncation of YOLO — it's redesigned from the ground up with three specific techniques:
- Depthwise-separable convolutions everywhere except the stem, cutting MACs by roughly
1/Cout + 1/k²relative to a standard conv (for k=3, ~8–9× fewer MACs per layer at matched channel counts). - PEP (Projection-Expansion-Projection) and EP (Expansion-Projection) modules — bottleneck blocks that project channels down before expensive operations and back up after, similar in spirit to MobileNetV2's inverted residuals but tuned smaller.
- Fewer, narrower detection scales — often a single detection head instead of YOLO's 2–3, trading multi-scale recall for a large cut in head + upsampling-path compute.
Published YOLO-Nano configurations report ~4.0M parameters and ~4.57 BFLOPs at 416×416 input, versus TinyYOLOv2's ~15.8 BFLOPs for similar mAP on Pascal VOC-scale problems — roughly 3.5× fewer FLOPs for comparable accuracy. On an MCU this difference is the gap between 3 fps and 10 fps at the same clock.
Worked Example: Sizing a Detector for an STM32H7-Class MCU
Target: person/package detection, 96×96 grayscale-ish RGB (downsampled), Cortex-M7 @480 MHz with CMSIS-NN, 1 MB flash / 564 KB SRAM budget, INT8 quantized.
Step 1 — pick input resolution. 96×96×3 keeps the input tensor small (27,648 bytes) and is standard for MCU vision (Edge Impulse, person-detection reference models use 96×96 or 128×128).
Step 2 — estimate first-layer activation memory, the usual peak:
Conv1: 96×96×3 → 48×48×16 (stride-2, 3×3, 16 filters)
Activation size = 48 × 48 × 16 × 1 byte (INT8) = 36,864 bytes
That's under 40 KB — fine. The peak typically occurs one or two layers deeper, at the widest×tallest feature map before the first big downsampling, e.g. a 48×48×32 layer = 73,728 bytes. Budgeting 2× for double-buffering (in-place activation reuse isn't always possible across a conv), that's ~147 KB — well inside 564 KB SRAM, leaving room for the persistent weight cache and stack.
Step 3 — estimate MACs. For a YOLO-Nano-style network at 96×96 (scaled down from the published 416×416, 4.57 BFLOPs figure by resolution ratio squared):
Scale factor = (96/416)² ≈ 0.0533
Estimated MACs ≈ 4.57 GFLOPs × 0.0533 = 243.6 MFLOPs → ÷2 ≈ 122 MMACs
(FLOPs ≈ 2×MACs is the standard conversion.)
Step 4 — estimate frame time. At a realistic sustained 1.5 GMAC/s for INT8 CMSIS-NN convolutions on this core:
t ≈ 122 MMAC / 1.5 GMAC/s ≈ 81 ms → ~12.3 fps theoretical
Check: real deployments rarely hit peak throughput because of memory-bound layers (1×1 pointwise convs, depthwise convs have poor arithmetic intensity). Applying a typical 0.4 efficiency factor for depthwise-heavy nets: 81 ms / 0.4 ≈ 203 ms → ~4.9 fps, roughly half the throughput claimed in the article. This still lands in the single-digit fps range reported for similar-sized nano detectors on 400+ MHz Cortex-M7 — the estimate is self-consistent, but it's a caution against trusting the naive theoretical-peak number.
Quantization and Anchor Box Considerations
- Post-training INT8 quantization typically costs 1–3 mAP points on TinyYOLO/YOLO-Nano-class models; QAT recovers most of that if accuracy is marginal, at the cost of retraining.
- Anchor boxes must be re-clustered (k-means on the training set) for the deployment input resolution — reusing COCO-derived anchors at 96×96 input systematically mis-scales boxes and hurts recall on small objects, which is already the weak point of low-resolution detectors.
- NMS (non-max suppression) runs on the CPU after the network — for
B×grid²candidate boxes this is cheap (a few hundred boxes, O(n²) worst case) but must be included in the frame budget; it's easy to forget in throughput estimates.
Practical Deployment Comparison
| Aspect | TinyYOLO (v2/v3) | YOLO-Nano |
|---|---|---|
| Params (416² input) | ~8.9M (v3) | ~4.0M |
| BFLOPs (416² input) | ~15.8 (v2) | ~4.57 |
| Detection heads | 2 (v3) | Often 1 |
| Design origin | Truncated full YOLO | Ground-up mobile design |
| Best fit | M55+Ethos-U55, or MCU+external flash | Cortex-M7/M4 class, tight SRAM |
| Typical framework | Darknet→ONNX→TFLite/CMSIS-NN | Custom/TFLite Micro |
Key Takeaways
- MCU object detection is bounded by activation SRAM and sustained MAC/s, not just parameter count — always compute the peak feature-map size, not just total FLOPs.
- TinyYOLO is a depth-truncated full YOLO; YOLO-Nano is a ground-up redesign using depthwise-separable convs and PEP/EP bottlenecks, giving ~3.5× fewer FLOPs for comparable accuracy.
- Anchor boxes must be re-clustered for the deployment resolution — reusing COCO anchors at low input sizes silently degrades small-object recall.
- INT8 post-training quantization costs 1–3 mAP typically; use QAT if that's unacceptable.
- Real sustained throughput is commonly 30–50% of theoretical peak MAC/s due to depthwise/pointwise layers being memory-bound — budget frame time accordingly, and don't forget NMS in the total.
Learning
Sign in to track your progress.
Evidence
Public projects engineers linked to Object Detection on MCU: YOLO-Nano, TinyYOLO.
No engineer has linked a project to this topic yet. Built something that proves it? Add the project and tag it with embedded-systems-object-detection-on-mcu-yolo-nano-tinyyolo — it then shows here and on your public profile.
