MCU Agent Examples — Six Working Project Templates
MCU Agent Examples
Six representative MCU agent projects — ranging from a simple threshold agent on an ESP32 to a voice-trigger-then-delegate agent on the ESP32-S3 — each described with hardware, libraries, agent behavior, and a link placeholder for the repository.
These are intended as starting templates, not finished products. Real deployments will require calibration, security hardening, and site-specific adjustments.
Example 1 — ESP32 Temperature Anomaly Agent
Hardware:
- ESP32-WROOM-32 or ESP32-S3 DevKit
- SHT31 temperature/humidity sensor (I2C)
- Status LED (GPIO)
Libraries:
- ESP-IDF ≥5.1 (FreeRTOS, esp-mqtt, I2C driver)
- cJSON (bundled with ESP-IDF)
What the agent does:
Reads temperature and humidity from the SHT31 every 500 ms. Computes a 60-second rolling mean and standard deviation. Flags a reading as anomalous when it is more than 2.5 standard deviations from the rolling mean (Z-score threshold). On anomaly: publishes to agents/<id>/event with QoS 1, toggles the status LED. No ML model — pure statistical detection. Reconnects to the MQTT broker with exponential back-off on connectivity loss.
Agent pattern: Pattern 2 (threshold with explanation) from Sensor Agent Patterns.
Repository: (repo link TBD)
Example 2 — STM32H743 Vibration Classifier with Alert
Hardware:
- STM32H743 Nucleo-144 (or custom board)
- ADXL345 3-axis accelerometer (SPI)
- Ethernet PHY (DP83848 via RMII)
Libraries:
- STM32CubeH7 HAL (FreeRTOS, SPI, Ethernet)
- LwIP + MQTT-C
- STM32Cube.AI generated inference library (MobileNet-derived classifier, 3-class: normal, imbalance, bearing_wear)
- CMSIS-DSP for FFT feature extraction
What the agent does:
Samples the ADXL345 at 1.6 kHz via SPI with DMA. Accumulates a 1-second window (1,600 samples × 3 axes). Computes FFT on each axis and extracts 32 spectral features per axis (96 features total). Runs the STM32Cube.AI quantized classifier — approximately 8 ms on the Cortex-M7 at 480 MHz. If classification is bearing_wear with confidence > 0.82: publishes an alert with the feature vector summary to agents/<id>/event. If confidence < 0.60 on any class: publishes to the delegation topic and waits for a cloud decision (5-second timeout). Normal operation publishes a heartbeat every 60 seconds.
Agent pattern: Pattern 1 (anomaly detect) + Pattern 3 (sensor fusion: 3-axis → single class).
Repository: (repo link TBD)
Example 3 — ESP32-S3 Voice-Trigger Then LLM-Delegate Agent
Hardware:
- ESP32-S3 DevKit-C (or ESP32-S3-BOX-3)
- I2S MEMS microphone (e.g., INMP441)
- External speaker (I2S amplifier, optional)
Libraries:
- ESP-IDF ≥5.2 (I2S driver, FreeRTOS, esp-mqtt)
- Edge Impulse Arduino/ESP-IDF SDK (EON compiled keyword spotting model)
- esp-http-client (for LLM delegation via HTTPS)
What the agent does:
Streams audio from the I2S microphone at 16 kHz mono. Runs a keyword spotting model (locally, via EON compiler + ESP-NN vector ISA acceleration) to detect a wake word, with a rolling 1-second inference window. On wake-word detection (confidence > 0.88): switches to recording mode, captures the following 5 seconds of audio, converts to 80-dimension log-Mel spectrogram features, and POSTs the features to an HTTPS LLM endpoint (edge server or cloud API). The LLM endpoint returns a structured JSON action: {"action": "turn_on", "target": "hvac"}. The agent parses the action and publishes a command to the actuator topic. Wake-word inference runs entirely on the ESP32-S3; the intent understanding runs off-device.
Important note: The ESP32-S3 does not run an LLM. It runs a small keyword-spotting neural network (~30 KB weights, ~50 KB activations) via the vector ISA. The LLM runs on a server.
Agent pattern: Pattern 1 (local inference) + Cloud delegation (LLM intent) + Pattern 4 (local actuate on response).
Repository: (repo link TBD)
Example 4 — RP2040 Environmental Monitor with MQTT
Hardware:
- Raspberry Pi Pico W (RP2040 + CYW43439 Wi-Fi)
- BME680 environmental sensor (I2C): temperature, humidity, pressure, VOC/gas resistance
- 128×64 OLED display (SSD1306, I2C, optional)
Libraries:
- Pico SDK 2.x (I2C, FreeRTOS port for RP2040)
- paho-embedded-mqtt (modified for Pico SDK)
- Bosch BSEC2 library (proprietary; converts BME680 raw gas resistance to IAQ index)
- lwIP (bundled in Pico SDK for Pico W)
What the agent does:
Reads the BME680 every 3 seconds. Applies the Bosch BSEC2 algorithm to compute an Indoor Air Quality (IAQ) index (0–500 scale). Displays current values on OLED. Publishes the fused reading to agents/<id>/telemetry every 30 seconds. Publishes an event to agents/<id>/event immediately when IAQ crosses 150 (poor air quality threshold). Subscribes to agents/<id>/cmd for threshold updates. Maintains a rolling 1-hour average in SRAM (12 bytes per 5-minute bucket × 12 buckets = 144 bytes).
Note on RP2040 memory: The RP2040 has 264 KB SRAM and no built-in flash — all code and data runs from external QSPI flash with execute-in-place. This agent requires approximately 80–120 KB of SRAM for the Pico SDK, lwIP, MQTT session, BSEC library, and application buffers.
Agent pattern: Pattern 3 (sensor fusion: BME680 raw → IAQ) + Pattern 2 (threshold with explanation).
Repository: (repo link TBD)
Example 5 — nRF52840 BLE-to-MQTT Gateway Agent
Hardware:
- Nordic nRF52840 DK or Seeed XIAO nRF52840
- Zephyr RTOS with BLE + USB CDC-ACM
Libraries:
- Zephyr ≥3.6 (Bluetooth LE, MQTT, networking)
- Zephyr sensor subsystem (simulated or external I2C sensor)
What the agent does:
Operates as a BLE peripheral and MQTT gateway simultaneously. Scans for BLE advertisements from a set of known sensor beacons (registered by MAC address in its allow-list). For each known beacon advertisement, parses the manufacturer-specific data containing temperature and battery level. Batches readings from up to 16 beacons over a 10-second window. Connects to an MQTT broker via USB-tethered network or on-board Wi-Fi companion chip. Publishes a batch JSON payload containing all beacon readings to agents/gateway-01/beacon-data. Provides a local state machine: beacons not heard within 5 minutes are flagged as offline in the next publish.
Agent pattern: Pattern 3 (aggregation/fusion from multiple sources) at gateway level.
Repository: (repo link TBD)
Example 6 — STM32L476 Predictive Maintenance Agent (Low Power)
Hardware:
- STM32L476 Nucleo-64 (Cortex-M4F, 80 MHz, 128 KB SRAM)
- MPU-6050 IMU (I2C): accelerometer + gyroscope
- SIM800C GSM/GPRS module (UART)
Libraries:
- STM32CubeL4 HAL (FreeRTOS, I2C, UART, low-power modes)
- TensorFlow Lite Micro (Cortex-M4F build with CMSIS-NN)
- AT-command MQTT library for SIM800C
What the agent does:
Targets battery-powered equipment in locations without Wi-Fi — agricultural machinery, remote pumps. Samples the IMU at 200 Hz for 2 seconds every 60 seconds. Computes RMS and spectral centroid. Runs a TFLM anomaly detection model (~22 KB weights, ~18 KB activations). If anomaly score is below threshold: enters STM32 STOP2 mode (approximately 2 µA) until the next sample interval. If anomaly detected: wakes the SIM800C (takes ~5 seconds), establishes GPRS, publishes via MQTT over TCP, then powers down the SIM module. Full wake-to-publish cycle: approximately 12 seconds. Battery life on 3000 mAh: 6–12 months depending on anomaly frequency.
Note on STM32L476 memory: The ML model + activations fit in the 128 KB SRAM (22 KB weights + 18 KB activations + 30 KB TFLM runtime + 30 KB OS/buffers ≈ 100 KB, within budget).
Agent pattern: Pattern 1 (anomaly detect) + low-power deep sleep between samples.
Repository: (repo link TBD)
Hardware and library summary
| Example | Board | Connectivity | ML | SRAM budget |
|---|---|---|---|---|
| 1 — Temp Anomaly | ESP32 | Wi-Fi / MQTT | None (statistical) | ~80 KB |
| 2 — Vibration Classifier | STM32H743 | Ethernet / MQTT | STM32Cube.AI (96 feat.) | ~300 KB |
| 3 — Voice + LLM Delegate | ESP32-S3 | Wi-Fi / HTTPS | EON (keyword spotting) | ~150 KB |
| 4 — Env Monitor | RP2040 (Pico W) | Wi-Fi / MQTT | None (BSEC2 algorithm) | ~100 KB |
| 5 — BLE Gateway | nRF52840 | BLE + MQTT | None | ~80 KB |
| 6 — Predictive Maint. | STM32L476 | GSM/GPRS / MQTT | TFLM anomaly (22 KB) | ~100 KB |
FAQ
Q: Are these examples tested against real hardware? The specifications and library choices are accurate. The code snippets in other pages on this site are written to be correct in principle. Full hardware-tested repositories will be linked as they are published.
Q: Can I adapt these for LoRaWAN instead of MQTT? Yes, with changes. Replace the MQTT client with a LoRaWAN stack (LMIC, Zephyr LoRaWAN). Adjust payload sizes — LoRaWAN DR0 (SF12 125 kHz) allows only 11 bytes per uplink. Use binary encoding (CBOR or custom bitpack) instead of JSON.
Q: Where are the repositories? Links will appear here as repositories are published. Subscribe to the newsletter or watch the ForestHub.ai GitHub organization for updates.