Après avoir découvert les capteurs au chapitre précédent, nous passons à l’action : construire un système d’irrigation automatique qui prend des décisions basées sur des mesures réelles du sol et de l’environnement. L’objectif est de maintenir l’humidité du sol dans une plage optimale, en minimisant la consommation d’eau.
Un système d’irrigation automatique repose sur trois couches :
| Couche | Composants | Rôle |
|---|---|---|
| Perception | Capteurs d’humidité, température, pluie | Mesurer l’état du sol et du climat |
| Décision | ESP32 + algorithme | Déterminer quand et combien arroser |
| Action | Électrovannes, pompe, relais | Délivrer l’eau aux zones ciblées |
[Capteur humidité] ──┐
[Capteur température] ─┤
[Pluviomètre] ─────────┤──→ [ESP32] ──→ [Module relais] ──→ [Électrovanne / Pompe]
[Horloge RTC] ─────────┤ │
[Seuils configurés] ───┘ └──→ [Stockage données / WiFi]
Une électrovanne (solenoid valve) contrôle le passage de l’eau. On distingue :
Point pratique : Pour un jardin, choisir une vanne NF 12V DC, débit ≥ 10 L/min, pression de travail 0,2–8 bar. Les vannes d’irrigation de type Gardena ou Hunter fonctionnent en 24V AC — elles nécessitent un transformateur.
Puissance de la bobine : P = U × I. Une vanne 12V / 0,5A consomme 6W. C’est trop pour un GPIO de l’ESP32 (max 12 mA à 3,3V) → il faut un relais ou un MOSFET.
Le relais agit comme un interrupteur commandé électriquement :
ESP32 GPIO ──→ [Optocoupleur] ──→ [Bobine relais] ──→ [Contact] ──→ Vanne 12V
3,3V Isolation galvanique Commutation puissance
Choix du module :
⚠️ Protection contre les surtensions : la bobine de l’électrovanne génère un pic de tension à la coupure (loi de Lenz). Une diode de roue libre (1N4007) en antiparallèle sur la bobine est indispensable.
Pour les systèmes alimentés par une cuve (récupération d’eau de pluie) :
Un simple interrupteur à lame ou un capteur résistif détecte s’il pleut. On peut aussi utiliser un pluviomètre à augets basculants (tipping bucket) pour une mesure quantitative :
Résolution = Volume de l’auget / Surface de collecte
Un auget de 3,2 mL avec une surface de collecte de 55 cm² donne 0,2 mm par basculement.
Le système complet consomme :
| Composant | Tension | Courant | Durée |
|---|---|---|---|
| ESP32 (actif WiFi) | 3,3V | ~240 mA | Continu |
| Capteur humidité capacitif | 3,3V | ~5 mA | 100 ms/mesure |
| DS18B20 | 3,3V | ~1 mA | 750 ms/mesure |
| Module relais (bobine) | 5V | ~70 mA | Durant arrosage |
| Électrovanne 12V | 12V | ~500 mA | Durant arrosage |
Équation clé — Capacité batterie :
C(Ah) = I_moyen × t_autonomie × facteur_sécurité
Pour 24h d’autonomie solaire avec une mesure toutes les 15 min (deep sleep entre les mesures) et un arrosage de 10 min/jour :
L’algorithme le plus basique compare l’humidité mesurée à deux seuils :
SI humidité < seuil_bas ET pas_de_pluie :
OUVRIR vanne pendant durée_arrosage
SI humidité > seuil_haut :
FERMER vanne
Limites : pas de prise en compte de la météo, risque d’arrosage juste avant la pluie, pas d’adaptation saisonnière.
Plus intelligent, cet algorithme estime le stock d’eau dans le sol :
S(t+1) = S(t) + P + I - ET_estimée
avec :
ET₀ ≈ 0,0023 × (T_moy + 17,8) × √(T_max - T_min) × Ra
où Ra = rayonnement extraterrestre (tabulé selon latitude et jour de l’année)
Un jardin comporte souvent des zones aux besoins différents :
| Zone | Type | Seuil bas | Seuil haut | Fréquence max |
|---|---|---|---|---|
| Potager | Légumes | 40% | 70% | 2×/jour |
| Pelouse | Gazon | 30% | 60% | 1×/jour |
| Massif | Vivaces | 25% | 55% | 1×/2 jours |
| Serre | Semis | 50% | 80% | 3×/jour |
Chaque zone possède sa propre électrovanne et son capteur d’humidité. L’ESP32 gère les zones séquentiellement (jamais deux vannes ouvertes en même temps, pour maintenir la pression).
# code/irrigation_zone.py
from machine import Pin, ADC
import time
class ZoneIrrigation:
def __init__(self, nom, pin_relais, pin_capteur,
seuil_bas=40, seuil_haut=70,
duree_max=600):
self.nom = nom
self.relais = Pin(pin_relais, Pin.OUT, value=0)
self.capteur = ADC(Pin(pin_capteur))
self.capteur.atten(ADC.ATTN_11DB)
self.seuil_bas = seuil_bas
self.seuil_haut = seuil_haut
self.duree_max = duree_max # secondes
Le fichier complet code/irrigation_zone.py contient les méthodes de lecture, calibration et arrosage.
Les capteurs capacitifs sont bruités. Un moyennage sur N mesures stabilise la lecture :
def lire_humidite(self, n_samples=10, delai_ms=50):
lectures = []
for _ in range(n_samples):
lectures.append(self.capteur.read())
time.sleep_ms(delai_ms)
brut = sum(lectures) // len(lectures)
# Conversion en % (calibration linéaire)
# air = 3200, eau = 1400 (valeurs typiques)
pct = max(0, min(100,
(3200 - brut) * 100 // (3200 - 1400)))
return pct
# code/controleur_irrigation.py (extrait)
from irrigation_zone import ZoneIrrigation
from machine import RTC, deepsleep
import network, ntptime
zones = [
ZoneIrrigation("Potager", pin_relais=26,
pin_capteur=34, seuil_bas=40),
ZoneIrrigation("Pelouse", pin_relais=27,
pin_capteur=35, seuil_bas=30),
]
def cycle_irrigation():
for zone in zones:
h = zone.lire_humidite()
print(f"{zone.nom}: {h}%")
if h < zone.seuil_bas:
zone.arroser()
Le contrôleur effectue un cycle de mesure, arrose si nécessaire, puis entre en deep sleep jusqu’au prochain cycle.
L’ESP32 possède un RTC interne qui survit au deep sleep. Cependant, il dérive (~5 s/jour). Pour les systèmes connectés, la synchronisation NTP corrige cette dérive :
import ntptime
ntptime.host = "pool.ntp.org"
ntptime.settime() # Synchronise le RTC interne
L’arrosage est plus efficace tôt le matin (6h-8h) ou en soirée (19h-21h) :
def dans_fenetre_arrosage():
heure = time.localtime()[3] # heure courante
return (6 <= heure <= 8) or (19 <= heure <= 21)
Un capteur de pluie ou une API météo peut inhiber l’arrosage :
def verifier_pluie(pin_pluie=33):
"""Capteur de pluie : 0 = pluie détectée"""
pluie = Pin(pin_pluie, Pin.IN, Pin.PULL_UP)
return pluie.value() == 0
def prevoir_pluie_api():
"""Interroge OpenWeatherMap (nécessite WiFi)"""
import urequests, json
url = ("http://api.openweathermap.org/data/2.5/"
"forecast?q=Paris&appid=VOTRE_CLE&cnt=8")
r = urequests.get(url)
data = json.loads(r.text)
r.close()
for item in data["list"]:
if "rain" in item.get("weather", [{}])[0].get("main", "").lower():
return True
return False
Le système prévoit plusieurs modes :
| Mode | Comportement | Cas d’usage |
|---|---|---|
| AUTO | Décision basée sur les capteurs | Fonctionnement normal |
| MANUEL | Arrosage forcé via bouton ou commande WiFi | Test, besoin ponctuel |
| ECO | Seuils abaissés de 10%, durée réduite de 30% | Restriction d’eau |
| HORS-GEL | Vannes fermées, drainage automatique | Hiver, T < 2°C |
| VEILLE | Mesures uniquement, pas d’arrosage | Absence prolongée |
┌──────────┐
┌────────→│ AUTO │←──────────┐
│ └────┬─────┘ │
│ │ T<2°C │ T>5°C
│ ▼ │
│ ┌──────────┐ │
│ │ HORS-GEL │───────────┘
│ └──────────┘
│
│ btn ┌──────────┐
└─────────│ MANUEL │
└──────────┘
Plutôt qu’un long arrosage continu, des impulsions courtes permettent une meilleure infiltration :
Principe : 3 × 5 minutes espacées de 15 minutes > 1 × 15 minutes continues
L’eau a le temps de s’infiltrer au lieu de ruisseler en surface.
Le besoin réel d’une culture = ET₀ × Kc, où Kc varie selon le stade de croissance :
| Stade | Kc typique |
|---|---|
| Semis / transplantation | 0,3 – 0,5 |
| Croissance végétative | 0,7 – 0,9 |
| Floraison / fructification | 1,0 – 1,2 |
| Maturation / récolte | 0,5 – 0,8 |
L’intégration du Kc dans l’algorithme permet de réduire la consommation de 20-30% par rapport à un arrosage à seuil fixe.
Un débitmètre à effet Hall (type YF-S201) sur la canalisation mesure le volume d’eau utilisé :
Volume = nombre_d’impulsions / facteur_K
Facteur K typique : 7,5 impulsions/litre pour le YF-S201
from machine import Pin
compteur = 0
def compter_impulsion(pin):
global compteur
compteur += 1
debit_pin = Pin(25, Pin.IN, Pin.PULL_UP)
debit_pin.irq(trigger=Pin.IRQ_FALLING,
handler=compter_impulsion)
Le système enregistre chaque événement pour le diagnostic :
def log_evenement(zone, action, humidite, volume=0):
timestamp = time.localtime()
ligne = "{:04d}-{:02d}-{:02d} {:02d}:{:02d}," \
"{},{},{},{}\n".format(
*timestamp[:5], zone, action, humidite, volume)
with open("/data/log.csv", "a") as f:
f.write(ligne)
Format CSV résultant :
2026-03-23 07:15,Potager,ARROSAGE,35,12.5
2026-03-23 07:16,Pelouse,SKIP,42,0
2026-03-23 19:00,Potager,ARROSAGE,38,10.2
Protocole :
Checklist avant déploiement :
| Concept | Détail |
|---|---|
| Actionneur principal | Électrovanne NF 12V DC |
| Commande | Module relais avec optocoupleur |
| Protection | Diode de roue libre + fusible |
| Algorithme simple | Seuils haut/bas sur humidité |
| Algorithme avancé | Bilan hydrique + Kc + météo |
| Optimisation | Arrosage par impulsions, fenêtres horaires |
| Sécurité | Mode hors-gel, durée max, inhibition pluie |
| Diagnostic | Log CSV horodaté |
💡 Point pratique : Commencez par le système le plus simple (un capteur, une vanne, seuils fixes). Ajoutez la complexité progressivement : multi-zones, bilan hydrique, API météo. Un système simple qui fonctionne vaut mieux qu’un système complexe qui plante.
| ← Précédent : Les Capteurs | Suivant : Collecte et Visualisation des Données → |