Du Raspberry Pi à notre propre carte.
Python, et un écran e-paper : la preuve que l’image s’affiche.
Une puce qui sait dormir profondément.
Notre propre carte, dans le boîtier imprimé en 3D, puis usiné en CNC.
Organiser un logiciel stateful, en C.
Pas de Linux, pas de processus, pas de garbage collector.
make dev-buildEn backend, on lit un JSON. Ici, on regarde l’objet réagir.
components/features/
├── display/
│ ├── ctrl_ble_display Bluetooth
│ ├── ctrl_http_display HTTP
│ ├── ctrl_mqtt_display MQTT
│ ├── ctrl_cli_display console
│ ├── svc_display le cœur, et sa state machine
│ ├── drv_epd_el133uf3 l’écran UF3
│ └── drv_epd_el133uf1 l’écran UF1, une autre variante
└── playlist/
├── ctrl_ble_playlist Bluetooth
├── ctrl_http_playlist HTTP
├── svc_playlist le cœur
└── repo_playlist les playlists, sur la carte SD
Une feature, un dossier : controllers, service, repository, drivers.
chaque feature s’enregistre sur
Dans une feature, les appels descendent. Entre features, des événements.
if (!fsm_try(&s_fsm, QUEUED, "show", src)) return ESP_ERR_NOT_FINISHED;
20 machines, 67 états. Combinés : plus de 5 milliards.
sdkconfig.defaults commun à toutes les cartes
sdkconfig.esp32s3-proto1.EL133UF3 puce · révision · écran
sdkconfig.esp32s3-proto2.EL133UF3 + LED avant, buzzer
make dev-build BOARD=esp32s3-proto2.EL133UF3
Une carte, un profil. Un écran, un driver. Le reste ne bouge pas.
Tenir un an sur une charge.
Un Nordic PPK2, en série avec la batterie, USB débranché.
Et pour y rester : des interruptions plutôt que du polling, et un nom par raison de rester éveillé.
Corriger un cadre déjà installé chez quelqu’un.
A · v1actif
B · v2écriture
A · v1en attente
B · v2probation
A · v1secours
B · v2actif
A · v1actif
B · v2rejeté
Par Bluetooth : 1,9 Mo en 30 s. Ou tout seul, en HTTP.
Seulement en développement, ou si un client l’active pour qu’on l’aide. Désactivée en production.
D’une idée à un Kickstarter, en 15 mois.
- Ce qui change quand on ne peut plus juste redéployer
- Backend et plateforme : du code déployé en quelques secondes - Platform engineer à la Banque Nationale : GitHub pour des milliers d'ingénieurs - Sablier : open source, plus de 3 000 étoiles - Reeveel depuis 2025 : on fabrique un objet
- Le résultat final d'abord, le chemin ensuite - E-paper couleur 13,3", ESP32, Bluetooth et Wi-Fi - NFC, accéléromètre, bouton caché, microSD, passe-partout aimanté - Et tout ça sur batterie : c'est ce qui rend le reste difficile
- Comme un Kindle, en couleur et en grand - Réfléchit la lumière : lisible en plein soleil - Une image fixe ne consomme rien, en changer coûte (on y revient)
- Un an : dormir presque tout le temps - Bluetooth, sans compte ni cloud. Le Wi-Fi en option : tout marche sans réseau - Mise à jour : on livrera des bugs, sans jamais bloquer un cadre - Périphériques : chacun consomme, chacun peut réveiller le cadre - De l'idée au Kickstarter : 15 mois
- Raspberry Pi et Python : l'écran marche, rien de plus - Un proof of concept, fait pour être jeté
- Une ESP32 câblée à la main - Le vrai critère apparaît : savoir dormir profondément, presque tout le temps
- Boîtier : un cadre du commerce, puis notre imprimante 3D (4 versions en 2 semaines) - Le fabricant prend le relais : impression 3D, puis usinage CNC - Sur la photo : la batterie, notre carte, la nappe de l'écran - Les aimants du passe-partout : premier essai raté, couche trop fine
- Le framework d'Espressif, en C, bas niveau - Pas de Linux, pas de processus, pas de GC : des tâches, la mémoire à la main
- Backend : coder, relancer, curl, lire un JSON - Ici : compiler, flasher en USB, regarder l'écran, tourner le cadre, approcher le téléphone - La console série : on tape une commande, la carte répond - Un build de dev instrumenté, un build de prod pour mesurer - [ressenti : voir un objet réagir à son code] - Transition : comment on organise un vrai logiciel là-dessus ?
- La vraie difficulté : un logiciel stateful, l'état vit dans la puce - Une image peut venir de 5 endroits, parfois en même temps - On range par feature : un dossier - Display : 4 controllers, 1 service, 1 driver par écran (UF3, UF1) - Playlist : un repository sur la carte SD
- Le vertical, les features. L'horizontal, la plateforme - Configuré une fois : Bluetooth, HTTP, console, carte SD, énergie - Chaque feature vient s'y enregistrer - Règle : on n'entre dans la plateforme que quand une 2e feature en a besoin
- Display publie DISPLAYED, la playlist passe à l'image suivante - Storage publie MOUNTED, le repository retrouve ses fichiers - Dans une feature : des appels. Entre features : des événements - Comme un bus de messages, dans la même puce
- Controller, Service, Repository : comme dans Spring - Plus une couche : le Driver, qui parle au matériel - Controller sans logique : une règle métier écrite une seule fois - Les appels descendent, les événements remontent - Vérifié par le build et un linter, pas en review
- Avant : un booléen "busy" quelque part, et on devinait - L'animation : Bluetooth accepté, HTTP et console refusés pendant RENDERING, puis HTTP passe - Chaque refus est loggé, pas de verrou dans le code métier - 20 machines, 67 états : 5 milliards de combinaisons, l'explosion combinatoire - C'est pour ça qu'on éteint et rallume nos appareils - Chaque machine reste petite, testable seule
- Une carte, un profil : la puce, la révision, l'écran - De proto1 à proto2 : 4 lignes (LED avant, buzzer) - Un nouvel écran, c'est un nouveau driver. Le reste ne bouge pas - En backend : un adapter par fournisseur
- En backend, la latence. Ici, des microampères - Un multimètre ne suffit pas : un PPK2 en série avec la batterie - La mesure : 4,23 mA en moyenne, des pics à 72 mA, chacun est un réveil - De 10 µA à 150 mA : 4 ordres de grandeur sur la même courbe - USB débranché : il fausse la mesure
- Le point de départ : la puce allumée qui attend, réglage par défaut - Chaque levier s'ajoute au précédent : ÷ 2, puis ÷ 115, puis ÷ 3 900 - Chiffres de la puce seule : la carte, l'écran et la radio ajoutent le reste - Interruptions : sinon on se réveille pour vérifier les capteurs - Deep sleep : chaque réveil repart de zéro, le "éteindre et rallumer" gratuit - 3 niveaux de présence : connecté, éveillé (s'annonce en Bluetooth), endormi (radio coupée) - Chaque composant qui garde la puce éveillée doit dire pourquoi - Un rafraîchissement coûte 4 fois plus que prévu : 1 ou 2 images par jour, une décision produit
- La mise à jour à distance, c'est du blue-green : vous connaissez déjà - Deux emplacements : on écrit B pendant que A tourne, on redémarre, B en probation - Échec : retour automatique sur A - Pas d'orchestrateur : le firmware se valide lui-même - Deux chemins : le téléphone en Bluetooth, ou le cadre seul en HTTP
- Au bureau, la console série. Chez quelqu'un, impossible - OpenTelemetry, comme vos services : logs, crashs, métriques - Notre propre passerelle : pas de clé d'API dans un firmware public - Seulement en dev, ou si un client l'active pour qu'on l'aide : désactivée en production - Le dashboard : versions, raisons de réveil, crashs, batterie - La télémétrie réveille le cadre une fois par jour au plus - Les versions cohabitent : on débugge plusieurs versions à la fois
- On a vu le comment. Maintenant, où on en est
- Juillet 2025 : l'idée - 4 prototypes, les 2 derniers avec le fabricant - Le Kickstarter est en ligne depuis le 14 octobre - La suite : tests, production cet hiver, livraisons au printemps - Pour moi : mettre à jour des cadres chez des gens que je ne connais pas
- Merci, place aux questions