J'ai confié la gestion de mes fraisiers à ChatGPT !
Mise en contexte
Nous sommes en avril, les beaux jours arrivent et avec eux, comme une petite envie de jardiner, c’est pourquoi j’ai voulu planter 6 jolis fraisiers dans une jardinière ensoleillée. Jusqu’ici rien de novateur : il faut bien avouer que c’est plaisant de s’occuper d’une telle plantation. Et puis les jours passent, on oublie de les arroser et, pour combler le déficit, on arrose énormément au risque de voir les plants pourrir…
Et si on mettait en place un système pour automatiser cette tâche ? Et pourquoi ne pas faire appel à l’intelligence artificielle pour réaliser cela ? Alors oui, il existe pléthore de kits ou de tutos tout faits pour automatiser l’arrosage. Cela existe depuis des décennies, fonctionne très bien et a été éprouvé (et je pense que dans mon cas, cela aurait été largement suffisant). Mais de nos jours, on voit de l’IA partout - même là où il n’y en a pas - alors pourquoi ne pas essayer d’en mettre ici aussi ?
Comment faire ?
Utiliser un modèle de langage pour réaliser la gestion de nos fraisiers implique qu’on ne peut pas rendre notre système électronique complètement indépendant. Même si des Raspberry Pi récents, dotés d’une certaine quantité de RAM, permettent de faire tourner des LLM légers, il ne faut pas oublier que nous ne souhaitons pas relier le système au secteur (ici j’ai juste trouvé dans mes armoires une batterie 600mAh et un panneau solaire Reolink qui fournit au max 5W). Donc si nous consommons toute la batterie uniquement pour prendre la décision, c’est problématique.
Et puis, on aimerait aussi avoir un retour direct de l’évolution de la plantation ! Nous allons donc devoir intégrer notre module dans notre maison connectée sur Home Assistant.
Pour ceux qui ne connaissent pas Home Assistant, c’est un framework complet pour gérer sa domotique, un peu comme Google Home, sauf qu’ici vous avez le contrôle sur tout de A à Z. À noter qu’Home Assistant se déploie comme un OS complet, c’est pourquoi l’écrasante majorité des gens le déploie sur Raspberry Pi. Mais si comme moi vous avez un mini-PC sous Linux Server et que vous souhaitez continuer à utiliser votre serveur pour d’autres processus, je vous conseille de le déployer dans une machine virtuelle via Virtual Box Manage. À noter que cela prendra minimum 2 Go de RAM sur votre machine tout de même, et cela peut augmenter avec des intégrations. Enfin bref, Home Assistant est un outil passionnant que j’ai découvert récemment, cela mériterait un article à part entière, leur doc est bien fournie, n’hésitez pas à vous y référer.
En réalité, Home Assistant fait partie du mouvement de l’Open Home Association qui regroupe toutes les alternatives open source sérieuses pour l’automatisation connectée, et dont vous l’aurez compris, Home Assistant est au centre.
Mais gardons en tête notre objectif initial : ce qui nous intéresse ici, c’est d’intégrer un module à notre maison connectée. Comme vous le savez peut-être, je suis un véritable fan des ESP32, j’en utilise vraiment partout… et bien cela tombe bien car il existe un outil très connu nommé “ESPHome” qui permet de produire un firmware via un simple fichier de configuration YAML pour intégrer nos MCU nativement dans Home Assistant (HA).
Pareil, ici aussi, je vais éviter de trop rentrer dans les détails, mais en installant l’appli ESPHome Builder dans notre interface HA, cela met en place le convertisseur fichier de config YAML vers code C++, le toolchain de compilation pour les micro-contrôleurs supportés et un logger.
La première étape consiste à fournir les credentials sur le Wifi auquel on souhaite que nos ESPs soient connectés, et ensuite on ajoute tout ce qu’on veut.
Le câblage et la configuration électronique
La partie de pompage
Nous allons maintenant passer en revue tous les éléments mis en place pour ce projet. Étant donné que l’on souhaite mettre en place un système d’arrosage, il convient de mettre en place une pompe électrique 5V. Ici j’utilise une simple pompe d’aquarium mais qui fait très bien l’affaire. Pour la commander on utilise un relais Songle SRD 5V. Le câblage resemble donc à ceci :
Avec ce câblage, il suffit de mettre au niveau haut le GPIO câblé sur le transistor NPN. Dans mon cas, ce sera le GPIO 16. Ensuite, je me suis dit qu’un arrosage de 8 secondes est suffisant pour la petite jardinière utilisée ici. Bien sûr, vous êtes libre de modifier cette valeur en fonction de vos besoins, mais selon moi, il est plus intéressant de faire plusieurs arrosages courts espacés dans le temps, plutôt qu’un arrosage long de plusieurs dizaines de secondes qui pourrait vider votre batterie très rapidement par temps couvert.
On se retrouve donc avec la configuration suivante :
switch:
- platform: gpio
name: "Pompe à eau"
internal: true
id: mainpump
pin: GPIO16
restore_mode: ALWAYS_OFF
- platform: template
name: "Arrosage"
icon: "mdi:watering-can"
turn_on_action:
- switch.turn_on: mainpump
- delay: 8s
- switch.turn_off: mainpump
turn_off_action:
- switch.turn_off: mainpump
lambda: "return false;"
Pour résumer, on met en place un interrupteur qui agit directement sur la sortie du GPIO (qui n’apparaît pas dans l’interface HA du fait de la propriété internal). À chaque fois que l’utilisateur appuie sur le bouton “Arrosage”, le GPIO16 de l’ESP32 est mis à HIGH pendant 8s. Ici, le switch est défini pour se remettre seul à OFF suite à l’action.
Les capteurs
Pour que notre IA puisse prendre des décisions, il lui faut des données en entrée, c’est pourquoi deux capteurs au minimum sont nécessaires pour connaître la température et l’humidité de l’air, ainsi que celle du terreau. Personnellement, j’utilise le capteur DHT11 (prenez le DHT22 pour une meilleure précision) et un capteur capacitif d’humidité du sol (j’ai préféré ce dernier à un capteur résistif pour éviter la corrosion).
Ici, rien de sorcier, on alimente les deux capteurs en 3.3V et on relie le flux de données à des GPIOs munis d’ADC (dans mon cas 32 et 34). Le DHT11 est supporté nativement par ESPhome donc pas de configuration complexe, on récupère indépendamment l’humidité et la température :
sensor:
- platform: dht
pin: GPIO32
model: DHT11
temperature:
name: "Température Interne Serre"
icon: "mdi:sun-thermometer"
filters:
- median:
window_size: 2
send_every: 2
send_first_at: 1
humidity:
name: "Humidité Interne Serre"
icon: "mdi:water-percent"
filters:
- median:
window_size: 2
send_every: 2
send_first_at: 1
update_interval: 12s
Le second capteur demande un tout petit peu plus de travail : la sortie reçue initialement est la tension lue directement en sortie de l’ADC mais bien entendu, cela n’a pas vraiment de sens pour exprimer une humidité… On se doit donc de réaliser une interpolation linéaire de volts vers des pourcentages. Pour effectuer cela, prenez un verre d’eau, positionnez dans un premier temps le capteur en l’air loin de toute humidité, notez la tension lue : il s’agit de la tension équivalente à 0% d’humidité. Maintenant, plongez le capteur dans le verre d’eau, vous pouvez à présent lire la tension équivalente à 100% d’humidité.
Vous pouvez maintenant mettre en place le filtre adapté :
filters:
- calibrate_linear:
- 2.734 -> 0.0
- 1.027 -> 100.0
- clamp:
min_value: 0
max_value: 100
Dans mon cas, vous constatez que pour une humidité nulle, je lis 2.734V tandis que pour une humidité maximale, je lis 1.027V. Cela dépend du fabricant, donc ne recopiez pas mes valeurs sans tester vous-même ! On se retrouve donc finalement avec la configuration suivante :
sensor:
- platform: adc
pin: GPIO34
id: soil_moisture_voltage
name: "Humidité du sol (Voltage brut)"
internal: true
update_interval: 12s
attenuation: 12db
unit_of_measurement: "V"
accuracy_decimals: 3
filters:
- median:
window_size: 2
send_every: 2
send_first_at: 1
- platform: copy
source_id: soil_moisture_voltage
name: "Humidité du sol"
unit_of_measurement: "%"
icon: "mdi:thermometer-water"
accuracy_decimals: 0
filters:
- calibrate_linear:
- 2.734 -> 0.0
- 1.027 -> 100.0
- clamp:
min_value: 0
max_value: 100
Vous avez sans doute remarqué que j’ajoute un filtre median sur chaque capteur, je vais vous en expliquer la raison :
Comme je l’ai dit, ma batterie est assez petite, et sans apport durant la nuit par exemple, elle peut se vider avant le petit matin. Il convient donc de trouver des optimisations comme celle ci : le Wifi est très énergivore lors de la transmission, c’est d’ailleurs ce qui consomme le plus dans le cadre d’EspHome.
J’y reviendrai, mais du fait que le cycle de fonctionnement dure 30 secondes et que l’on demande des mesures toutes les 12 secondes (update_interval: 12s), mes capteurs ont le temps d’effectuer deux mesures, pas plus. Par conséquent, plutôt que d’envoyer via Wifi au serveur HA ces deux mesures une à une, je vais demander à l’ESP32 de me calculer la moyenne entre ces deux mesures et de m’envoyer le résultat. J’ai donc un unique paquet Wifi transmis, mais qui, en réalité, prend en compte deux mesures !
Les modes de fonctionnement
Comme expliqué dans le paragraphe précédent, nous voulons maximiser l’efficience du module, pour cela en électronique embarqué il est d’usage de mettre en place différents modes de fonctionnements, avec leurs fonctionnalités et consommations électriques relatives. Ici deux modes suffisent selon moi :
- un mode mesures, arrosage & communication
- un mode deep sleep
Vous l’avez sans doute deviné, mais le but du mode deep sleep est de sauvegarder un maximum la batterie, tandis que toutes les actions concrètes se déroulent dans l’autre mode. Bien entendu, ce n’est pas parce que ce mode est intitulé mesures, arrosage et communication que cela signifie que les trois auront lieu en même temps à chaque itération du mode (cela n’arrive que rarement).
Reste à décider le temps alloué pour chaque mode, ainsi que leurs fréquences respectives. Le but étant de minimiser le temps passé dans le mode actif, on décide que 30 secondes est suffisant, du fait que l’arrosage dure 8 secondes et que deux mesures suffisent. Maintenant pour ce qui est de la fréquence, c’est assez intéressant car il y a plusieurs limites : à la base je m’étais mis en tête que faire tourner l’ESP32 en mode actif 30 secondes à 7h00 et 30 secondes à 19h00 était suffisant, mais c’est une erreur ! Car dans ce cas on considère que en 30 secondes il y a l’enchaînement d’étapes suivant : on fait la mesure -> on interprète avec ChatGPT (via l’API d’OpenAI) -> on reçoit une réponse -> on arrose ou pas. Le problème ici c’est qu’il y a beaucoup trop d’inconnues, l’API peut être surchargée et mettre plus de 30 secondes à réagir, alors l’arrosage prévu n’a pas lieu. Et au quand bien même le modèle met moins de 30 secondes à répondre, s’il met plus de 22 secondes (sans compter le temps de mesure) l’arrosage sera coupé dans son action.
On pourrait me suggérer d’augmenter le temps d’exécution du mode actif, ce qui aura pour conséquence directe d’augmenter drastiquement la consommation totale, mais en réalité cela ne résoudrait pas le problème… Car ce que je ne vous ai pas encore dit c’est que j’utilise OpenClaw (interconnecté avec le skill home-assistant), pour récupérer les mesures, les envoyer à gpt5-mini et renvoyer la réponse au module. De ce fait, on utilise une tâche cron qui est exécutée à heure fixe, contrairement à l’ESP32 qui fonctionne via des délais basés sur son module RTC. On ne peut donc pas dire simplement à OpenClaw de se réveiller en même temps que l’ESP32. D’autant plus que dans l’optique de calquer l’ESP32 sur un cycle de 12 heures, il est nécessaire de le démarrer une première fois manuellement à 7h ou 19h, en essayant d’être le plus proche du temps universel coordonné (UTC) (à réitérer pour chaque mise à jour de notre firmware).
Vous comprenez donc la difficulté de la synchronisation en question. On pourrait par ailleurs aussi ajouter que Home Assistant ne maintient pas pendant 12 heures la valeur des capteurs. Donc si Open Claw s’exécute avant que les mesures soient complètement retransmises à notre serveur, les données lui apparaissent indisponibles. Je pense tout de même que ce soit configurable quelque part (je vais me renseigner) mais cela n’a pas de sens dans notre cas car l’état à 7h du matin ne doit pas influencer l’arrosage du soir.
Comment OpenClaw agit concrètement sur notre module ?
Donc, après avoir listé tous les points problématiques, il est temps de vous exposer la solution à laquelle j’ai abouti ! Il n’est plus question de passer en mode actif uniquement à 7h00 et 19h00, car comme nous l’avons vu, il est primordial d’obtenir un flux continu de données. Attention, par continu ici, je n’entends pas faire des mesures toutes les 10 secondes mais toutes les 30 minutes. Pour notre projet, c’est largement suffisant. Ceci fait, Home Assistant ne considère plus de discontinuité dans nos requêtes, ce qui permet à notre agent OpenCLaw de se baser au pire sur les mesures de la demi-heure précédente. Cependant, il reste un problème car maintenant nous pouvons fournir des mesures sans crainte, mais si notre agent veut allumer la pompe et que l’ESP32 est en deep-sleep, il y a un souci…
Et c’est ici que vient ma proposition : ce n’est peut-être pas la meilleure solution possible, mais plutôt que de demander à ChatGPT d’agir directement sur notre module, nous allons stocker l’information comme quoi un arrosage est nécessaire au niveau du serveur, qui lui est disponible en permanence, pour qu’il fournisse l’information à l’ESP32 dès qu’il se réveille, que la pompe 5V doit être allumée pendant 8s.
Comment faire cela ? C’est étonnamment simple. La première étape consiste à rajouter un indicateur de disponibilité dans le firmware même du micro-contrôleur :
binary_sensor:
- platform: status
name: "Online"
Cela va permettre de faire remonter au niveau du serveur si l’ESP32 est en deep sleep ou non.
La seconde étape consiste à créer dans votre espace Home Assistant un interrupteur binaire qui va permettre de stocker temporairement une demande d’arrosage.
Enfin, pour finaliser tout cela, on met en place une automatisation :
alias: Arrosage en attente
description: ""
triggers:
- trigger: state
entity_id:
- binary_sensor.mini_serre_module_online
to:
- "on"
conditions:
- condition: state
entity_id: input_boolean.arrosage_programme
state: "on"
actions:
- action: switch.turn_on
target:
entity_id: switch.mini_serre_module_arrosage
- delay:
seconds: 2
- action: input_boolean.turn_off
target:
entity_id: input_boolean.arrosage_programme
mode: single
Il faut comprendre ici que dès que le module de notre jardinière est en ligne et que le bouton “Arrosage programmé” (créé juste avant) est actif, alors la demande d’arrosage est directement communiquée à l’ESP32, et ensuite on remet à 0 le bouton “Arrosage programmé”.
Voilà nous avons résolu tout les soucis inhérents à la synchronisation entre OpenClaw et Home Assistant !
Comment configurer OpenClaw pour cette tâche ?
Le dernière étape est très simple : rendez-vous dans l’onglet “Tâches cron” de votre gateway OpenClaw, puis il suffit de créer une nouvelle tâche isolée avec les paramètres suivants :
- Expression de planification : 0 7,8,9,18,19,20 * * * (exemple pour arrosages possibles à 7h, 8h, 9h, 18h, 19h et 20h)
- Prompt de la tâche :
En tant que véritable jardinier, tu es chargé de gérer l’arrosage chaque jour le matin et le soir dans ma mini-serre qui contient <détails sur vos plants>. En fonction de l'humidité de l'air, de la température et de l'humidité du sol mesurées actuellement par les capteurs de mini_serre_module disponible via le skill home-assistant, ainsi que de la météo sur les 12 prochaines heures sur <votre ville>, décide si un arrosage est nécessaire, si c'est le cas, fais une action switch_on sur le input_boolean.arrosage_programme (toujours via le skill home-assistant).
Enfin envoie moi un résumé sous cette forme :
"
🍓 <PLANTES> - <DATE> - <HEURE>
💧 Humidité de l'air : <valeur_mesurée>%
🌡️ Température interne : <valeur_mesurée>°C
🌱 Humidité du sol : <valeur_mesurée>%
🚿 Arrosage : <OUI ou NON>
"
N'écris rien d'autre, la date doit être exprimée au format jj/mm/aaaa, l'heure à Paris (non UTC), toutes les valeurs insérées doivent êtres en gras.
- Choisissez votre canal de sortie pour les comptes-rendus (dans mon cas ce sera Telegram)
Résultats
Et voilà, vous avez à présent un système d’arrosage complètement automatisé qui se base sur un LLM.
Auteur : Romain MELLAZA
Date de publication : 26 Avril 2026