🛠 Nœud IoT de datalogging : capteurs sur le M4, stockage et transport en conteneur
Objectives
The X8 signature use case, documented by the official datalogging-iot tutorial: sensors connect on the MCU side (the STM32H747 exposes 8 ADC inputs with separate VREF, 3 SPI, 4 PWM outputs, 7 GPIO on the Arduino side — plus the SoC's 3 ADCs/2 DACs/comparators and RNG), while the Docker container on the Linux side handles storage, queuing, and transport (MQTT/HTTP). Separation of responsibilities: real-time and analog tasks on the M4, memory (2 GB LPDDR4, 16 GB eMMC), networking, and modern libraries on the A53.
Hardware
- 1 × Arduino Portenta X8 + carrier board (Breakout/Max Carrier) to access sensor pins
- 1 × analog sensor (probe, potentiometer) on an M4-side ADC input, or a digital sensor on SPI/I²C
- Active IP network (networking tutorial) for transport
- "Arduino Mbed OS Portenta Boards" core + adb
- A test MQTT broker (or a simple HTTP server) on the LAN
Complete Code
// capteur_m4.ino — acquisition sur le M4, exposition RPC au conteneur
#include "SerialRPC.h"
#include "RPC.h"
const int BROCHE_CAPTEUR = A0; // >
// Le conteneur Linux appelle cette fonction a son rythme d'echantillonnage
int readSensor {
long somme = 0;
for (int i = 0; i < 16; i++) { somme += analogRead(BROCHE_CAPTEUR); }
return (int)(somme / 16); // moyenne de 16 lectures
}
void setup {
Serial.begin(115200);
RPC.bind("readSensor", readSensor);
}
void loop { delay(50); }
# Cote Linux : un conteneur de logging qui appelle readSensor via le
# broker m4-proxy (5001), journalise sur l'eMMC et publie en MQTT.
# Image de depart officielle pour le pont Python<->M4 :
docker run -d --name logger \
--restart unless-stopped \
-p 5002-5020:5002-5020 \
-v /home/fio/logs:/data \
--device /dev/ttyGS0 \
arduino/python-rpc-serial
# >
# (lecture RPC + file + MQTT) — reproduis-le depuis le tuto officiel.
Expected Verification
The container calls readSensor at regular intervals, values scroll through the log on the eMMC (folder mounted from the host) and arrive at the MQTT broker. The benefit of this setup: the M4 knows neither TCP nor JSON — it exposes a function; everything else (buffering during network outages, TLS, formats) lives in the container, which is replaceable and updated via OTA without touching the firmware.
Common Errors
- Running the full network stack on the M4: it is possible but counterproductive on the X8 — the official design places transport on the Linux side; the M4 remains a real-time I/O peripheral.
readSensorblocking: an RPC call must remain short; if you average over 10,000 samples, the Python call waits and the container's watchdog may complain.- Data loss during outages:
--restart unless-stoppedrestarts the container, but only a queue persisted on the eMMC (file, SQLite) survives reboots — do not rely solely on a memory buffer. - Confusing the ADCs: the X8 datasheet table (8 ADC inputs with separate VREF on the M4 side) does not match the full STM32H747 pinout — wire according to the carrier board and the pinout page, not the SoC datasheet.
- Sensor power supply: the board pins are 3.3 V, 8 mA max per pin — a 5 V or power-hungry sensor requires a level-shifting/translation stage, never direct connection.
- >
- >
Other tutorials for this board
- Premiers pas : comprendre le monstre à 9 cœurs et entrer dans Linux via ADB
- Premier sketch sur le cœur M4 : le blink qui se flash par ADB
- Docker dès la sortie de l'emballage : premier conteneur sur le Linux embarqué
- Pont Linux ↔ Arduino : appeler des fonctions du sketch M4 depuis Python (RPC)
- Mettre la X8 en réseau : Wi-Fi du Murata 1DX et Gigabit Ethernet sur porteuse
- Le firmware caché : mettre à jour le bridge STM32H7 M7 qui expose les périphériques à Linux
Code examples for this board
etat-systeme.shBashgpio-libgpiod.shBashpython-gpio.pyPythondocker-hello.shBashflasher-core-arduino.shBashwifi-nmcli.shBash