Module 5U001(STEPE-G²): Développement à base d’Arduino d’un dispositif autonome de gestion du suivi et de la recharge en eau d’un réservoir de stockage.
Travail mené par:
BOUONOU NGONGA Helena (étudiante parcours Géophysique/Géotechnique, Sorbonne sciences-ingénierie)
&
MEGAPTCHE PINEL Nelson (étudiante parcours Géophysique/Géotechnique, Sorbonne sciences-ingénierie)
Durée du projet : Décembre 2025 à Janvier 2026
Introduction
La gestion de la ressource en eau revient aujourd’hui au devant de la scène. Face à l’avènement du changement climatique, qui se traduit par des épisodes de sécheresse de plus en plus intenses, un apport en eau permanent et sans interruption devient indispensable afin d’assurer la continuité de nos activités, qu’il s’agisse de la consommation, de l’agriculture, de l’élevage, des industries ou d’autres usages.
L’automatisation de la gestion de l’approvisionnement de cette ressource constitue toutefois la meilleure approche permettant un suivi efficace et un contrôle optimal de nos réserves en eau.
L’approche de notre projet est basée sur le développement d’une boîte de commande autonome, à base d’Arduino, capable d’assurer à la fois la recharge, le contrôle du stock d’eau dans le réservoir, ainsi que le suivi de l’approvisionnement en temps opportun.
Objectif
Création d’un dispositif autonome de gestion de la recharge en eau d’un réservoir à base arduino.
Objectifs spécifiques
-
Détection précise du niveau d'eau
-
Protection de la pompe contre le fonctionnement
-
Surveillance en temps réel
-
Mise en œuvre de sécurités multiples
-
Equipements et rôles
Figure 1: accessoires de notre système de montage
Le choix d’un capteur de niveau d’eau dans notre projet, plutôt qu’un détecteur d’eau, n’est pas anodin. Bien que la mesure constitue la fonction principale de ces deux dispositifs, la différence réside dans leur mode d’utilisation. Le capteur de niveau est destiné à réaliser des mesures continues et précises du niveau de liquide, tandis qu’un détecteur de niveau est principalement utilisé pour signaler la présence ou l’absence de liquide à un point donné.
Notre projet vise le suivi continu du niveau d’eau dans le réservoir, c’est pourquoi nous avons opté pour l’utilisation d’un capteur de niveau d’eau.
-
Principe de fonctionnement de notre dispositif
La prise en compte des différents cas de figure, en fonction des composants de commande (capteurs) de notre système, doit être intégrée dans le code de commande. Toutefois, l’utilisation d’un grand nombre de composants de commande entraîne des boucles conditionnelles plus complexes, augmentant ainsi les risques de dysfonctionnement du système.
Il est donc nécessaire de concevoir un fonctionnement plus robuste, reposant sur un nombre réduit de composants de commande, tout en assurant une autonomie fonctionnelle du système. Ci-dessous est présenté l’organigramme définissant le fonctionnement global de notre système:
Figure 2: organigramme de fonctionnement du système
Le système opère selon une boucle fermée de contrôle :
-
Acquisition : Lecture des capteurs toutes les 100ms
-
Traitement : Analyse des données et prise de décision
-
Action : Commande des actionneurs selon la logique
-
Surveillance : Vérification des sécurités et affichage
-
Développement du système
III.1 Paramètre de configuration
Tel que défini dans le code du système (voir annexe), il s’agit des conditions limite d’eau dans le réservoir nécessaire pour une éventuelle mise en marche ou pas de la pompe et temps de pompage de ce dernier
// Paramètres ajustables selon application
const int SEUIL_BAS = 100; // Niveau bas → démarrage
const int SEUIL_HAUT = 200; // Niveau haut → arrêt
const unsigned long TEMPS_MAX_POMPAGE = 300000; // 5 minutes
const float COURANT_MIN_POMPE = 0.5; // Détection pompe à sec
III.2 Schéma de câblage du système
ARDUINO UNO → COMPOSANTS
├── D2 → Bouton poussoir (GND)
├── D4 → Relais IN
├── D7 → LED Rouge (+220Ω→GND)
├── D8 → LED Verte (+220Ω→GND)
├── A2 → Grove Electricity Sensor
├── 5V → Alimentation shield
├── GND → Masse commune
└── I2C → Shield Grove ports
SHIELD GROVE → CAPTEURS
├── Port I2C 1 → Grove Water Level Sensor
├── Port I2C 2 → DPS310 (optionnel)
└── Port A2 → Grove Electricity Sensor
Figure 3: Illustration simplifiée du montage fonctionnel
Figure 4: Montage de notre système
-
Résultats des tests
Une fois le code transféré vers l’Arduino depuis l’interface Arduino IDE, il est possible d’observer le signalement de l’état du système, qui indique 0 (figure 5), illustrant que celui-ci n’est pas encore mis en fonctionnement automatique. Néanmoins, l’état initial du système est déjà affiché : il reste en attente de son démarrage après l’appui sur le bouton poussoir.
Figure 5: initialisation de notre système
Une fois le système mis en marche, les états initiaux renvoyés par les capteurs sont pris en compte par le système. En fonction des boucles de commande définies dans le code, la pompe se met en marche ou non selon les paramètres de configuration établis.
Après le lancement du système en fonctionnement automatique, il est possible de lire au niveau de la sortie (Output) de l’IDE l’indication « SYSTEME = 1 ».
Si le niveau d’eau dans le réservoir est inférieur au seuil bas fixé (100), l’affichage « eauBas = 1 » apparaît dans la sortie de l’IDE ; dans le cas contraire, « eauBas = 0 » est affiché.
De même, si le niveau d’eau est supérieur au seuil haut fixé (200), l’indication « eauHaut = 1 » est affichée ; dans le cas contraire, « eauHaut = 0 ».
Le déclenchement de la pompe est conditionné par la détection d’un niveau d’eau bas, c’est-à-dire lorsque le capteur fournit l’information « eauBas = 1 », autorisant ainsi la mise en marche de la pompe.
Figure 6: état de fonctionnement du système avec suivi du niveau d’eau dans le réservoir
Afin de limiter le remplissage excessif du réservoir et d’éviter tout risque de débordement, il était nécessaire de garantir la prise en compte de cette information par le système. C’est pourquoi nous avons décidé que, après plusieurs détections successives du niveau d’eau dans le réservoir, si le capteur indique des valeurs supérieures à 250, le système, par mesure de sécurité, repasse automatiquement en mode non actif « SYSTEME = 0 » (figure 7).
Figure 7: mise en arrêt du système une fois le remplissage confirmé du réservoir
Remarque: une activation de la pompe est signalée par l’allumage de la LED bleu illustrant une mise en fonctionnement de ce dernier et de notre système. Lorsqu’il est éteint et non fonctionnel, une leg verte s’allume pour matérialiser celà au niveau du système.
-
Limites et perspectives d’amélioration
Malgré son efficacité dans l’automatisation de la gestion d’un réservoir d’eau, le système développé présente certaines limites qu’il convient de souligner:
-
Le système repose sur des seuils fixes de niveau d’eau (seuil bas et seuil haut). Cette approche, bien que simple et robuste, ne permet pas une adaptation dynamique aux variations de consommation.
-
La dépendance à un unique capteur de niveau constitue une limite en termes de fiabilité. En cas de défaillance du capteur ou d’erreur de communication I2C avec l’ATtiny, le système peut fonctionner de manière dégradée, voire incorrecte.
-
Son autonomie énergétique reste limitée car l’alimentation de la pompe dépend d’une source externe continue.
-
Le système ne dispose pas d’une interface utilisateur avancée. Les informations relatives à l’état du réservoir et de la pompe sont uniquement indiquées par des LEDs, ce qui limite la lisibilité et l’exploitation des données pour un utilisateur non technique.
Enfin, la capacité du système à gérer des situations extrêmes (panne prolongée de la pompe, fuite du réservoir, colmatage des conduites) reste limitée, car les mécanismes de diagnostic et d’alerte ne sont pas encore intégrés.
Conclusion
Le système proposé constitue une solution fonctionnelle et pertinente pour la gestion autonome d’un réservoir d’eau, son évolution vers une architecture plus intelligente, communicante et énergétiquement autonome permettrait d’envisager une application à plus grande échelle et dans des environnements plus contraignants.
Ainsi grâce à cette approche autonome, on vise à faire évoluer la fonction des systèmes de monitoring. Celle-ci ne se baserait plus uniquement sur une logique surveillance-action, mais plutôt sur une approche surveillance-régulation-suivi-action. Cette évolution garantirait à la fois un meilleur controle, une meilleure optimisation et une meilleur gestion de la ressource en eau.
Bibliographie
-
Grove - Water Sensor | Seeed Studio Wikipédia. (November 2025). https://wiki.seeedstudio.com/Grove-Water-Level-Sensor/
-
Commander une pompe à eau par la carte arduino, Robotique. Consulté en Novembre 2025 https://www.robotique.tech/tutoriel/commander-une-pompe-a-eau-par-la-carte-arduino/
-
Bert Van Dam. Tuto Arduino Uno: 45 projets électroniques originaux. Publitronic Elektor, 2016.
-
MERABTI Djahida (2017). Conception et réalisation d’une commande automatique d’une station de pompage à base d’une carte ARDUINO Mega2560. https://dspace.ummto.dz/server/api/core/bitstreams/52536b4a-c564-47b2-a902-c5bc888f124e/content
-
https://icn.lycee-valin.fr/dokuwiki/doku.php?id=arduino:module_de_connexion_grove
Annexe
Code téléchargé dans l’arduino uno pour notre système autonome
// ============================================
// SYSTÈME DE GESTION RÉSERVOIR - UN SEUL ATtiny
// ============================================
#include <Wire.h>
// ---------- BROCHES ----------
const int BOUTON = 2;
const int RELAIS_POMPE = 4;
const int LED_ROUGE = 7;
const int LED_VERTE = 8;
const int ELECTRICITY_SENSOR = A2;
// ---------- I2C ATtiny ----------
#define ATTINY_ADDR 0x77 // adresse unique du capteur
#define TIMEOUT_I2C 100
// ---------- CONSTANTES ----------
const unsigned long TEMPS_MAX_POMPAGE = 300000;
const unsigned long DELAI_ANTI_REBOND = 50;
const int SEUIL_BAS = 100; // seuil pour eau basse
const int SEUIL_HAUT = 200; // seuil pour réservoir plein
const float COURANT_MIN_POMPE = 0.5;
// ---------- VARIABLES ----------
bool systemeActif = false;
bool pompeFonctionne = false;
bool etatBouton = HIGH;
bool dernierEtatBouton = HIGH;
unsigned long dernierTempsDebounce = 0;
unsigned long tempsDemarrePompe = 0;
unsigned long tempsAnomalie = 0;
unsigned long dernierLoop = 0;
unsigned long dernierClignotementLED = 0;
bool etatLEDClignotante = false;
// ---------- FONCTION I2C NON BLOQUANTE ----------
int lireCapteurI2C(uint8_t addr) {
Wire.requestFrom(addr, (uint8_t)1);
unsigned long t0 = millis();
while (Wire.available() < 1 && millis() - t0 < TIMEOUT_I2C);
if (Wire.available()) return Wire.read();
return -1;
}
// ============================================
// SETUP
// ============================================
void setup() {
Serial.begin(115200);
Wire.begin();
pinMode(BOUTON, INPUT_PULLUP);
pinMode(RELAIS_POMPE, OUTPUT);
pinMode(LED_ROUGE, OUTPUT);
pinMode(LED_VERTE, OUTPUT);
digitalWrite(RELAIS_POMPE, LOW);
Serial.println("=== SYSTEME RESERVOIR - UN SEUL ATtiny ===");
}
// ============================================
// LOOP PRINCIPAL NON BLOQUANT
// ============================================
void loop() {
if (millis() - dernierLoop < 100) return;
dernierLoop = millis();
// ----- BOUTON -----
int lectureBouton = digitalRead(BOUTON);
if (lectureBouton != dernierEtatBouton) dernierTempsDebounce = millis();
if ((millis() - dernierTempsDebounce) > DELAI_ANTI_REBOND) {
if (lectureBouton != etatBouton) {
etatBouton = lectureBouton;
if (etatBouton == LOW) systemeActif = !systemeActif;
}
}
dernierEtatBouton = lectureBouton;
// ----- LECTURE DU CAPTEUR -----
int Niveau_eau = lireCapteurI2C(ATTINY_ADDR);
// Serial.print("Niveau_eau = "); Serial.println(Niveau_eau);
bool eauBas = (Niveau_eau >= 0 && Niveau_eau < SEUIL_BAS);
bool eauHaut = (Niveau_eau >= SEUIL_HAUT);
// ----- DEBUG NIVEAU -----
Serial.print("niveau brut = ");
Serial.print(Niveau_eau);
Serial.print(" | eauBas = ");
Serial.print(eauBas);
Serial.print(" | eauHaut = ");
Serial.println(eauHaut);
// ----- COURANT POMPE -----
float courant = abs(((analogRead(ELECTRICITY_SENSOR) / 1024.0) * 5.0 - 2.5) / 0.185);
// ----- LOGIQUE POMPE -----
if (systemeActif) {
if (eauBas && !pompeFonctionne) {
digitalWrite(RELAIS_POMPE, HIGH);
pompeFonctionne = true;
tempsDemarrePompe = millis();
}
if (eauHaut && pompeFonctionne) {
digitalWrite(RELAIS_POMPE, LOW);
pompeFonctionne = false;
}
if (pompeFonctionne && millis() - tempsDemarrePompe > TEMPS_MAX_POMPAGE) {
digitalWrite(RELAIS_POMPE, LOW);
pompeFonctionne = false;
}
if (pompeFonctionne && courant < COURANT_MIN_POMPE) {
if (tempsAnomalie == 0) tempsAnomalie = millis();
if (millis() - tempsAnomalie > 5000) {
digitalWrite(RELAIS_POMPE, LOW);
pompeFonctionne = false;
}
} else tempsAnomalie = 0;
}
// ----- LEDS -----
if (!systemeActif) {
digitalWrite(LED_ROUGE, LOW);
digitalWrite(LED_VERTE, LOW);
} else if (eauBas) {
digitalWrite(LED_ROUGE, HIGH);
digitalWrite(LED_VERTE, LOW);
} else if (eauHaut) {
digitalWrite(LED_ROUGE, LOW);
digitalWrite(LED_VERTE, HIGH);
} else if (pompeFonctionne) {
if (millis() - dernierClignotementLED > 500) {
dernierClignotementLED = millis();
etatLEDClignotante = !etatLEDClignotante;
}
digitalWrite(LED_ROUGE, etatLEDClignotante);
digitalWrite(LED_VERTE, LOW);
} else {
digitalWrite(LED_ROUGE, LOW);
digitalWrite(LED_VERTE, HIGH);
}
// ----- DEBUG -----
static unsigned long dernierAffichage = 0;
if (millis() - dernierAffichage > 3000) {
dernierAffichage = millis();
Serial.print("Systeme: "); Serial.print(systemeActif);
Serial.print(" | Pompe: "); Serial.print(pompeFonctionne);
Serial.print(" | Niveau_eau: "); Serial.print(Niveau_eau);
Serial.print(" | Courant(A): "); Serial.println(courant);
}
}







No Comments