#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoPixel.h> // AJOUTÉ POUR LE STYLE
// --- Définitions des broches ---
#define relayPin 26
#define BP1_AUTO 4
#define Led_AUTO 13 // On garde cette LED
#define BP2_MANU 16
#define Led_MANU 14 // On garde cette LED
#define BP3_MAINT 17
#define Led_MAINT 27 // On garde cette LED
#define BP4_MARCHE 12
#define BP5_ARRET 19
#define Pot1 34
#define Pot2 35
#define Capteur_Niveau_Bas 18
#define Capteur_Niveau_Haut 5
// --- NOUVEAU: Définition du ruban de STYLE ---
#define pinLEDWS2812 25
#define NUMPIXELS_STRIP 10 // Mettez le nombre de LEDs sur votre ruban
Adafruit_NeoPixel strip(NUMPIXELS_STRIP, pinLEDWS2812, NEO_GRB + NEO_KHZ800);
// --- FIN NOUVEAU ---
// --- Définitions Écran I2C ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS_1 0x3C
#define SCREEN_ADDRESS_2 0x3D
// --- Déclaration des objets écran ---
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- Variables globales ---
int Mode = -1; // -1: aucun, 0: AUTO, 1: MANU, 2: MAINT
int menuPage = 0;
int menuSelection = 0;
// --- VARIABLES HORLOGE RTC ---
int globalHeures = 19;
int globalMinutes = 10;
unsigned long lastRtcUpdateTime = 0;
const unsigned long RtcInterval = 10000; // 10 sec pour tester
// --- VARIABLES PARAMETRAGE POMPE ---
int declenchementHeure = 7;
int declenchementMinute = 0;
int declenchementDuree = 30;
bool pompeEnMarchePlanifiee = false;
unsigned long tempsDemarragePlanifie = 0;
int tempParamHeure = 0;
int tempParamMinute = 0;
int tempParamDuree = 0;
int parametrageState = 0;
int lastPot1Value_Param = -1;
// --- VARIABLES REGALGE HEURE ---
int tempHeures = 0;
int tempMinutes = 0;
int reglageHeureState = 0;
unsigned long lastBlinkTime = 0;
bool blinkState = false;
int lastPot1Value_Heure = -1;
// --- VARIABLES TIMER LOOP ---
unsigned long lastScreenUpdateTime = 0;
const long screenUpdateInterval = 50;
// Variables debounce pour la navigation menu (BP4 & BP5)
bool bp4_menu_lastState = HIGH;
bool bp5_menu_lastState = HIGH;
unsigned long lastDebounceTime_BP4 = 0;
unsigned long lastDebounceTime_BP5 = 0;
bool bp4_menu_stableState = HIGH;
bool bp5_menu_stableState = HIGH;
// Variables debounce pour les boutons de Mode (BP1, BP2, BP3)
bool bp1_mode_lastState = HIGH;
bool bp2_mode_lastState = HIGH;
bool bp3_mode_lastState = HIGH;
unsigned long lastDebounceTime_BP1_Mode = 0;
unsigned long lastDebounceTime_BP2_Mode = 0;
unsigned long lastDebounceTime_BP3_Mode = 0;
bool bp1_mode_stableState = HIGH;
bool bp2_mode_stableState = HIGH;
bool bp3_mode_stableState = HIGH;
#define DEBOUNCE_DELAY 50
// --- Prototypes de fonctions ---
void updateClock();
void updateStyleLEDs(); // MODIFIÉ
void initialisation_pin();
void afficherEtatPrimaire();
void gererMenuSecondaire();
void mettreAJourEcranMenu();
void drawMenu();
void drawPageAccueil();
void drawPageParametrage();
void drawPageReglageHeure();
void drawPageRedemarrer();
void drawPageInfosSystem();
void drawMenuInactif();
void gererboutons();
void modeAUTO();
void modeMANU();
void modeMAINT();
void redemarrerESP32();
void drawIconParam(int x, int y);
void drawIconHeure(int x, int y);
void drawIconReboot(int x, int y);
void drawIconInfo(int x, int y);
void setup()
{
Serial.begin(115200);
Wire.begin();
initialisation_pin(); // Initialise les LEDs de statut (13, 14, 27)
// NOUVEAU: Initialisation du ruban de style
strip.begin();
strip.clear();
strip.show();
// --- FIN NOUVEAU ---
// Initialisation Ecran 1 (Etat)
if (!display1.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS_1))
{
Serial.println(F("Echec init SSD1306 Ecran 1"));
for (;;)
;
}
display1.display();
delay(500);
// Initialisation Ecran 2 (Menu)
if (!display2.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS_2))
{
Serial.println(F("Echec init SSD1306 Ecran 2"));
for (;;)
;
}
display2.display();
delay(500);
// Initialise le timer de l'horloge
lastRtcUpdateTime = millis();
}
void updateClock()
{
if (millis() - lastRtcUpdateTime >= RtcInterval)
{
lastRtcUpdateTime += RtcInterval;
globalMinutes++;
if (globalMinutes >= 60)
{
globalMinutes = 0;
globalHeures++;
if (globalHeures >= 24)
{
globalHeures = 0;
}
}
}
}
/**
* @brief NOUVELLE FONCTION: Met à jour le ruban de LEDs de style
* s'allume la nuit et change de couleur selon le statut.
*/
void updateStyleLEDs()
{
// Condition horaire: 7h00 du matin jusqu'à 18h59
if (globalHeures >= 7 && globalHeures < 19)
{
// C'est le jour, on éteint le ruban
strip.clear();
strip.show();
return;
}
// --- C'est la nuit (19h00 - 06h59), on allume ---
// 1. Lire les statuts (pour la priorité)
bool niveauBasDetecte = (digitalRead(Capteur_Niveau_Bas) == LOW);
bool pompeEstEnMarche = (digitalRead(relayPin) == HIGH);
uint32_t color = strip.Color(0, 0, 0); // Couleur par défaut (éteint)
// 2. Définir la couleur par priorité
// Priorité 1: Alarme Niveau Bas (!niveauBasDetecte signifie que le capteur est "sec")
if (!niveauBasDetecte)
{
// Clignote en rouge vif
if (blinkState)
{
color = strip.Color(150, 0, 0); // Rouge vif
}
// else: 'color' reste noir (éteint), créant le clignotement
}
// Priorité 2: Pompe en marche
else if (pompeEstEnMarche)
{
color = strip.Color(100, 0, 0); // Rouge fixe (moins vif)
}
// Priorité 3: Statut du Mode (si tout va bien)
else
{
switch (Mode)
{
case 0: // AUTO
color = strip.Color(0, 80, 0); // Vert
break;
case 1: // MANU
color = strip.Color(0, 0, 80); // Bleu
break;
case 2: // MAINT
color = strip.Color(80, 80, 0); // Jaune
break;
default:
color = strip.Color(0, 0, 0); // Eteint si pas de mode
break;
}
}
// 4. Appliquer la couleur à tout le ruban
strip.fill(color);
strip.show();
}
void loop()
{
updateClock();
if (millis() - lastBlinkTime > 400)
{
lastBlinkTime = millis();
blinkState = !blinkState;
}
gererboutons(); // Gère les LEDs de statut (13, 14, 27)
switch (Mode)
{
case 0:
modeAUTO();
break;
case 1:
modeMANU();
break;
case 2:
modeMAINT();
gererMenuSecondaire();
break;
default:
digitalWrite(relayPin, LOW);
break;
}
if (millis() - lastScreenUpdateTime >= screenUpdateInterval)
{
lastScreenUpdateTime += screenUpdateInterval;
updateStyleLEDs(); // NOUVEAU: Met à jour le ruban de style
afficherEtatPrimaire();
mettreAJourEcranMenu();
}
}
void initialisation_pin()
{
pinMode(relayPin, OUTPUT);
pinMode(BP1_AUTO, INPUT_PULLUP);
pinMode(Led_AUTO, OUTPUT); // CONSERVÉ
pinMode(BP2_MANU, INPUT_PULLUP);
pinMode(Led_MANU, OUTPUT); // CONSERVÉ
pinMode(BP3_MAINT, INPUT_PULLUP);
pinMode(Led_MAINT, OUTPUT); // CONSERVÉ
pinMode(BP4_MARCHE, INPUT_PULLUP);
pinMode(BP5_ARRET, INPUT_PULLUP);
pinMode(Capteur_Niveau_Bas, INPUT_PULLUP);
pinMode(Capteur_Niveau_Haut, INPUT_PULLUP);
digitalWrite(Led_AUTO, LOW); // CONSERVÉ
digitalWrite(Led_MANU, LOW); // CONSERVÉ
digitalWrite(Led_MAINT, LOW); // CONSERVÉ
digitalWrite(relayPin, LOW);
}
void gererboutons()
{
bool bp1_currentState = digitalRead(BP1_AUTO);
bool bp2_currentState = digitalRead(BP2_MANU);
bool bp3_currentState = digitalRead(BP3_MAINT);
// --- Anti-rebond et logique pour BP1 (AUTO) ---
if (bp1_currentState != bp1_mode_lastState)
{
lastDebounceTime_BP1_Mode = millis();
}
if ((millis() - lastDebounceTime_BP1_Mode) > DEBOUNCE_DELAY)
{
if (bp1_currentState != bp1_mode_stableState)
{
bp1_mode_stableState = bp1_currentState;
if (bp1_mode_stableState == LOW)
{
digitalWrite(Led_AUTO, HIGH); // CONSERVÉ
digitalWrite(Led_MANU, LOW); // CONSERVÉ
digitalWrite(Led_MAINT, LOW); // CONSERVÉ
Mode = 0;
}
}
}
bp1_mode_lastState = bp1_currentState;
// --- Anti-rebond et logique pour BP2 (MANU) ---
if (bp2_currentState != bp2_mode_lastState)
{
lastDebounceTime_BP2_Mode = millis();
}
if ((millis() - lastDebounceTime_BP2_Mode) > DEBOUNCE_DELAY)
{
if (bp2_currentState != bp2_mode_stableState)
{
bp2_mode_stableState = bp2_currentState;
if (bp2_mode_stableState == LOW)
{
digitalWrite(Led_AUTO, LOW); // CONSERVÉ
digitalWrite(Led_MANU, HIGH); // CONSERVÉ
digitalWrite(Led_MAINT, LOW); // CONSERVÉ
Mode = 1;
}
}
}
bp2_mode_lastState = bp2_currentState;
// --- Anti-rebond et logique pour BP3 (MAINT) ---
if (bp3_currentState != bp3_mode_lastState)
{
lastDebounceTime_BP3_Mode = millis();
}
if ((millis() - lastDebounceTime_BP3_Mode) > DEBOUNCE_DELAY)
{
if (bp3_currentState != bp3_mode_stableState)
{
bp3_mode_stableState = bp3_currentState;
if (bp3_mode_stableState == LOW)
{
digitalWrite(Led_AUTO, LOW); // CONSERVÉ
digitalWrite(Led_MANU, LOW); // CONSERVÉ
digitalWrite(Led_MAINT, HIGH); // CONSERVÉ
Mode = 2;
}
}
}
bp3_mode_lastState = bp3_currentState;
}
/**
* @brief LOGIQUE MODE AUTO (CORRIGÉE AVEC HYSTÉRÉSIS)
*/
void modeAUTO()
{
bool niveauBasDetecte = (digitalRead(Capteur_Niveau_Bas) == LOW);
bool niveauHautDetecte = (digitalRead(Capteur_Niveau_Haut) == LOW);
bool pompeEstEnMarche = (digitalRead(relayPin) == HIGH);
// --- 1. Gérer la demande horaire (logique de timer) ---
bool demandeHoraire = false;
if (pompeEnMarchePlanifiee)
{
// Cycle planifié en cours
unsigned long dureeMillis = declenchementDuree * 60000UL;
if (millis() - tempsDemarragePlanifie > dureeMillis)
{
pompeEnMarchePlanifiee = false; // Fin du cycle
demandeHoraire = false;
}
else
{
demandeHoraire = true; // Maintient la demande
}
}
// Démarrer un NOUVEAU cycle planifié
if (globalHeures == declenchementHeure &&
globalMinutes == declenchementMinute &&
!pompeEnMarchePlanifiee && !pompeEstEnMarche) // Ne pas démarrer si déjà en marche
{
pompeEnMarchePlanifiee = true;
tempsDemarragePlanifie = millis();
demandeHoraire = true;
}
// --- 2. Logique de décision (CORRIGÉE) ---
// CONDITION D'ARRÊT (Priorité 1: Sécurité HAUT)
if (niveauHautDetecte)
{
digitalWrite(relayPin, LOW);
pompeEnMarchePlanifiee = false; // Annule aussi le cycle planifié
}
// CONDITION DE DÉMARRAGE (Priorité 2: Niveau BAS)
else if (!niveauBasDetecte)
{
digitalWrite(relayPin, HIGH);
if (pompeEnMarchePlanifiee)
{ // Si un cycle planifié était en cours, il est "remplacé"
pompeEnMarchePlanifiee = false;
}
}
// CONDITION DE MAINTIEN (Hystérésis)
// Si la pompe est en marche (à cause du niv bas) ET que le niveau bas est maintenant détecté
else if (pompeEstEnMarche && niveauBasDetecte && !pompeEnMarchePlanifiee)
{
// NE RIEN FAIRE, on est dans la plage d'hystérésis
// On laisse la pompe tourner jusqu'au niveau haut
}
// CONDITION DE DÉMARRAGE/MAINTIEN (Priorité 3: Horaire)
else if (demandeHoraire)
{
digitalWrite(relayPin, HIGH);
}
// CONDITION D'ARRÊT (Par défaut)
else
{
digitalWrite(relayPin, LOW);
pompeEnMarchePlanifiee = false; // S'assurer que tout est bien arrêté
}
}
void modeMANU()
{
// Vérification de sécurité du niveau haut
if (digitalRead(Capteur_Niveau_Haut) == LOW)
{
digitalWrite(relayPin, LOW); // Arrêt forcé si niveau haut détecté
return;
}
// Logique normale du mode manuel
if (!digitalRead(BP4_MARCHE))
{
digitalWrite(relayPin, HIGH);
}
else if (!digitalRead(BP5_ARRET))
{
digitalWrite(relayPin, LOW);
}
}
void modeMAINT()
{
digitalWrite(relayPin, LOW);
}
/**
* @brief Affiche l'écran de statut principal (Ecran 1)
* (REVERSION À LA VERSION SIMPLE - TAILLE 1)
*/
void afficherEtatPrimaire()
{
display1.clearDisplay();
display1.setTextSize(1);
display1.setTextColor(SSD1306_WHITE);
display1.setCursor(0, 0);
// Ligne 1: Heure et WiFi
char timeBuffer[6];
sprintf(timeBuffer, "%02d:%02d", globalHeures, globalMinutes);
display1.print(timeBuffer);
display1.print(" WIF: OK");
// Ligne 2: Mode
display1.setCursor(0, 16);
switch (Mode)
{
case 0:
display1.println("MODE:AUTO");
break;
case 1:
display1.println("MODE:MANU");
break;
case 2:
display1.println("MODE:MAINT");
break;
default:
display1.println("MODE:--");
break;
}
// Ligne 3: Pompe et Citerne (sur la même ligne)
display1.setCursor(0, 24);
if (digitalRead(relayPin))
{
display1.print("P:RUN ");
}
else
{
display1.print("P:STOP ");
}
bool niveauBasDetecte = (digitalRead(Capteur_Niveau_Bas) == LOW);
bool niveauHautDetecte = (digitalRead(Capteur_Niveau_Haut) == LOW);
if (niveauHautDetecte)
{
display1.print("CIT:PLEIN");
}
else if (niveauBasDetecte)
{
display1.print("CIT:EN C.");
}
else
{
display1.print("CIT:BAS!");
}
display1.display();
}
/**
* @brief Gère la navigation dans le menu secondaire
*/
void gererMenuSecondaire()
{
bool bp4_currentState = digitalRead(BP4_MARCHE);
bool bp5_currentState = digitalRead(BP5_ARRET);
// --- Gestion BP4 (MARCHE) : Naviguer ou Action ---
if (bp4_currentState != bp4_menu_lastState)
{
lastDebounceTime_BP4 = millis();
}
if ((millis() - lastDebounceTime_BP4) > DEBOUNCE_DELAY)
{
if (bp4_currentState != bp4_menu_stableState)
{
bp4_menu_stableState = bp4_currentState;
if (bp4_menu_stableState == LOW)
{
if (menuPage == 0)
{ // Page Accueil: Naviguer (0, 1, 2, 3)
menuSelection++;
if (menuSelection > 3)
menuSelection = 0;
}
else if (menuPage == 1)
{ // Page Parametrage: Champ suivant
parametrageState++;
if (parametrageState > 2)
parametrageState = 0; // 0=H, 1=M, 2=Durée
lastPot1Value_Param = -1; // Réinitialise le pot
}
else if (menuPage == 2)
{ // Page Réglage Heure: Champ suivant
reglageHeureState++;
if (reglageHeureState > 1)
reglageHeureState = 0;
lastPot1Value_Heure = -1;
}
else if (menuPage == 3)
{ // Page Redémarrer: Confirmer
redemarrerESP32();
}
}
}
}
bp4_menu_lastState = bp4_currentState;
// --- Gestion BP5 (ARRET) : Entrer ou Retour/Sauvegarder ---
if (bp5_currentState != bp5_menu_lastState)
{
lastDebounceTime_BP5 = millis();
}
if ((millis() - lastDebounceTime_BP5) > DEBOUNCE_DELAY)
{
if (bp5_currentState != bp5_menu_stableState)
{
bp5_menu_stableState = bp5_currentState;
if (bp5_menu_stableState == LOW)
{
if (menuPage == 0)
{ // Page Accueil: Entrer
menuPage = menuSelection + 1;
// Initialise la page de Parametrage (Page 1)
if (menuPage == 1)
{
tempParamHeure = declenchementHeure;
tempParamMinute = declenchementMinute;
tempParamDuree = declenchementDuree;
parametrageState = 0;
lastPot1Value_Param = -1;
}
// Initialise la page de Réglage Heure (Page 2)
if (menuPage == 2)
{
tempHeures = globalHeures;
tempMinutes = globalMinutes;
reglageHeureState = 0;
lastPot1Value_Heure = -1;
}
}
else
{ // Dans un sous-menu: Retour et Sauvegarde
// Si on quitte la Page 1 (Parametrage), on sauvegarde
if (menuPage == 1)
{
declenchementHeure = tempParamHeure;
declenchementMinute = tempParamMinute;
declenchementDuree = tempParamDuree;
}
// Si on quitte la Page 2 (Réglage Heure), on sauvegarde
if (menuPage == 2)
{
globalHeures = tempHeures;
globalMinutes = tempMinutes;
lastRtcUpdateTime = millis(); // Resynchronise l'horloge
}
menuPage = 0;
menuSelection = 0;
}
}
}
}
bp5_menu_lastState = bp5_currentState;
}
void mettreAJourEcranMenu()
{
if (Mode == 2)
{
drawMenu();
}
else
{
menuPage = 0;
menuSelection = 0;
drawMenuInactif();
}
}
/**
* @brief PAGE D'ACCUEIL (LOGO)
* S'affiche quand le menu n'est pas actif (Design de la maison)
*/
void drawMenuInactif()
{
display2.clearDisplay();
// Coordonnées du centre (légèrement remonté)
int x = 64; // Centre X
int y = 28; // Centre Y de la base du toit
// Dessin de la maison
display2.fillTriangle(x, y - 14, // Pointe du toit
x - 18, y, // Coin gauche toit
x + 18, y, // Coin droit toit
SSD1306_WHITE);
// Base de la maison
display2.fillRect(x - 14, y, 28, 20, SSD1306_WHITE);
// Porte (rectangle noir à l'intérieur de la base)
display2.fillRect(x - 5, y + 8, 10, 12, SSD1306_BLACK);
// Contour de la porte
display2.drawRect(x - 5, y + 8, 10, 12, SSD1306_WHITE);
// Instruction en bas (centrée)
display2.setTextSize(1);
int textWidth = 21 * 6; // "Appuyer [MAINT] Menu"
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 55); // Centré
display2.print("Appuyer [MAINT] Menu");
display2.display();
}
void drawMenu()
{
display2.clearDisplay();
display2.setTextSize(1);
display2.setTextColor(SSD1306_WHITE);
switch (menuPage)
{
case 0:
drawPageAccueil();
break;
case 1:
drawPageParametrage();
break;
case 2:
drawPageReglageHeure();
break;
case 3:
drawPageRedemarrer();
break;
case 4:
drawPageInfosSystem();
break;
default:
drawPageAccueil();
break;
}
display2.display();
}
/**
* @brief Affiche le menu principal (Page 0)
* (DESIGN GRILLE 2x2 - Ajusté)
*/
void drawPageAccueil()
{
display2.clearDisplay();
display2.setTextSize(1);
display2.setTextColor(SSD1306_WHITE);
// --- Positions des CENTRES des icônes ---
int iconX1 = 32;
int iconX2 = 96;
int iconY1 = 16; // Centré dans la boîte (y=2 à 30)
int iconY2 = 46; // Centré dans la boîte (y=32 à 60)
// --- Dessiner les 4 icônes ---
drawIconParam(iconX1, iconY1);
drawIconHeure(iconX2, iconY1);
drawIconReboot(iconX1, iconY2);
drawIconInfo(iconX2, iconY2);
// --- Dessiner le sélecteur et le texte ---
String helpText = "";
switch (menuSelection)
{
case 0: // Parametrage
display2.drawRoundRect(10, 2, 44, 28, 5, SSD1306_WHITE); // Boîte (x, y, w, h)
helpText = "Parametrage";
break;
case 1: // Reglage Heure
display2.drawRoundRect(74, 2, 44, 28, 5, SSD1306_WHITE);
helpText = "Regl. Heure";
break;
case 2: // Redemarrer
display2.drawRoundRect(10, 32, 44, 28, 5, SSD1306_WHITE); // Boîte (y=32)
helpText = "Redemarrer";
break;
case 3: // Infos
display2.drawRoundRect(74, 32, 44, 28, 5, SSD1306_WHITE); // Boîte (y=32)
helpText = "Infos Systeme";
break;
}
// Ligne de séparation pour le texte
display2.drawFastHLine(0, 53, 128, SSD1306_WHITE);
// Centrer le texte d'aide
int16_t x1, y1;
uint16_t w, h;
display2.getTextBounds(helpText, 0, 0, &x1, &y1, &w, &h);
display2.setCursor((SCREEN_WIDTH - w) / 2, 56);
display2.print(helpText);
}
/**
* @brief PAGE PARAMETRAGE (Page 1)
* (DESIGN SIMPLIFIÉ - TAILLE 1 - CORRIGÉ)
*/
void drawPageParametrage()
{
display2.clearDisplay();
display2.setTextSize(1);
display2.setTextColor(SSD1306_WHITE);
// Titre centré
int textWidth = 17 * 6; // "PARAMETRAGE POMPE"
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 0);
display2.print("PARAMETRAGE POMPE");
display2.drawFastHLine(0, 10, 128, SSD1306_WHITE);
// --- Logique de lecture du Potentiomètre ---
int pot1Value = analogRead(Pot1);
if (lastPot1Value_Param == -1)
{
lastPot1Value_Param = pot1Value;
}
else if (abs(pot1Value - lastPot1Value_Param) > 50)
{
switch (parametrageState)
{
case 0:
tempParamHeure = map(pot1Value, 0, 4095, 0, 23);
break;
case 1:
tempParamMinute = map(pot1Value, 0, 4095, 0, 59);
break;
case 2:
tempParamDuree = map(pot1Value, 0, 4095, 0, 120);
break;
}
lastPot1Value_Param = pot1Value;
}
char buffer[20]; // Buffer assez grand pour les lignes
// --- Ligne 1: Heure de démarrage ---
display2.setCursor(0, 20);
// Affiche le curseur ">" si sélectionné
if (parametrageState == 0)
display2.print(">");
else
display2.print(" ");
sprintf(buffer, "Demarrage: %02d H", tempParamHeure);
display2.print(buffer);
// Affiche un "_" clignotant
if (parametrageState == 0 && blinkState)
display2.print("_");
// --- Ligne 2: Minute de démarrage ---
display2.setCursor(0, 30);
if (parametrageState == 1)
display2.print(">");
else
display2.print(" ");
sprintf(buffer, "Minute: %02d MIN", tempParamMinute);
display2.print(buffer);
if (parametrageState == 1 && blinkState)
display2.print("_");
// --- Ligne 3: Durée ---
display2.setCursor(0, 40);
if (parametrageState == 2)
display2.print(">");
else
display2.print(" ");
sprintf(buffer, "Duree: %d MIN", tempParamDuree);
display2.print(buffer);
if (parametrageState == 2 && blinkState)
display2.print("_");
// --- Affichage Aide (CORRIGÉ - 2 LIGNES) ---
display2.drawFastHLine(0, 49, 128, SSD1306_WHITE);
display2.setCursor(0, 51);
display2.print("[MARCHE] > Suivant");
display2.setCursor(0, 58);
display2.print("[ARRET] > Valider");
}
/**
* @brief Affiche la page de réglage de l'heure (Page 2)
* (DESIGN SIMPLIFIÉ - TAILLE 2 - CORRIGÉ)
*/
void drawPageReglageHeure()
{
display2.clearDisplay();
display2.setTextSize(1);
display2.setTextColor(SSD1306_WHITE);
// Titre centré
int textWidth = 13 * 6; // "REGLAGE HEURE"
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 0);
display2.print("REGLAGE HEURE");
display2.drawFastHLine(0, 10, 128, SSD1306_WHITE);
int pot1Value = analogRead(Pot1);
if (lastPot1Value_Heure == -1)
{
lastPot1Value_Heure = pot1Value;
}
else if (abs(pot1Value - lastPot1Value_Heure) > 50)
{
if (reglageHeureState == 0)
{
tempHeures = map(pot1Value, 0, 4095, 0, 23);
}
else
{
tempMinutes = map(pot1Value, 0, 4095, 0, 59);
}
lastPot1Value_Heure = pot1Value;
}
// --- Affichage centré (Taille 2) ---
display2.setTextSize(2);
// 5 chars * 12px = 60px
textWidth = 5 * 12;
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 25); // Centré
char buffer[3];
// Heures
if (reglageHeureState == 0 && blinkState)
{
display2.print("__");
}
else
{
sprintf(buffer, "%02d", tempHeures);
display2.print(buffer);
}
display2.print(":");
// Minutes
if (reglageHeureState == 1 && blinkState)
{
display2.print("__");
}
else
{
sprintf(buffer, "%02d", tempMinutes);
display2.print(buffer);
}
// --- Affichage de l'aide --- (CORRIGÉ - 2 LIGNES)
display2.setTextSize(1);
display2.drawFastHLine(0, 49, 128, SSD1306_WHITE);
display2.setCursor(0, 51);
display2.print(reglageHeureState == 0 ? "[MARCHE] > Minutes" : "[MARCHE] > Heures");
display2.setCursor(0, 58);
display2.print("[ARRET] > Valider");
}
/**
* @brief Page de confirmation de redémarrage
* (DESIGN SIMPLIFIÉ)
*/
void drawPageRedemarrer()
{
display2.clearDisplay();
display2.setTextSize(1);
display2.setTextColor(SSD1306_WHITE);
int textWidth = 21 * 6; // "Redemarrer l'ESP32?"
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 20);
display2.print("Redemarrer l'ESP32?");
// --- Texte d'aide ---
display2.drawFastHLine(0, 54, 128, SSD1306_WHITE);
display2.setCursor(0, 56);
display2.print("[MARCHE] = OK");
display2.setCursor(128 - 60, 56); // Aligné à droite
display2.print("[ARRET] = NON");
}
/**
* @brief Page d'informations système
* (DESIGN CORRIGÉ)
*/
void drawPageInfosSystem()
{
display2.clearDisplay();
display2.setTextSize(1);
display2.setTextColor(SSD1306_WHITE);
// Titre centré
int textWidth = 13 * 6; // "INFOS SYSTEME"
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 0);
display2.print("INFOS SYSTEME");
display2.drawFastHLine(0, 10, 128, SSD1306_WHITE);
display2.setCursor(0, 15);
display2.print("Version:");
display2.setCursor(70, 15);
display2.print("1.4 (Simple)"); // Version 1.4
display2.setCursor(0, 25);
display2.print("Projet:");
display2.setCursor(70, 25);
display2.print("Pompe Citerne");
display2.setCursor(0, 35);
display2.print("By:");
display2.setCursor(70, 35);
display2.print("Freddy Diatta");
display2.drawFastHLine(0, 54, 128, SSD1306_WHITE);
// Texte d'aide centré
textWidth = 19 * 6; // "[ARRET] pour Retour"
display2.setCursor((SCREEN_WIDTH - textWidth) / 2, 56);
display2.print("[ARRET] pour Retour");
}
void redemarrerESP32()
{
display2.clearDisplay();
display2.setTextSize(2); // Plus grand
display2.setCursor(15, 20);
display2.print("Redemarrage");
display2.setCursor(45, 40);
display2.print("en cours...");
display2.display();
delay(1500); // Un peu plus long pour voir le message
ESP.restart();
}
// -------------------------------------------------
// --- NOUVELLES FONCTIONS (DESSIN DES ICÔNES) ---
// -------------------------------------------------
/**
* @brief Dessine une icône d'engrenage (Paramètres)
*/
void drawIconParam(int x, int y)
{
display2.fillCircle(x, y, 8, SSD1306_WHITE);
display2.fillCircle(x, y, 4, SSD1306_BLACK);
for (int i = 0; i < 8; i++)
{
float angle = i * PI / 4;
int x1 = x + 7 * cos(angle);
int y1 = y + 7 * sin(angle);
int x2 = x + 11 * cos(angle);
int y2 = y + 11 * sin(angle);
display2.drawLine(x1, y1, x2, y2, SSD1306_WHITE);
}
}
/**
* @brief Dessine une icône d'horloge (Réglage Heure)
*/
void drawIconHeure(int x, int y)
{
display2.drawCircle(x, y, 10, SSD1306_WHITE); // Cadran
display2.drawLine(x, y, x, y - 6, SSD1306_WHITE); // Aiguille minutes
display2.drawLine(x, y, x + 4, y, SSD1306_WHITE); // Aiguille heures
display2.drawPixel(x, y - 8, SSD1306_WHITE); // Marque 12h
}
/**
* @brief Dessine une icône de redémarrage (Power)
*/
void drawIconReboot(int x, int y)
{
display2.drawCircle(x, y, 9, SSD1306_WHITE); // Cercle extérieur
display2.drawPixel(x, y - 10, SSD1306_WHITE); // Point haut
display2.drawLine(x, y - 4, x, y + 4, SSD1306_WHITE); // Ligne verticale
}
/**
* @brief Dessine une icône d'information
*/
void drawIconInfo(int x, int y)
{
display2.drawCircle(x, y, 10, SSD1306_WHITE); // Cercle
display2.fillCircle(x, y - 4, 2, SSD1306_WHITE); // Point du "i"
display2.fillRect(x - 1, y - 1, 3, 7, SSD1306_WHITE); // Corps du "i"
}AUTO
MANU
MAINTENANCE
ARRET
MARCHE
POT1
POT2
Capteur_HAUT
Capteur_BAS