// ====================================================================================================
// Projet: Contrôleur de Granules Ver. 5.31
// Auteur: [Votre Nom]
// Description: Correction de la valeur par défaut pour l'étalonnage au démarrage.
// Correction du calcul de la consommation affichée.
// ====================================================================================================
// --- Inclusion des bibliothèques ---
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>
#include <EEPROM.h>
// --- Déclaration des broches ---
const int pinJoystickX = A0;
const int pinJoystickY = A1;
const int pinJoystickBtn = 2;
#define TFT_MENU_CS 8
#define TFT_MENU_DC 10
#define TFT_MENU_RST 9
#define TFT_INFOS_CS 13
#define TFT_INFOS_DC 11
#define TFT_INFOS_RST 12
#define PIN_RELAIS_POMPE 7
// --- Définitions de constantes pour les adresses EEPROM ---
#define EEPROM_ADDR_MAGIC_NUMBER 0 // Nouvelle adresse pour le numéro magique
#define EEPROM_ADDR_TEMPS_ON_MIN 1
#define EEPROM_ADDR_TEMPS_ON_SEC 2
#define EEPROM_ADDR_TEMPS_OFF_MIN 3
#define EEPROM_ADDR_TEMPS_OFF_SEC 4
#define EEPROM_ADDR_GRADE_GRANULES 5
#define EEPROM_ADDR_UNITE_CONSO 6
#define EEPROM_ADDR_GRANULES_PAR_MINUTE 7 // Nouvelle adresse pour le float (4 octets)
// --- Définitions de constantes pour les états ---
#define MENU_PRINCIPAL 0
#define SOUS_MENU_PARAMETRES 1
#define SOUS_MENU_DONNEES 2
#define MODE_MANUEL_EN_COURS 3
#define MODE_CYCLE_AUTOMATIQUE 4
#define REGLAGE_HEURE_EN_COURS 5
#define DEMARRER_ARRETER_CYCLE_AUTO 7
#define SOUS_MENU_TYPE_GRANULES 8
#define SOUS_MENU_UNITE_CONSO 9
#define REGLAGE_ETALONNAGE 10 // Nouvel état pour l'étalonnage
// --- Structures de données ---
struct MenuOption {
const char* nom;
int id;
};
// --- Tableaux des options de menu ---
MenuOption menuPrincipal[] = {
{"", DEMARRER_ARRETER_CYCLE_AUTO},
{"Cycle Auto", MODE_CYCLE_AUTOMATIQUE},
{"Parametres", SOUS_MENU_PARAMETRES},
{"Donnees", SOUS_MENU_DONNEES},
{"Mode Manuel", MODE_MANUEL_EN_COURS}
};
const int tailleMenuPrincipal = sizeof(menuPrincipal) / sizeof(MenuOption);
MenuOption sousMenuParametres[] = {
{"Reglage heure", REGLAGE_HEURE_EN_COURS},
{"Type de granules", SOUS_MENU_TYPE_GRANULES},
{"Consommation", SOUS_MENU_UNITE_CONSO},
{"Etalonnage", REGLAGE_ETALONNAGE},
{"Retour", MENU_PRINCIPAL}
};
const int tailleSousMenuParametres = sizeof(sousMenuParametres) / sizeof(MenuOption);
MenuOption sousMenuDonnees[] = {
{"Historique", -1},
{"Statistiques", -1},
{"Retour", MENU_PRINCIPAL}
};
const int tailleSousMenuDonnees = sizeof(sousMenuDonnees) / sizeof(MenuOption);
MenuOption sousMenuTypeGranules[] = {
{"Premium", 0},
{"Moyen", 1},
{"Economique", 2},
{"Retour", SOUS_MENU_PARAMETRES}
};
const int tailleSousMenuTypeGranules = sizeof(sousMenuTypeGranules) / sizeof(MenuOption);
MenuOption sousMenuUniteConso[] = {
{"Minute", 0},
{"Heure", 1},
{"Jour", 2},
{"Semaine", 3},
{"Mois", 4},
{"Annee", 5},
{"Retour", SOUS_MENU_PARAMETRES}
};
const int tailleSousMenuUniteConso = sizeof(sousMenuUniteConso) / sizeof(MenuOption);
// --- Variables globales pour l'état du menu ---
int menuActuel = MENU_PRINCIPAL;
int selectionActuelle = 0;
int selectionPrecedente = 0;
int champReglageHeure = 0;
int champPrecedentReglageHeure = 0;
int heureTemporaire;
int minuteTemporaire;
int jourTemporaire;
int moisTemporaire;
int anneeTemporaire;
bool pompeActive = false;
// Variables pour le mode de cycle automatique
int champCycleAuto = 0;
int champPrecedentCycleAuto = 0;
int tempsON_min_temp;
int tempsON_sec_temp;
int tempsOFF_min_temp;
int tempsOFF_sec_temp;
int tempsON_min_sauvegarde;
int tempsON_sec_sauvegarde;
int tempsOFF_min_sauvegarde;
int tempsOFF_sec_sauvegarde;
// Variables pour le cycle automatique en cours
bool cycleAutoEnCours = false;
unsigned long timerDepart;
int etatCycleAuto; // 0 = OFF, 1 = ON
// Variables pour le sous-menu "Type de granules"
int selectionGrade = 0; // 0=Premium, 1=Moyen, 2=Economique
int selectionGradeSauvegarde;
// Variables pour le sous-menu "Unite Consommation"
int selectionUniteConso = 0; // 0=Minute, 1=Heure, etc.
int selectionUniteConsoSauvegarde;
// Variables pour la gestion du joystick et le debounce
int etatBoutonJoystick = 0;
int dernierEtatBouton = HIGH;
long dernierDebounceTime = 0;
long delaiDebounce = 50;
unsigned long tempsDerniereNavigationJoystick = 0;
// Variables pour l'affichage des informations
unsigned long derniereMiseAJourInfos = 0;
const long intervalleMiseAJour = 1000;
bool premierAffichageInfos = true;
// Nouvelles variables pour l'étalonnage
float granulesParMinute = 45.0; // Valeur par défaut en grammes par minute
float granulesParMinuteSauvegarde;
int champEtalonnage = 0;
int granulesTemporaire; // pour la partie entière
int decimalesTemporaire; // pour la partie décimale
int champPrecedentEtalonnage = 0;
// Constantes pour l'énergie par grade (valeurs par défaut)
#define ENERGIE_KWH_PREMIUM 4.8 // kWh par kg
#define ENERGIE_KWH_MOYEN 4.5 // kWh par kg
#define ENERGIE_KWH_ECONOMIQUE 4.2 // kWh par kg
#define KWH_TO_BTU 3412.14 // Facteur de conversion
// Création des objets pour les écrans et le RTC
Adafruit_ILI9341 Lcd_Menu = Adafruit_ILI9341(TFT_MENU_CS, TFT_MENU_DC, TFT_MENU_RST);
Adafruit_ILI9341 Lcd_Infos = Adafruit_ILI9341(TFT_INFOS_CS, TFT_INFOS_DC, TFT_INFOS_RST);
RTC_DS1307 rtc;
// --- Fonctions utilitaires pour la date ---
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int daysInMonth(int month, int year) {
if (month == 2) {
return isLeapYear(year) ? 29 : 28;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
return 31;
}
}
// Fonction utilitaire pour sauvegarder et lire un float en EEPROM
void EEPROM_writeFloat(int address, float value) {
byte* p = (byte*)(void*)&value;
for (int i = 0; i < sizeof(value); i++) {
EEPROM.write(address + i, *p++);
}
}
float EEPROM_readFloat(int address) {
float value;
byte* p = (byte*)(void*)&value;
for (int i = 0; i < sizeof(value); i++) {
*p++ = EEPROM.read(address + i);
}
return value;
}
// --- Fonctions modulaires ---
void dessinerOption(int index, bool estSelectionnee, MenuOption* menu, int taille) {
int yPos = 55 + (index * 25);
Lcd_Menu.setTextSize(2);
if (estSelectionnee) {
Lcd_Menu.setTextColor(ILI9341_BLACK);
Lcd_Menu.fillRect(10, yPos - 3, Lcd_Menu.width() - 20, 22, ILI9341_YELLOW);
} else {
Lcd_Menu.setTextColor(ILI9341_WHITE);
Lcd_Menu.fillRect(10, yPos - 3, Lcd_Menu.width() - 20, 22, ILI9341_BLACK);
}
Lcd_Menu.setCursor(20, yPos);
if (menuActuel == MENU_PRINCIPAL && index == 0) {
if (cycleAutoEnCours) {
Lcd_Menu.print("Arreter Cycle Auto");
} else {
Lcd_Menu.print("Demarrer Cycle Auto");
}
} else {
Lcd_Menu.print(menu[index].nom);
}
}
void dessinerMenuComplet() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
MenuOption* menu = nullptr;
int taille = 0;
if (menuActuel == MENU_PRINCIPAL) {
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Menu");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
menu = menuPrincipal;
taille = tailleMenuPrincipal;
} else if (menuActuel == SOUS_MENU_PARAMETRES) {
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Parametres");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
menu = sousMenuParametres;
taille = tailleSousMenuParametres;
} else if (menuActuel == SOUS_MENU_DONNEES) {
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Donnees");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
menu = sousMenuDonnees;
taille = tailleSousMenuDonnees;
} else if (menuActuel == SOUS_MENU_TYPE_GRANULES) {
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Type de granules");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
menu = sousMenuTypeGranules;
taille = tailleSousMenuTypeGranules;
} else if (menuActuel == SOUS_MENU_UNITE_CONSO) {
Lcd_Menu.setTextSize(2);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Unite Consommation");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
menu = sousMenuUniteConso;
taille = tailleSousMenuUniteConso;
}
if (menu != nullptr) {
for (int i = 0; i < taille; i++) {
dessinerOption(i, i == selectionActuelle, menu, taille);
}
}
}
void sauvegarderHeureRTC() {
DateTime nouvelleHeure(anneeTemporaire, moisTemporaire, jourTemporaire, heureTemporaire, minuteTemporaire, 0);
rtc.adjust(nouvelleHeure);
menuActuel = SOUS_MENU_PARAMETRES;
selectionActuelle = 0;
dessinerMenuComplet();
}
void dessinerUnChampDeHeure(int champ, bool estSelectionne) {
Lcd_Menu.setTextSize(2);
if (estSelectionne) {
Lcd_Menu.setTextColor(ILI9341_BLACK, ILI9341_YELLOW);
} else {
Lcd_Menu.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
}
if (champ == 0) {
Lcd_Menu.setCursor(100, 60);
Lcd_Menu.fillRect(100, 60, 40, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(100, 60);
if (heureTemporaire < 10) Lcd_Menu.print('0');
Lcd_Menu.print(heureTemporaire, DEC);
} else if (champ == 1) {
Lcd_Menu.setCursor(150, 60);
Lcd_Menu.fillRect(150, 60, 40, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(150, 60);
if (minuteTemporaire < 10) Lcd_Menu.print('0');
Lcd_Menu.print(minuteTemporaire, DEC);
} else if (champ == 2) {
Lcd_Menu.setCursor(100, 90);
Lcd_Menu.fillRect(100, 90, 40, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(100, 90);
if (jourTemporaire < 10) Lcd_Menu.print('0');
Lcd_Menu.print(jourTemporaire, DEC);
} else if (champ == 3) {
Lcd_Menu.setCursor(150, 90);
Lcd_Menu.fillRect(150, 90, 40, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(150, 90);
if (moisTemporaire < 10) Lcd_Menu.print('0');
Lcd_Menu.print(moisTemporaire, DEC);
} else if (champ == 4) {
Lcd_Menu.setCursor(200, 90);
Lcd_Menu.fillRect(200, 90, 60, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(200, 90);
Lcd_Menu.print(anneeTemporaire, DEC);
} else if (champ == 5) {
Lcd_Menu.setCursor(10, 150);
Lcd_Menu.fillRect(10, 147, Lcd_Menu.width() - 20, 22, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(20, 150);
Lcd_Menu.print("Sauvegarder");
} else if (champ == 6) {
Lcd_Menu.setCursor(10, 180);
Lcd_Menu.fillRect(10, 177, Lcd_Menu.width() - 20, 22, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(20, 180);
Lcd_Menu.print("Annuler");
}
}
void dessinerReglageHeureComplet() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Regler l'heure");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
Lcd_Menu.setTextSize(2);
Lcd_Menu.setTextColor(ILI9341_WHITE);
Lcd_Menu.setCursor(10, 60);
Lcd_Menu.print("Heure: ");
Lcd_Menu.setCursor(140, 60);
Lcd_Menu.print(":");
Lcd_Menu.setCursor(10, 90);
Lcd_Menu.print("Date: ");
Lcd_Menu.setCursor(140, 90);
Lcd_Menu.print("/");
Lcd_Menu.setCursor(190, 90);
Lcd_Menu.print("/");
for (int i = 0; i <= 6; i++) {
dessinerUnChampDeHeure(i, i == champReglageHeure);
}
}
void afficherModeManuel() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Mode Manuel");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
Lcd_Menu.setTextSize(2);
Lcd_Menu.setCursor(20, 60);
Lcd_Menu.setTextColor(ILI9341_WHITE);
Lcd_Menu.print("Pompe a granules: ");
Lcd_Menu.setCursor(20, 120);
Lcd_Menu.setTextColor(ILI9341_YELLOW);
Lcd_Menu.println("Pressez le bouton pour basculer.");
}
void mettreAJourEtatPompe() {
Lcd_Menu.setTextSize(2);
Lcd_Menu.setCursor(20, 90);
Lcd_Menu.fillRect(20, 90, 200, 20, ILI9341_BLACK);
if (pompeActive) {
Lcd_Menu.setTextColor(ILI9341_GREEN);
Lcd_Menu.print("ACTIVE");
digitalWrite(PIN_RELAIS_POMPE, HIGH);
} else {
Lcd_Menu.setTextColor(ILI9341_RED);
Lcd_Menu.print("INACTIVE");
digitalWrite(PIN_RELAIS_POMPE, LOW);
}
}
void dessinerUnChampDeCycle(int champ, int val) {
Lcd_Menu.setTextSize(2);
Lcd_Menu.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
int xPos = (champ == 0 || champ == 2) ? 150 : 200;
int yPos = (champ == 0 || champ == 1) ? 60 : 90;
Lcd_Menu.fillRect(xPos, yPos, 40, 16, ILI9341_BLACK);
Lcd_Menu.setCursor(xPos, yPos);
if (val < 10) Lcd_Menu.print('0');
Lcd_Menu.print(val, DEC);
}
void dessinerSelection(int champ, bool estSelectionne) {
int xPos = 0;
int yPos = 0;
int width = 0;
int height = 0;
if (champ <= 3) {
xPos = (champ == 0 || champ == 2) ? 148 : 198;
yPos = (champ == 0 || champ == 1) ? 58 : 88;
width = 44;
height = 20;
} else if (champ == 4) { // Sauvegarder
xPos = 8;
yPos = 145;
width = Lcd_Menu.width() - 16;
height = 26;
} else if (champ == 5) { // Annuler
xPos = 8;
yPos = 175;
width = Lcd_Menu.width() - 16;
height = 26;
}
if (estSelectionne) {
Lcd_Menu.drawRect(xPos, yPos, width, height, ILI9341_YELLOW);
} else {
Lcd_Menu.drawRect(xPos, yPos, width, height, ILI9341_BLACK);
}
}
void dessinerProgrammationComplet() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Cycle Auto");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
Lcd_Menu.setTextSize(2);
Lcd_Menu.setTextColor(ILI9341_WHITE);
Lcd_Menu.setCursor(20, 60);
Lcd_Menu.print("Temps ON : ");
Lcd_Menu.setCursor(190, 60);
Lcd_Menu.print(":"); // Séparateur fixe
Lcd_Menu.setCursor(20, 90);
Lcd_Menu.print("Temps OFF:");
Lcd_Menu.setCursor(190, 90);
Lcd_Menu.print(":"); // Séparateur fixe
dessinerUnChampDeCycle(0, tempsON_min_temp);
dessinerUnChampDeCycle(1, tempsON_sec_temp);
dessinerUnChampDeCycle(2, tempsOFF_min_temp);
dessinerUnChampDeCycle(3, tempsOFF_sec_temp);
Lcd_Menu.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
Lcd_Menu.setCursor(20, 150);
Lcd_Menu.print("Sauvegarder");
Lcd_Menu.setCursor(20, 180);
Lcd_Menu.print("Annuler");
dessinerSelection(champCycleAuto, true);
}
void dessinerSousMenuTypeGranules() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Type de granules");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
MenuOption* menu = sousMenuTypeGranules;
int taille = tailleSousMenuTypeGranules;
for (int i = 0; i < taille; i++) {
dessinerOption(i, i == selectionActuelle, menu, taille);
}
}
void dessinerSousMenuUniteConso() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
Lcd_Menu.setTextSize(2);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Unite Consommation");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
MenuOption* menu = sousMenuUniteConso;
int taille = tailleSousMenuUniteConso;
for (int i = 0; i < taille; i++) {
dessinerOption(i, i == selectionActuelle, menu, taille);
}
}
void dessinerUnChampEtalonnage(int champ, bool estSelectionne) {
Lcd_Menu.setTextSize(2);
if (estSelectionne) {
Lcd_Menu.setTextColor(ILI9341_BLACK, ILI9341_YELLOW);
} else {
Lcd_Menu.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
}
if (champ == 0) {
Lcd_Menu.setCursor(110, 60);
Lcd_Menu.fillRect(110, 60, 40, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(110, 60);
Lcd_Menu.print(granulesTemporaire, DEC);
} else if (champ == 1) {
Lcd_Menu.setCursor(160, 60);
Lcd_Menu.fillRect(160, 60, 40, 16, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(160, 60);
Lcd_Menu.print(decimalesTemporaire, DEC);
} else if (champ == 2) {
Lcd_Menu.setCursor(10, 150);
Lcd_Menu.fillRect(10, 147, Lcd_Menu.width() - 20, 22, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(20, 150);
Lcd_Menu.print("Sauvegarder");
} else if (champ == 3) {
Lcd_Menu.setCursor(10, 180);
Lcd_Menu.fillRect(10, 177, Lcd_Menu.width() - 20, 22, estSelectionne ? ILI9341_YELLOW : ILI9341_BLACK);
Lcd_Menu.setCursor(20, 180);
Lcd_Menu.print("Annuler");
}
}
void dessinerReglageEtalonnageComplet() {
Lcd_Menu.fillScreen(ILI9341_BLACK);
Lcd_Menu.setCursor(10, 10);
Lcd_Menu.setTextSize(3);
Lcd_Menu.setTextColor(ILI9341_CYAN);
Lcd_Menu.println("Etalonnage");
Lcd_Menu.drawFastHLine(0, 40, Lcd_Menu.width(), ILI9341_CYAN);
Lcd_Menu.setTextSize(2);
Lcd_Menu.setTextColor(ILI9341_WHITE);
Lcd_Menu.setCursor(10, 60);
Lcd_Menu.print("g/min: ");
Lcd_Menu.setCursor(150, 60);
Lcd_Menu.print(".");
Lcd_Menu.setCursor(200, 60);
Lcd_Menu.print("g/min");
dessinerUnChampEtalonnage(0, champEtalonnage == 0);
dessinerUnChampEtalonnage(1, champEtalonnage == 1);
dessinerUnChampEtalonnage(2, champEtalonnage == 2);
dessinerUnChampEtalonnage(3, champEtalonnage == 3);
}
// Nouvelle fonction pour calculer le débit moyen de granules en g/h
float calculerGranulesHeureMoyen() {
float tempsON_sec = (tempsON_min_sauvegarde * 60) + tempsON_sec_sauvegarde;
float tempsOFF_sec = (tempsOFF_min_sauvegarde * 60) + tempsOFF_sec_sauvegarde;
float dureeCycle = tempsON_sec + tempsOFF_sec;
float ratioON = (dureeCycle > 0) ? tempsON_sec / dureeCycle : 0.0;
return granulesParMinuteSauvegarde * 60.0 * ratioON;
}
// Mise à jour de la fonction pour calculer la conso par unité
float calculerGranulesParUnite(int unite) {
float granulesParHeure = calculerGranulesHeureMoyen();
float facteurConversion = 1.0; // Par minute
if (unite == 1) facteurConversion = 1.0; // Par heure
else if (unite == 2) facteurConversion = 24.0; // Par jour
else if (unite == 3) facteurConversion = 24.0 * 7.0; // Par semaine
else if (unite == 4) facteurConversion = 24.0 * 30.4375; // Moyenne mensuelle
else if (unite == 5) facteurConversion = 24.0 * 365.25; // Moyenne annuelle
// Correction : si l'unité est "minute" on divise le granules/heure par 60
if (unite == 0) {
return granulesParHeure / 60.0;
}
return granulesParHeure * facteurConversion;
}
// Mise à jour de la fonction pour calculer la puissance et l'énergie
void calculerPuissanceEnergie(float* btu, float* kwh) {
float granulesParHeure = calculerGranulesHeureMoyen();
float energie_kwh_par_kg = 0;
if (selectionGradeSauvegarde == 0) {
energie_kwh_par_kg = ENERGIE_KWH_PREMIUM;
} else if (selectionGradeSauvegarde == 1) {
energie_kwh_par_kg = ENERGIE_KWH_MOYEN;
} else if (selectionGradeSauvegarde == 2) {
energie_kwh_par_kg = ENERGIE_KWH_ECONOMIQUE;
}
*kwh = (granulesParHeure / 1000.0) * energie_kwh_par_kg;
*btu = (*kwh) * KWH_TO_BTU;
}
void afficherCompteAReboursInfos() {
static unsigned long previousRemainingTime = 0;
static int previousStatus = -1;
static bool previousCycleState = false;
unsigned long tempsEcoule = millis() - timerDepart;
unsigned long tempsRestant;
Lcd_Infos.setTextSize(2);
Lcd_Infos.setTextColor(ILI9341_WHITE, ILI9341_BLUE);
if (cycleAutoEnCours != previousCycleState) {
Lcd_Infos.fillRect(100, 135, 120, 16, ILI9341_BLUE);
Lcd_Infos.setCursor(100, 135);
if (cycleAutoEnCours) {
Lcd_Infos.setTextColor(ILI9341_GREEN);
Lcd_Infos.print("EN COURS");
} else {
Lcd_Infos.setTextColor(ILI9341_RED);
Lcd_Infos.print("ARRETE");
}
previousCycleState = cycleAutoEnCours;
previousStatus = -1;
return;
}
if (cycleAutoEnCours) {
if (etatCycleAuto != previousStatus) {
Lcd_Infos.fillRect(200, 85, 40, 16, ILI9341_BLUE);
Lcd_Infos.fillRect(200, 105, 40, 16, ILI9341_BLUE);
Lcd_Infos.setTextColor(ILI9341_YELLOW, ILI9341_BLUE);
if (etatCycleAuto == 1) {
unsigned long dureeTotaleON = (tempsON_min_sauvegarde * 60 + tempsON_sec_sauvegarde) * 1000UL;
tempsRestant = (dureeTotaleON > tempsEcoule) ? dureeTotaleON - tempsEcoule : 0;
int secondesRestantes = tempsRestant / 1000;
int minutesRestantes = secondesRestantes / 60;
secondesRestantes %= 60;
Lcd_Infos.setCursor(200, 85);
if (minutesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(minutesRestantes);
Lcd_Infos.print(":");
if (secondesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(secondesRestantes);
} else {
unsigned long dureeTotaleOFF = (tempsOFF_min_sauvegarde * 60 + tempsOFF_sec_sauvegarde) * 1000UL;
tempsRestant = (dureeTotaleOFF > tempsEcoule) ? dureeTotaleOFF - tempsEcoule : 0;
int secondesRestantes = tempsRestant / 1000;
int minutesRestantes = secondesRestantes / 60;
secondesRestantes %= 60;
Lcd_Infos.setCursor(200, 105);
if (minutesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(minutesRestantes);
Lcd_Infos.print(":");
if (secondesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(secondesRestantes);
}
previousStatus = etatCycleAuto;
previousRemainingTime = tempsRestant / 1000;
return;
}
unsigned long currentRemainingTime = (etatCycleAuto == 1) ?
((tempsON_min_sauvegarde * 60 + tempsON_sec_sauvegarde) * 1000UL > tempsEcoule ? ((tempsON_min_sauvegarde * 60 + tempsON_sec_sauvegarde) * 1000UL - tempsEcoule) / 1000 : 0) :
((tempsOFF_min_sauvegarde * 60 + tempsOFF_sec_sauvegarde) * 1000UL > tempsEcoule ? ((tempsOFF_min_sauvegarde * 60 + tempsOFF_sec_sauvegarde) * 1000UL - tempsEcoule) / 1000 : 0);
if (currentRemainingTime != previousRemainingTime) {
int secondesRestantes = currentRemainingTime;
int minutesRestantes = secondesRestantes / 60;
secondesRestantes %= 60;
Lcd_Infos.setTextColor(ILI9341_YELLOW, ILI9341_BLUE);
if (etatCycleAuto == 1) {
Lcd_Infos.setCursor(200, 85);
Lcd_Infos.fillRect(200, 85, 40, 16, ILI9341_BLUE);
if (minutesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(minutesRestantes);
Lcd_Infos.print(":");
if (secondesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(secondesRestantes);
} else {
Lcd_Infos.setCursor(200, 105);
Lcd_Infos.fillRect(200, 105, 40, 16, ILI9341_BLUE);
if (minutesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(minutesRestantes);
Lcd_Infos.print(":");
if (secondesRestantes < 10) Lcd_Infos.print('0');
Lcd_Infos.print(secondesRestantes);
}
previousRemainingTime = currentRemainingTime;
}
}
}
void afficherInfos() {
static char previousTime[9] = "";
static char previousDate[11] = "";
static int previousONMin = -1;
static int previousONSec = -1;
static int previousOFFMin = -1;
static int previousOFFSec = -1;
static float previousConsoEstimee = -1.0;
static float previousKwhHeure = -1.0;
static float previousBtuHeure = -1.0;
if (premierAffichageInfos) {
Lcd_Infos.fillScreen(ILI9341_BLUE);
Lcd_Infos.setCursor(0, 0);
Lcd_Infos.setTextSize(2);
Lcd_Infos.setTextColor(ILI9341_WHITE);
Lcd_Infos.println("Infos Systeme");
Lcd_Infos.println("--------------------");
Lcd_Infos.setCursor(0, 35);
Lcd_Infos.print("Heure: ");
Lcd_Infos.setCursor(0, 55);
Lcd_Infos.print("Date: ");
Lcd_Infos.setCursor(0, 85);
Lcd_Infos.print("Temps ON: ");
Lcd_Infos.setCursor(0, 105);
Lcd_Infos.print("Temps OFF:");
Lcd_Infos.setCursor(0, 135);
Lcd_Infos.print("Cycle:");
Lcd_Infos.setCursor(0, 160);
Lcd_Infos.print("Conso est:");
Lcd_Infos.setCursor(0, 180);
Lcd_Infos.print("Energie est:");
Lcd_Infos.setCursor(0, 200);
Lcd_Infos.print(" - kWh/h:");
Lcd_Infos.setCursor(0, 220);
Lcd_Infos.print(" - BTU/h:");
premierAffichageInfos = false;
}
DateTime now = rtc.now();
Lcd_Infos.setTextSize(2);
Lcd_Infos.setTextColor(ILI9341_WHITE, ILI9341_BLUE);
char currentTime[9];
sprintf(currentTime, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
if (strcmp(currentTime, previousTime) != 0) {
Lcd_Infos.setCursor(85, 35);
Lcd_Infos.print(currentTime);
strcpy(previousTime, currentTime);
}
char currentDate[11];
sprintf(currentDate, "%02d/%02d/%04d", now.day(), now.month(), now.year());
if (strcmp(currentDate, previousDate) != 0) {
Lcd_Infos.setCursor(85, 55);
Lcd_Infos.print(currentDate);
strcpy(previousDate, currentDate);
}
if (tempsON_min_sauvegarde != previousONMin || tempsON_sec_sauvegarde != previousONSec) {
Lcd_Infos.setCursor(120, 85);
Lcd_Infos.fillRect(120, 85, 60, 16, ILI9341_BLUE);
if (tempsON_min_sauvegarde < 10) Lcd_Infos.print('0');
Lcd_Infos.print(tempsON_min_sauvegarde);
Lcd_Infos.print(":");
if (tempsON_sec_sauvegarde < 10) Lcd_Infos.print('0');
Lcd_Infos.print(tempsON_sec_sauvegarde);
previousONMin = tempsON_min_sauvegarde;
previousONSec = tempsON_sec_sauvegarde;
}
if (tempsOFF_min_sauvegarde != previousOFFMin || tempsOFF_sec_sauvegarde != previousOFFSec) {
Lcd_Infos.setCursor(120, 105);
Lcd_Infos.fillRect(120, 105, 60, 16, ILI9341_BLUE);
if (tempsOFF_min_sauvegarde < 10) Lcd_Infos.print('0');
Lcd_Infos.print(tempsOFF_min_sauvegarde);
Lcd_Infos.print(":");
if (tempsOFF_sec_sauvegarde < 10) Lcd_Infos.print('0');
Lcd_Infos.print(tempsOFF_sec_sauvegarde);
previousOFFMin = tempsOFF_min_sauvegarde;
previousOFFSec = tempsOFF_sec_sauvegarde;
}
float consoEstimee = calculerGranulesParUnite(selectionUniteConsoSauvegarde);
if (abs(consoEstimee - previousConsoEstimee) > 0.01) {
Lcd_Infos.setCursor(120, 160);
Lcd_Infos.fillRect(120, 160, 120, 16, ILI9341_BLUE);
Lcd_Infos.print(consoEstimee, 1);
Lcd_Infos.print(" g/");
if (selectionUniteConsoSauvegarde == 0) Lcd_Infos.print("min");
else if (selectionUniteConsoSauvegarde == 1) Lcd_Infos.print("h");
else if (selectionUniteConsoSauvegarde == 2) Lcd_Infos.print("j");
else if (selectionUniteConsoSauvegarde == 3) Lcd_Infos.print("sem");
else if (selectionUniteConsoSauvegarde == 4) Lcd_Infos.print("mois");
else if (selectionUniteConsoSauvegarde == 5) Lcd_Infos.print("an");
previousConsoEstimee = consoEstimee;
}
float btuHeure, kwhHeure;
calculerPuissanceEnergie(&btuHeure, &kwhHeure);
if (abs(kwhHeure - previousKwhHeure) > 0.01) {
Lcd_Infos.setCursor(120, 200);
Lcd_Infos.fillRect(120, 200, 120, 16, ILI9341_BLUE);
Lcd_Infos.print(kwhHeure, 1);
previousKwhHeure = kwhHeure;
}
if (abs(btuHeure - previousBtuHeure) > 1.0) {
Lcd_Infos.setCursor(120, 220);
Lcd_Infos.fillRect(120, 220, 120, 16, ILI9341_BLUE);
Lcd_Infos.print(btuHeure, 0);
previousBtuHeure = btuHeure;
}
afficherCompteAReboursInfos();
}
void naviguer(int direction) {
selectionPrecedente = selectionActuelle;
MenuOption* menu = nullptr;
int taille = 0;
if (menuActuel == MENU_PRINCIPAL) {
menu = menuPrincipal;
taille = tailleMenuPrincipal;
} else if (menuActuel == SOUS_MENU_PARAMETRES) {
menu = sousMenuParametres;
taille = tailleSousMenuParametres;
} else if (menuActuel == SOUS_MENU_DONNEES) {
menu = sousMenuDonnees;
taille = tailleSousMenuDonnees;
} else if (menuActuel == SOUS_MENU_TYPE_GRANULES) {
menu = sousMenuTypeGranules;
taille = tailleSousMenuTypeGranules;
} else if (menuActuel == SOUS_MENU_UNITE_CONSO) {
menu = sousMenuUniteConso;
taille = tailleSousMenuUniteConso;
}
if (menu != nullptr) {
selectionActuelle += direction;
if (selectionActuelle < 0) {
selectionActuelle = taille - 1;
} else if (selectionActuelle >= taille) {
selectionActuelle = 0;
}
// Mise à jour sélective pour éviter le scintillement
dessinerOption(selectionPrecedente, false, menu, taille);
dessinerOption(selectionActuelle, true, menu, taille);
}
}
void selectionner() {
MenuOption* menu = nullptr;
int taille = 0;
if (menuActuel == MENU_PRINCIPAL) {
menu = menuPrincipal;
taille = tailleMenuPrincipal;
} else if (menuActuel == SOUS_MENU_PARAMETRES) {
menu = sousMenuParametres;
taille = tailleSousMenuParametres;
} else if (menuActuel == SOUS_MENU_DONNEES) {
menu = sousMenuDonnees;
taille = tailleSousMenuDonnees;
} else if (menuActuel == SOUS_MENU_TYPE_GRANULES) {
menu = sousMenuTypeGranules;
taille = tailleSousMenuTypeGranules;
} else if (menuActuel == SOUS_MENU_UNITE_CONSO) {
menu = sousMenuUniteConso;
taille = tailleSousMenuUniteConso;
}
if (menu != nullptr) {
int nouvelleAction = menu[selectionActuelle].id;
if (menuActuel == MENU_PRINCIPAL && nouvelleAction == DEMARRER_ARRETER_CYCLE_AUTO) {
cycleAutoEnCours = !cycleAutoEnCours;
if (cycleAutoEnCours) {
etatCycleAuto = 1;
digitalWrite(PIN_RELAIS_POMPE, HIGH);
timerDepart = millis();
} else {
digitalWrite(PIN_RELAIS_POMPE, LOW);
}
dessinerMenuComplet();
} else if (nouvelleAction == SOUS_MENU_TYPE_GRANULES) {
menuActuel = SOUS_MENU_TYPE_GRANULES;
selectionActuelle = selectionGrade;
dessinerSousMenuTypeGranules();
} else if (nouvelleAction == SOUS_MENU_UNITE_CONSO) {
menuActuel = SOUS_MENU_UNITE_CONSO;
selectionActuelle = selectionUniteConso;
dessinerSousMenuUniteConso();
} else if (nouvelleAction == REGLAGE_ETALONNAGE) {
menuActuel = REGLAGE_ETALONNAGE;
granulesTemporaire = (int)granulesParMinute;
decimalesTemporaire = (int)((granulesParMinute - granulesTemporaire) * 10.0);
champEtalonnage = 0;
champPrecedentEtalonnage = 0;
dessinerReglageEtalonnageComplet();
} else if (nouvelleAction >= 0) {
menuActuel = nouvelleAction;
selectionActuelle = 0;
if (menuActuel == REGLAGE_HEURE_EN_COURS) {
DateTime now = rtc.now();
heureTemporaire = now.hour();
minuteTemporaire = now.minute();
jourTemporaire = now.day();
moisTemporaire = now.month();
anneeTemporaire = now.year();
champReglageHeure = 0;
champPrecedentReglageHeure = 0;
dessinerReglageHeureComplet();
} else if (menuActuel == MODE_MANUEL_EN_COURS) {
afficherModeManuel();
mettreAJourEtatPompe();
} else if (menuActuel == MODE_CYCLE_AUTOMATIQUE) {
tempsON_min_temp = tempsON_min_sauvegarde;
tempsON_sec_temp = tempsON_sec_sauvegarde;
tempsOFF_min_temp = tempsOFF_min_sauvegarde;
tempsOFF_sec_temp = tempsOFF_sec_sauvegarde;
champCycleAuto = 0;
champPrecedentCycleAuto = 0;
dessinerProgrammationComplet();
} else {
dessinerMenuComplet();
}
}
}
}
// ====================================================================================================
// Fonctions setup() et loop() de l'Arduino
// ====================================================================================================
void setup() {
pinMode(pinJoystickBtn, INPUT_PULLUP);
pinMode(PIN_RELAIS_POMPE, OUTPUT);
Lcd_Menu.begin();
Lcd_Menu.setRotation(1);
Lcd_Infos.begin();
Lcd_Infos.setRotation(1);
Wire.begin();
if (! rtc.begin()) {
Lcd_Infos.fillScreen(ILI9341_RED);
Lcd_Infos.setTextColor(ILI9341_WHITE);
Lcd_Infos.setCursor(0,0);
Lcd_Infos.println("Erreur RTC !");
while (1);
}
if (EEPROM.read(EEPROM_ADDR_MAGIC_NUMBER) != 0xDE) {
// Premier demarrage, on initialise avec les valeurs par defaut
tempsON_min_sauvegarde = 0;
tempsON_sec_sauvegarde = 5;
tempsOFF_min_sauvegarde = 0;
tempsOFF_sec_sauvegarde = 10;
selectionGradeSauvegarde = 0;
selectionUniteConsoSauvegarde = 0;
granulesParMinuteSauvegarde = 45.0; // La valeur par défaut pour l'étalonnage
EEPROM.write(EEPROM_ADDR_MAGIC_NUMBER, 0xDE);
EEPROM.write(EEPROM_ADDR_TEMPS_ON_MIN, tempsON_min_sauvegarde);
EEPROM.write(EEPROM_ADDR_TEMPS_ON_SEC, tempsON_sec_sauvegarde);
EEPROM.write(EEPROM_ADDR_TEMPS_OFF_MIN, tempsOFF_min_sauvegarde);
EEPROM.write(EEPROM_ADDR_TEMPS_OFF_SEC, tempsOFF_sec_sauvegarde);
EEPROM.write(EEPROM_ADDR_GRADE_GRANULES, selectionGradeSauvegarde);
EEPROM.write(EEPROM_ADDR_UNITE_CONSO, selectionUniteConsoSauvegarde);
EEPROM_writeFloat(EEPROM_ADDR_GRANULES_PAR_MINUTE, granulesParMinuteSauvegarde);
} else {
// EEPROM deja initialisee, on charge les valeurs
tempsON_min_sauvegarde = EEPROM.read(EEPROM_ADDR_TEMPS_ON_MIN);
tempsON_sec_sauvegarde = EEPROM.read(EEPROM_ADDR_TEMPS_ON_SEC);
tempsOFF_min_sauvegarde = EEPROM.read(EEPROM_ADDR_TEMPS_OFF_MIN);
tempsOFF_sec_sauvegarde = EEPROM.read(EEPROM_ADDR_TEMPS_OFF_SEC);
selectionGradeSauvegarde = EEPROM.read(EEPROM_ADDR_GRADE_GRANULES);
selectionUniteConsoSauvegarde = EEPROM.read(EEPROM_ADDR_UNITE_CONSO);
granulesParMinuteSauvegarde = EEPROM_readFloat(EEPROM_ADDR_GRANULES_PAR_MINUTE);
}
// Des verification de validite, au cas ou les valeurs EEPROM sont corrompues
if (tempsON_min_sauvegarde > 60) tempsON_min_sauvegarde = 0;
if (tempsON_sec_sauvegarde > 60) tempsON_sec_sauvegarde = 5;
if (tempsOFF_min_sauvegarde > 60) tempsOFF_min_sauvegarde = 0;
if (tempsOFF_sec_sauvegarde > 60) tempsOFF_sec_sauvegarde = 10;
if (selectionGradeSauvegarde > 2) selectionGradeSauvegarde = 0;
if (selectionUniteConsoSauvegarde > 5) selectionUniteConsoSauvegarde = 0;
if (granulesParMinuteSauvegarde < 0 || granulesParMinuteSauvegarde > 999.9) granulesParMinuteSauvegarde = 45.0;
selectionGrade = selectionGradeSauvegarde;
selectionUniteConso = selectionUniteConsoSauvegarde;
granulesParMinute = granulesParMinuteSauvegarde;
dessinerMenuComplet();
afficherInfos();
}
void loop() {
unsigned long tempsActuel = millis();
if (cycleAutoEnCours) {
unsigned long dureeTotaleON = (tempsON_min_sauvegarde * 60 + tempsON_sec_sauvegarde) * 1000UL;
unsigned long dureeTotaleOFF = (tempsOFF_min_sauvegarde * 60 + tempsOFF_sec_sauvegarde) * 1000UL;
if (etatCycleAuto == 1) {
if (millis() - timerDepart >= dureeTotaleON) {
etatCycleAuto = 0;
timerDepart = millis();
digitalWrite(PIN_RELAIS_POMPE, LOW);
}
} else {
if (millis() - timerDepart >= dureeTotaleOFF) {
etatCycleAuto = 1;
timerDepart = millis();
digitalWrite(PIN_RELAIS_POMPE, HIGH);
}
}
}
if (menuActuel == MENU_PRINCIPAL || menuActuel == SOUS_MENU_PARAMETRES || menuActuel == SOUS_MENU_DONNEES) {
if (tempsActuel - tempsDerniereNavigationJoystick > 200) {
int valY = analogRead(pinJoystickY);
if (valY < 200) {
naviguer(-1);
tempsDerniereNavigationJoystick = tempsActuel;
}
if (valY > 800) {
naviguer(1);
tempsDerniereNavigationJoystick = tempsActuel;
}
}
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
selectionner();
}
}
}
dernierEtatBouton = lectureBouton;
} else if (menuActuel == SOUS_MENU_TYPE_GRANULES) {
if (tempsActuel - tempsDerniereNavigationJoystick > 200) {
int valY = analogRead(pinJoystickY);
if (valY < 200) {
selectionPrecedente = selectionActuelle;
selectionActuelle = (selectionActuelle - 1 + tailleSousMenuTypeGranules) % tailleSousMenuTypeGranules;
dessinerOption(selectionPrecedente, false, sousMenuTypeGranules, tailleSousMenuTypeGranules);
dessinerOption(selectionActuelle, true, sousMenuTypeGranules, tailleSousMenuTypeGranules);
tempsDerniereNavigationJoystick = tempsActuel;
}
if (valY > 800) {
selectionPrecedente = selectionActuelle;
selectionActuelle = (selectionActuelle + 1) % tailleSousMenuTypeGranules;
dessinerOption(selectionPrecedente, false, sousMenuTypeGranules, tailleSousMenuTypeGranules);
dessinerOption(selectionActuelle, true, sousMenuTypeGranules, tailleSousMenuTypeGranules);
tempsDerniereNavigationJoystick = tempsActuel;
}
}
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
if (sousMenuTypeGranules[selectionActuelle].id >= 0) {
selectionGrade = sousMenuTypeGranules[selectionActuelle].id;
EEPROM.write(EEPROM_ADDR_GRADE_GRANULES, selectionGrade);
menuActuel = SOUS_MENU_PARAMETRES;
selectionActuelle = 1;
dessinerMenuComplet();
} else {
menuActuel = sousMenuTypeGranules[selectionActuelle].id;
selectionActuelle = 0;
dessinerMenuComplet();
}
}
}
}
dernierEtatBouton = lectureBouton;
} else if (menuActuel == SOUS_MENU_UNITE_CONSO) {
if (tempsActuel - tempsDerniereNavigationJoystick > 200) {
int valY = analogRead(pinJoystickY);
if (valY < 200) {
selectionPrecedente = selectionActuelle;
selectionActuelle = (selectionActuelle - 1 + tailleSousMenuUniteConso) % tailleSousMenuUniteConso;
dessinerOption(selectionPrecedente, false, sousMenuUniteConso, tailleSousMenuUniteConso);
dessinerOption(selectionActuelle, true, sousMenuUniteConso, tailleSousMenuUniteConso);
tempsDerniereNavigationJoystick = tempsActuel;
}
if (valY > 800) {
selectionPrecedente = selectionActuelle;
selectionActuelle = (selectionActuelle + 1) % tailleSousMenuUniteConso;
dessinerOption(selectionPrecedente, false, sousMenuUniteConso, tailleSousMenuUniteConso);
dessinerOption(selectionActuelle, true, sousMenuUniteConso, tailleSousMenuUniteConso);
tempsDerniereNavigationJoystick = tempsActuel;
}
}
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
if (sousMenuUniteConso[selectionActuelle].id >= 0) {
selectionUniteConso = sousMenuUniteConso[selectionActuelle].id;
EEPROM.write(EEPROM_ADDR_UNITE_CONSO, selectionUniteConso);
menuActuel = SOUS_MENU_PARAMETRES;
selectionActuelle = 2;
dessinerMenuComplet();
} else {
menuActuel = sousMenuUniteConso[selectionActuelle].id;
selectionActuelle = 0;
dessinerMenuComplet();
}
}
}
}
dernierEtatBouton = lectureBouton;
} else if (menuActuel == REGLAGE_HEURE_EN_COURS) {
if (tempsActuel - tempsDerniereNavigationJoystick > 200) {
int valY = analogRead(pinJoystickY);
int valX = analogRead(pinJoystickX);
if (valY < 200) {
if (champReglageHeure == 0) {
heureTemporaire = (heureTemporaire + 1) % 24;
} else if (champReglageHeure == 1) {
minuteTemporaire = (minuteTemporaire + 1) % 60;
} else if (champReglageHeure == 2) {
int maxJour = daysInMonth(moisTemporaire, anneeTemporaire);
jourTemporaire = (jourTemporaire >= maxJour) ? 1 : jourTemporaire + 1;
} else if (champReglageHeure == 3) {
moisTemporaire = (moisTemporaire >= 12) ? 1 : moisTemporaire + 1;
if (jourTemporaire > daysInMonth(moisTemporaire, anneeTemporaire)) {
jourTemporaire = daysInMonth(moisTemporaire, anneeTemporaire);
}
} else if (champReglageHeure == 4) {
anneeTemporaire++;
}
dessinerUnChampDeHeure(champReglageHeure, true);
tempsDerniereNavigationJoystick = tempsActuel;
} else if (valY > 800) {
if (champReglageHeure == 0) {
heureTemporaire = (heureTemporaire == 0) ? 23 : heureTemporaire - 1;
} else if (champReglageHeure == 1) {
minuteTemporaire = (minuteTemporaire == 0) ? 59 : minuteTemporaire - 1;
} else if (champReglageHeure == 2) {
int maxJour = daysInMonth(moisTemporaire, anneeTemporaire);
jourTemporaire = (jourTemporaire <= 1) ? maxJour : jourTemporaire - 1;
} else if (champReglageHeure == 3) {
moisTemporaire = (moisTemporaire == 1) ? 12 : moisTemporaire - 1;
if (jourTemporaire > daysInMonth(moisTemporaire, anneeTemporaire)) {
jourTemporaire = daysInMonth(moisTemporaire, anneeTemporaire);
}
} else if (champReglageHeure == 4) {
anneeTemporaire--;
}
dessinerUnChampDeHeure(champReglageHeure, true);
tempsDerniereNavigationJoystick = tempsActuel;
}
if (valX < 200) {
champPrecedentReglageHeure = champReglageHeure;
champReglageHeure = (champReglageHeure - 1 < 0) ? 6 : champReglageHeure - 1;
dessinerUnChampDeHeure(champPrecedentReglageHeure, false);
dessinerUnChampDeHeure(champReglageHeure, true);
tempsDerniereNavigationJoystick = tempsActuel;
} else if (valX > 800) {
champPrecedentReglageHeure = champReglageHeure;
champReglageHeure = (champReglageHeure + 1 > 6) ? 0 : champReglageHeure + 1;
dessinerUnChampDeHeure(champPrecedentReglageHeure, false);
dessinerUnChampDeHeure(champReglageHeure, true);
tempsDerniereNavigationJoystick = tempsActuel;
}
}
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
if (champReglageHeure == 5) {
sauvegarderHeureRTC();
} else if (champReglageHeure == 6) {
menuActuel = SOUS_MENU_PARAMETRES;
selectionActuelle = 0;
dessinerMenuComplet();
}
}
}
}
dernierEtatBouton = lectureBouton;
} else if (menuActuel == MODE_MANUEL_EN_COURS) {
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
pompeActive = !pompeActive;
digitalWrite(PIN_RELAIS_POMPE, pompeActive ? HIGH : LOW);
mettreAJourEtatPompe();
}
}
}
dernierEtatBouton = lectureBouton;
int valY = analogRead(pinJoystickY);
if (valY < 200) {
menuActuel = MENU_PRINCIPAL;
selectionActuelle = 0;
pompeActive = false;
digitalWrite(PIN_RELAIS_POMPE, LOW);
dessinerMenuComplet();
}
} else if (menuActuel == MODE_CYCLE_AUTOMATIQUE) {
int valY = analogRead(pinJoystickY);
int valX = analogRead(pinJoystickX);
if (tempsActuel - tempsDerniereNavigationJoystick > 200) {
if (valY < 200) {
if (champCycleAuto == 0) tempsON_min_temp = (tempsON_min_temp + 1) % 60;
else if (champCycleAuto == 1) tempsON_sec_temp = (tempsON_sec_temp + 1) % 60;
else if (champCycleAuto == 2) tempsOFF_min_temp = (tempsOFF_min_temp + 1) % 60;
else if (champCycleAuto == 3) tempsOFF_sec_temp = (tempsOFF_sec_temp + 1) % 60;
if (champCycleAuto <= 3) {
dessinerUnChampDeCycle(champCycleAuto, champCycleAuto == 0 ? tempsON_min_temp : (champCycleAuto == 1 ? tempsON_sec_temp : (champCycleAuto == 2 ? tempsOFF_min_temp : tempsOFF_sec_temp)));
}
tempsDerniereNavigationJoystick = tempsActuel;
} else if (valY > 800) {
if (champCycleAuto == 0) tempsON_min_temp = (tempsON_min_temp == 0) ? 59 : tempsON_min_temp - 1;
else if (champCycleAuto == 1) tempsON_sec_temp = (tempsON_sec_temp == 0) ? 59 : tempsON_sec_temp - 1;
else if (champCycleAuto == 2) tempsOFF_min_temp = (tempsOFF_min_temp == 0) ? 59 : tempsOFF_min_temp - 1;
else if (champCycleAuto == 3) tempsOFF_sec_temp = (tempsOFF_sec_temp == 0) ? 59 : tempsOFF_sec_temp - 1;
if (champCycleAuto <= 3) {
dessinerUnChampDeCycle(champCycleAuto, champCycleAuto == 0 ? tempsON_min_temp : (champCycleAuto == 1 ? tempsON_sec_temp : (champCycleAuto == 2 ? tempsOFF_min_temp : tempsOFF_sec_temp)));
}
tempsDerniereNavigationJoystick = tempsActuel;
}
if (valX < 200) {
champPrecedentCycleAuto = champCycleAuto;
champCycleAuto = (champCycleAuto - 1 < 0) ? 5 : champCycleAuto - 1;
dessinerSelection(champPrecedentCycleAuto, false);
dessinerSelection(champCycleAuto, true);
tempsDerniereNavigationJoystick = tempsActuel;
} else if (valX > 800) {
champPrecedentCycleAuto = champCycleAuto;
champCycleAuto = (champCycleAuto + 1 > 5) ? 0 : champCycleAuto + 1;
dessinerSelection(champPrecedentCycleAuto, false);
dessinerSelection(champCycleAuto, true);
tempsDerniereNavigationJoystick = tempsActuel;
}
}
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
if (champCycleAuto == 4) {
EEPROM.write(EEPROM_ADDR_TEMPS_ON_MIN, tempsON_min_temp);
EEPROM.write(EEPROM_ADDR_TEMPS_ON_SEC, tempsON_sec_temp);
EEPROM.write(EEPROM_ADDR_TEMPS_OFF_MIN, tempsOFF_min_temp);
EEPROM.write(EEPROM_ADDR_TEMPS_OFF_SEC, tempsOFF_sec_temp);
tempsON_min_sauvegarde = tempsON_min_temp;
tempsON_sec_sauvegarde = tempsON_sec_temp;
tempsOFF_min_sauvegarde = tempsOFF_min_temp;
tempsOFF_sec_sauvegarde = tempsOFF_sec_temp;
menuActuel = MENU_PRINCIPAL;
selectionActuelle = 0;
dessinerMenuComplet();
} else if (champCycleAuto == 5) {
menuActuel = MENU_PRINCIPAL;
selectionActuelle = 0;
dessinerMenuComplet();
}
}
}
}
dernierEtatBouton = lectureBouton;
} else if (menuActuel == REGLAGE_ETALONNAGE) {
if (tempsActuel - tempsDerniereNavigationJoystick > 200) {
int valY = analogRead(pinJoystickY);
int valX = analogRead(pinJoystickX);
if (valY < 200) {
if (champEtalonnage == 0) {
granulesTemporaire = (granulesTemporaire + 1) % 1000;
} else if (champEtalonnage == 1) {
decimalesTemporaire = (decimalesTemporaire + 1) % 10;
}
dessinerUnChampEtalonnage(champEtalonnage, true);
tempsDerniereNavigationJoystick = tempsActuel;
} else if (valY > 800) {
if (champEtalonnage == 0) {
granulesTemporaire = (granulesTemporaire == 0) ? 999 : granulesTemporaire - 1;
} else if (champEtalonnage == 1) {
decimalesTemporaire = (decimalesTemporaire == 0) ? 9 : decimalesTemporaire - 1;
}
dessinerUnChampEtalonnage(champEtalonnage, true);
tempsDerniereNavigationJoystick = tempsActuel;
}
if (valX < 200) {
champPrecedentEtalonnage = champEtalonnage;
champEtalonnage = (champEtalonnage - 1 < 0) ? 3 : champEtalonnage - 1;
dessinerUnChampEtalonnage(champPrecedentEtalonnage, false);
dessinerUnChampEtalonnage(champEtalonnage, true);
tempsDerniereNavigationJoystick = tempsActuel;
} else if (valX > 800) {
champPrecedentEtalonnage = champEtalonnage;
champEtalonnage = (champEtalonnage + 1 > 3) ? 0 : champEtalonnage + 1;
dessinerUnChampEtalonnage(champPrecedentEtalonnage, false);
dessinerUnChampEtalonnage(champEtalonnage, true);
tempsDerniereNavigationJoystick = tempsActuel;
}
}
int lectureBouton = digitalRead(pinJoystickBtn);
if (lectureBouton != dernierEtatBouton) {
dernierDebounceTime = millis();
}
if ((millis() - dernierDebounceTime) > delaiDebounce) {
if (lectureBouton != etatBoutonJoystick) {
etatBoutonJoystick = lectureBouton;
if (etatBoutonJoystick == LOW) {
if (champEtalonnage == 2) {
granulesParMinute = granulesTemporaire + (float)decimalesTemporaire / 10.0;
EEPROM_writeFloat(EEPROM_ADDR_GRANULES_PAR_MINUTE, granulesParMinute);
granulesParMinuteSauvegarde = granulesParMinute;
menuActuel = SOUS_MENU_PARAMETRES;
selectionActuelle = 3;
dessinerMenuComplet();
} else if (champEtalonnage == 3) {
menuActuel = SOUS_MENU_PARAMETRES;
selectionActuelle = 3;
dessinerMenuComplet();
}
}
}
}
dernierEtatBouton = lectureBouton;
}
if (millis() - derniereMiseAJourInfos >= intervalleMiseAJour) {
afficherInfos();
derniereMiseAJourInfos = millis();
}
}