J'ai écrit un petit système d'exploitation en partant de zéro et fonctionnant sur un Arduino ou un ESP32. Il me permet de faire de la programmation et des projets DIY avec mes élèves. Il a une ligne de commande qui ressemble à MS-DOS ou à Linux… mais sinon c'est codé en C++ en utilisant l'IDE Arduino et ses librairies.
IoToS — Internet of Things micro Operating System
Pour créer l'OS, je suis parti de libs (lib LittleFS, ping, FTP, dir…) et d'exemples que j'ai rassemblés petit à petit pour les faire discuter ensemble.
Mon but… voir si c'était possible d'en écrire un tout seul… Et environ 2000 heures de codage et de tests plus tard, je l'utilise avec mes élèves pour créer des systèmes :
Prise IP — allumer ou éteindre un appareil depuis un navigateur web ou en ligne de commande
Caméra IP — LilyGo pour surveillance à distance connectée au réseau WiFi et photo déclenchée par un détecteur de mouvement
Station météo web — capteurs de température, d'humidité, de pression, consultables en ligne
Alarme capteur mouvement PIR — détection de mouvement avec envoi d'e-mail automatique
GTB — Gestion technique de bâtiment, commande de chauffage à distance
Projecteur DMX ou guirlande de LED RVB — commande de LED par Ethernet
Mais aussi, ce micro-OS permet d'expliquer aux élèves le fonctionnement d'un « OS » et ses limites.
En effet, l'Arduino est un microcontrôleur qui exécute un setup (une fois) et une loop qui tourne sans fin : c'est un automate !
Je voulais faire la liaison entre un automate sans OS et… un vrai petit OS. Mais entre les deux il n'y a rien :
Soit c'est trop limité, pas de ligne de commande (OS temps réel : RTOS)
Soit c'est trop gros ou écrit en assembleur…
Ici le code source est commenté et il est séparé en parties distinctes :
Un Boot Firmware (avant le setup)
Un Load Driver : le setup() : connexion réseau ou WiFi, portail captif, gestion du LCD…
Un Kernel : le loop()
Un CLI : shell_Cmdline.h
Des Apps : serveur web, FTP…
Grâce à l'IoToS, on a un petit OS : on peut voir le chaînon manquant entre l'automate et un vrai petit « OS ».
Ce micro OS permet d'avoir un support de service pour ses projets, je diffuse le code source pour que d'autres puissent l'utiliser et continuer à s'amuser en programmant, pour le nouveau Arduino R4 Minima et le Shield Ethernet v2, mais aussi l'ESP32 / 8266.
Les services disponibles :
Un CLI (Command Line Interface) en Serial ou Telnet offre un shell cmdLine interactif de type MS-DOS / UNIX.
Les commandes disponibles couvrent la configuration réseau (ip subnet gateway dhcp port web).
La gestion des fichiers SD (dir type del rename copie).
Les outils réseau (ping tracert netstat).
Ainsi que la sauvegarde en EEPROM de la configuration (save reload defaults reset).
IoToS embarque également un serveur WEB AJAX avec pages HTML stockées sur carte MicroSD (sur l'Ethernet Shield v2).
Un serveur FTP pour un accès aux fichiers de la carte MicroSD depuis le réseau.
Une synchronisation NTP, un datalogger CSV horodaté.
Un afficheur LCD ou un écran LCD TFT avec menu et boutons de configuration (selon version).
Le tout sur un ARM Cortex-M4 ou ESP32/8266 sans système d'exploitation temps réel, selon un modèle de noyau coopératif.
L'IoToS vient en soutien au système pour lequel l'Arduino est câblé (prise IP, station Météo, caméra IP, DMX, Alarme PIR…)
Le code métier est compilé avec IoToS dans le même firmware.
La prise IP (commande de LED par page WEB) constitue le système minimal de référence.
Pour intégrer votre propre système DIY, IoToS est conçu pour être étendu : ajoutez vos commandes CLI, vos pages WEB et vos drivers dans les fichiers .h prévus à cet effet.
Licence : GNU LGPL v2.1 — usage libre y compris commercial, code applicatif propriétaire autorisé.
Micro OS pour Arduino UNO R4 Minima (Renesas RA4M1 / ARM Cortex-M4) + Ethernet Shield v2 (W5500).
Transforme la carte en nœud réseau complet : CLI Serial/Telnet, serveur WEB AJAX, FTP, Datalogger NTP, ping/tracert/netstat, EEPROM.
\Mes Documents\Arduino\libraries\| Commande | Argument | Description |
|---|---|---|
| Affiche la configuration complète (IP, services, état) | ||
| name | Changer le nom du système | |
| LED | on/off | Allumer / éteindre la LED |
| WEB | on/off | Démarrer / arrêter le serveur WEB |
| FTP | on/off | Démarrer / arrêter le serveur FTP |
| ram | RAM disponible | |
| ping | xx.xx.xx.xx | Ping complet ICMP |
| tracert | <URL> | Traceroute réseau |
| netstat | État des connexions réseau | |
| version | Version et infos debug |
| Commande | Argument | Description |
|---|---|---|
| dir | Liste les fichiers sur la MicroSD | |
| type | <nom.ext> | Affiche le contenu d'un fichier |
| del | <nom> | Supprime un fichier |
| rename | <old> <new> | Renomme un fichier |
| copie | <src> <dst> | Copie un fichier |
| edit | <texte> | Ajoute une ligne (max 100 car.) |
| create | <nom.ext> | Crée un fichier avec en-tête Excel |
| select | <nom.ext> | Sélectionne le fichier Datalogger actif |
| datalogger | on/off | Active / désactive l'enregistrement |
| Commande | Argument | Description |
|---|---|---|
| ip | 192.168.0.x | Définir l'adresse IP |
| subnet | 255.255.255.0 | Masque de sous-réseau |
| gateway | 192.168.0.x | Passerelle |
| mac | DE:AD:BE:EF:FE:ED | Adresse MAC |
| dhcp | on/off | Activer / désactiver le DHCP |
| port | 0–65535 | Port du serveur WEB (défaut 80) |
| Commande | Description |
|---|---|
| save | Sauvegarde la configuration en EEPROM |
| reload | Recharge la configuration depuis l'EEPROM |
| defaults | Remet la config d'usine (192.168.0.10) |
| reset | Redémarre l'Arduino avec la config EEPROM |
| Commande | Argument | Description |
|---|---|---|
| loginWEB | on/off | Activer / désactiver l'auth sur le site WEB |
| login-passWEB | Changer Login:Password (base64 — base64encode.org) | |
| loginFTP | Changer le login FTP | |
| passwordFTP | Changer le password FTP |
Serial : 115200 bps · NL+CR · Putty Flow control → None
Telnet : Host = IP Arduino · Port 23 · Décocher "Return key sends Telnet New Line"
FTP (FileZilla) : Auth type = Compte · Limiter à 1 connexion simultanée · Login/pass par défaut : arduino / arduino
| Bibliothèque | Version | Licence | Modifiée | Obligation principale |
|---|---|---|---|---|
| Arduino-MemoryFree | — | Beerware | Non | Aucune |
| EthernetICMP | — | LGPL v2.1 | OUI | Distribuer .h/.cpp modifiés |
| NTPClient2 | — | MIT | OUI | Conserver copyright |
| SdFat | v2.3.1 | MIT | Non | Conserver copyright |
| SimpleFTPServer | — | MIT | OUI | Conserver copyright |
| U8g2 (code) | 2.35.30 | BSD 2-Clause | Non | Conserver copyright |
| U8g2 (polices) | 2.35.30 | OFL/MIT/BSD | Non | Vérifier par police |
| CmdLineTelnet | v20 | — | OUI | Voir dépôt d'origine |
Auteur : Jean-Marc Biechy — Institution Saint-Jean, École d'Électronique Informatique et Réseau — Colmar, France — 01/03/2026
Contact : radiobiechy@gmail.com — Fourni en l'état sans garantie.
Version d'IoToS avec écran LCD TFT I2C GM12864-59N VER 2.0 (ST7567S) via librairie U8g2 v2.35.30.
Menu rotatif 5 lignes navigable avec 3 boutons sur interruptions : (−) (OK) (+).
0x3F × 2(−) sur D2 · Bouton (OK) sur D8 · Bouton (+) sur D3U8G2_ST7567_ENH_DG128064I_F_SW_I2C
Version d'IoToS avec écran LCD I2C Blacklight RGB intégré — menu rotatif 5 lignes, 3 boutons OK / (+) / (−) sur interruptions.
U8g2 v2.35.30 (écran ST7567S)
Version d'IoToS pour ESP32 Wemos D1 R32 (Wroom 32 · 4 Mo Flash) — CLI Serial/Telnet, Bluetooth, portail captif, LittleFS.
https://dl.espressif.com/dl/package_esp32_index.jsonSchémas de partition disponibles :
| Partition Scheme | APP (OTA0) | APP (OTA1) | LittleFS | OTA |
|---|---|---|---|---|
| Default 4MB with SPIFFS | 1.250 MB | 1.250 MB | 1.375 MB | Oui |
| No OTA (Large App) | 2.000 MB | — | 1.875 MB | Non |
| Minimal SPIFFS (Large App with OTA) | 1.875 MB | 1.875 MB | 0.120 MB | Oui |
/data dans l'ESP en partition LittleFSCtrl + Shift + P → "Upload LittleFS to Pico/ESP8266/ESP32"upload_littleFS_WEMOS_ESP32_D1_R32_v6.bat
ESP32 Wrover Module — LiLyGO CAMERA MIC 16 Mo (Flash total 16 777 216 octets) — Commande par page WEB.
OTA programmation par WiFi ✓
https://dl.espressif.com/dl/package_esp32_index.json/data dans l'ESP en partition LittleFStools\ dans C:\Program Files\Arduino\, y déposer ESP32FS-1.0.zip décompresséFichier : C:\Users\<User>\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\boards.txt
Ajouter sous la ligne esp32wrover.name=ESP32 Wrover Module :
esp32wrover.menu.PartitionScheme.lilygo_16mb_ota=LilyGO 16MB OTA (2MB APP/11.5MB SPIFFS) esp32wrover.menu.PartitionScheme.lilygo_16mb_ota.build.partitions=LilyGO_16Mo_OTA_(2MbAPP_11.5MbSPIFFS) esp32wrover.menu.PartitionScheme.lilygo_16mb_ota.upload.maximum_size=2097152
Créer le fichier LilyGO_16Mo_OTA_(2MbAPP_11.5MbSPIFFS).csv dans :
...\packages\esp32\hardware\esp32\1.0.6\tools\partitions\
# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, app0, app, ota_0, 0x10000, 0x200000, app1, app, ota_1, 0x210000,0x200000, spiffs, data, spiffs, 0x410000,0xBF0000,
| Commande | Argument | Description |
|---|---|---|
| help | Aide commandes disponibles (man ou ?) | |
| resolvideo | Résolution vidéo : QQVGA / QVGA / VGA / SVGA / XGA / UXGA | |
| resolphoto | Résolution photo : QQVGA / QVGA / VGA / SVGA / XGA / UXGA | |
| pir | on/off | Capteur PIR (détecteur de mouvement) → photo en LittleFS |
| timephoto | <sec> | Temps entre deux photos en secondes |
| resetcompteur | Reset compteur photo (supprimer les photos avant) | |
| Oled | on/off | Écran OLED ON / OFF |
| WEB | on/off | Serveur WEB ON / OFF |
| FTP | on/off | Serveur FTP ON / OFF |
| ram | RAM disponible | |
| ping | xx.xx.xx.xx | Ping ICMP |
| Commande | Argument | Description |
|---|---|---|
| datalogger | on/off | Activation de l'enregistrement des actions |
| create | </nom.ext> | Création fichier avec en-tête Excel |
| select | </nom.ext> | Sélection du fichier datalogger actif |
⚠️ Mettre un / devant chaque nom de fichier
| Commande | Argument | Description |
|---|---|---|
| dir | Informations fichiers sur le LittleFS | |
| rename | </old> </new> | Renomme un fichier |
| del | </nom> | Efface un fichier |
| type | </nom> | Affiche le contenu d'un fichier |
| edit | <texte> | Ajoute une ligne (max 100 caractères) |
| copie | </src> </dst> | Copie un fichier |
| format | Formate la partition LittleFS (⚠️ irréversible) |
| Commande | Argument | Description |
|---|---|---|
| wifi | on/off | Démarrer / arrêter le module WiFi |
| infowifi | Informations connexion WiFi | |
| SSID | <nom> | Nom du réseau WiFi (max 40 caractères) |
| wifipass | <secret> | Mot de passe WiFi (max 40 caractères) |
| Affiche la configuration courante | ||
| mac | <MAC> | Adresse MAC (défaut : DE:AD:BE:EF:FE:ED) |
| dhcp | on/off | Activer / désactiver le DHCP |
| ip | <IP> | Adresse IP (ex : ip 192.168.0.66) |
| subnet | <IP> | Masque de sous-réseau |
| gateway | <IP> | Passerelle |
| port | 0–65535 | Port WEB (défaut 80) |
| Commande | Argument | Description |
|---|---|---|
| loginWEB | on/off | Activer / désactiver l'auth sur le site WEB |
| login-passWEB | Changer Login:Password (base64 — base64encode.org) | |
| loginFTP | Changer le login FTP | |
| passwordFTP | Changer le password FTP |
| Commande | Description |
|---|---|
| reload | Recharge la configuration depuis l'EEPROM |
| defaults | Reset usine (192.168.0.10) |
| save | Sauvegarde la configuration en EEPROM |
| loadconf | Charge la configuration depuis un fichier LittleFS |
| saveconf | Sauve la configuration dans un fichier LittleFS |
| reset | Redémarre l'Arduino avec la config EEPROM |
| debug | Affichage de variables DEBUG |
Exemple — changer l'IP : ip 192.168.0.2 puis save puis reset
IoToS est un micro-système embarqué pour Arduino UNO R4 Minima. Il reçoit les données météo d'une station distante par radio LoRa 868 MHz et les publie sur un serveur WEB accessible depuis le réseau local.
Deux sources de données sont affichées en temps réel :
– Les capteurs locaux via LoRa (vent, pluie, température, humidité, pression, direction girouette)
– La météo Internet via Open-Meteo (prévisions, ressentie, rafales, visibilité, code WMO…)
Capteurs Platine Grove UNO R3 LoRa 868MHz UNO R4
physiques (Shield meteo) Emetteur Radio Recepteur
simplex
Anemometre +-------------+ +----------------+ ))) ((( +------------+
(RJ11 D) ----| RJ11 D |----|D2/INT1 LoRa | | | | I2C|--- LCD ST7567
| | | D6 RX |---TX---+ +----RX--|D0 RX |
Girouette | |----|A0->A1 D7 TX | | |
(RJ11 D) ----| | | | Grove LoRa | D8 |--- Bouton ok
+-------------+ | | 868MHz | D2 |--- Bouton +
Pluviometre +-------------+ |D4 | (D6/D7) (D0/D1) | D3 |--- Bouton -
(RJ11 G) ----| RJ11 G |----| | | |
+-------------+ | | | D6 |--- LED Reception
DHT22 Grove [===bleu===] ------|D5 | | |
LCD ST7567 [===blanc==] ------|A4 SDA | +------------+
(I2C) ------|A5 SCL | IoToS
LED emission [===rouge==] ------|D8 |
| |
[===noir===] ------|D7 TX |
+----------------+
Anémomètre — Girouette — Pluviomètre — Température — Humidité
| Port | Direction | Module | Remarque |
|---|---|---|---|
| D2 | ENTRÉE | Anémomètre (INT0 phys) | Branché D2, INT1 logique |
| D3 | — | (INT1 = lecture D2) | Décalage physique ! |
| D4 | ENTRÉE | Pluviomètre | RJ11 gauche, front desc. |
| D5 | ENTRÉE | DHT22 Grove (bleu) | 1-Wire temp+hum |
| D6 | ENTRÉE | Grove LoRa RX | SoftwareSerial RX |
| D7 | SORTIE | Grove LoRa TX | SoftwareSerial TX |
| D8 | SORTIE | LED émission | HIGH pendant émission LoRa |
| A0 | ENTRÉE | Girouette (physique) | Détectée sur A1 ! |
| A1 | ENTRÉE | Girouette (logique) | Décalage physique ! |
| A4 | ENTRÉE | LCD SDA (I2C) | Wire.h |
| A5 | ENTRÉE | LCD SCL (I2C) | Wire.h |
Les fils jaunes du connecteur Grove ne correspondent pas aux étiquettes imprimées sur la platine météo. Les broches physiques sont décalées d'un port.
pluviometre Anemometre Girouette
D4 D2 A0
| | |
┌─────────────────────────────────────────────────┐
│ Platine Grove Station Meteo │
│ https://www.lextronic.fr/P38811-... │
│ │
│ Connecteur RJ11 GAUCHE Connecteur RJ11 DROIT │
│ ┌───────────────┐ ┌───────────────────┐ │
│ │ Pluviometre │ │ Girouette+Anemo │ │
│ │ RJ11 G │ │ RJ11 D │ │
│ └───────┬───────┘ └────────┬──────────┘ │
└──────────┼─────────────────────────┼────────────┘
│ │
PORT D4 PORT A0 (→ detecte A1)
PORT D2 (→ INT1 logique)
| Module | Port Grove | Fils | Connexion |
|---|---|---|---|
| Grove LoRa 868MHz | D6/D7 | Jaune→D6 (RX) · Blanc→D7 (TX) | SoftwareSerial |
| Grove DHT22 (bleu) | D5 | Jaune→D5 (1-Wire) | Temp + Humidité |
| Grove LED (rouge) | D8 | Jaune→D8 (HIGH=allumée) | Émission LoRa |
| LCD GM12864I I2C | I2C direct | SDA→A4 · SCL→A5 | ST7567 — pas Grove |
| Port | Direction | Module |
|---|---|---|
| D8 | ENTRÉE | Bouton OK |
| D2 | ENTRÉE | Bouton (+) interruption |
| D3 | ENTRÉE | Bouton (−) interruption |
| D5 | SORTIE | Module LED Grove |
| D6 | SORTIE | LED réception LoRa |
| LED_BUILTIN | SORTIE | Serveur WEB démarré OK |
| SDA/SCL | I2C | Écran LCD ST7567S |
| Ethernet Shield v2 | SPI+SD | W5500 — MicroSD |
\Mes Documents\Arduino\libraries\La station émettrice est équipée d'une platine Grove Base Shield sur laquelle sont connectés les capteurs physiques :
Les données sont encodées dans une trame (STX | ID | LEN | DATA | CRC | ETX) et émises toutes les secondes par radio LoRa 868 MHz vers le récepteur IoToS.
| Capteur | Unité | Plage |
|---|---|---|
| Vitesse vent | km/h | 0 à 255 |
| Direction girouette | 1 à 8 | N NE E SE S SO O NO |
| Pluviomètre | mm | 0 à 255 |
| Température | °C | −128 à +127 |
| Humidité | %RH | 0 à 100 |
| Pression | hPa | 900 à 1155 |
| RSSI | dBm | qualité signal radio |
Le shell CLI est accessible via le port Serial USB ou en Telnet. La configuration se fait en trois étapes :
Définir l'adresse IP, le masque et la passerelle puis sauvegarder et redémarrer l'Arduino.
| Commande | Description |
|---|---|
ip 192.168.0.10 | Adresse IP statique |
subnet 255.255.255.0 | Masque de sous-réseau |
gateway 192.168.0.1 | Passerelle |
dhcp on / off | Laisser le DHCP attribuer l'IP |
port 80 | Port du serveur WEB |
save | Sauvegarder en EEPROM |
reset | Redémarrer avec la nouvelle config |
Indiquer les coordonnées GPS du site d'installation pour que le système interroge la bonne zone géographique.
| Commande | Description |
|---|---|
GPS 48.08 7.36 | Latitude et longitude |
GPS 48.57 7.75 | Exemple pour Strasbourg |
GPSville Colmar | Ville prédéfinie : Colmar, Strasbourg, Mulhouse, Sélestat, Nancy, Lyon, Paris |
| Commande | Description |
|---|---|
print | Affiche toute la configuration |
| Accès | Détail |
|---|---|
| Navigateur | http://<IP de l'Arduino>/ |
| Page météo temps réel | index.htm |
| Configuration réseau | ConfIP.htm |
| Auth | Login : user / Mot de passe : pass (Base64) |
| FTP FileZilla | 1 connexion simultanée max |