#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Servo.h>
#include <EEPROM.h>
// Initialisation des objets
LiquidCrystal_I2C lcd(0x27, 20, 4); // Adresse I2C du LCD
RTC_DS1307 rtc; // Horloge temps réel
Servo servo;
// Définition des broches
const int potPin = A0; // Potentiomètre
const int btnMenuPin = 2; // Bouton de navigation
const int btnEditPin = 3; // Bouton d'édition
const int btnManualPin = 4; // Nouveau bouton pour ouverture manuelle du servo
// Variables globales
int menuIndex = 0; // Index du menu actuel
bool editing = false; // Indicateur du mode d'édition
bool selectHour = true; // Sélection de l'heure (true) ou des minutes (false)
int openHour, openMinute, openDuration; // Paramètres personnalisables
bool lastMenuState = HIGH; // Dernier état du bouton de navigation
bool lastEditState = HIGH; // Dernier état du bouton d'édition
bool lastManualState = HIGH; // Dernier état du bouton manuel
unsigned long lastBlinkTime = 0;
bool blinkState = true; // État du clignotement
bool manualOpening = false; // Indique si le servo est ouvert manuellement
// Variables pour éviter les mises à jour inutiles de l'écran
String lastLine[4]; // État précédent de chaque ligne de l'écran
void setup() {
// Initialisation des périphériques
lcd.init();
lcd.backlight();
rtc.begin();
servo.attach(9);
// Configuration des boutons
pinMode(btnMenuPin, INPUT_PULLUP);
pinMode(btnEditPin, INPUT_PULLUP);
pinMode(btnManualPin, INPUT_PULLUP); // Nouveau bouton
// Lecture des paramètres depuis l'EEPROM
openHour = EEPROM.read(0);
openMinute = EEPROM.read(1);
openDuration = EEPROM.read(2);
// Vérification du RTC
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Mise à jour avec l'heure de compilation
}
// Initialisation de l'état précédent des lignes LCD
for (int i = 0; i < 4; i++) {
lastLine[i] = "";
}
}
void loop() {
// Lecture des boutons
bool menuState = digitalRead(btnMenuPin);
bool editState = digitalRead(btnEditPin);
bool manualState = digitalRead(btnManualPin);
// Navigation entre les menus
if (menuState == LOW && lastMenuState == HIGH) {
menuIndex = (menuIndex + 1) % 3; // Passer au menu suivant
editing = false; // Désactiver le mode édition au changement de menu
selectHour = true; // Réinitialiser la sélection
}
lastMenuState = menuState;
// Activation/désactivation du mode édition
if (editState == LOW && lastEditState == HIGH) {
if (editing) {
if (menuIndex == 1 && !selectHour) { // Si on termine l'édition des minutes
editing = false;
saveParameters();
} else if (menuIndex == 2) { // Si on termine la modification de la durée
editing = false;
saveParameters();
}
selectHour = !selectHour; // Basculer entre heure et minute dans le menu 1
} else {
editing = true; // Activer l'édition
}
}
lastEditState = editState;
// Modification des paramètres via le potentiomètre en mode édition
int potValue = analogRead(potPin);
if (editing) {
if (menuIndex == 1) { // Menu de réglage de l'heure d'ouverture
if (selectHour) {
openHour = map(potValue, 0, 1023, 0, 23); // Réglage des heures
} else {
openMinute = map(potValue, 0, 1023, 0, 59); // Réglage des minutes
}
} else if (menuIndex == 2) { // Menu de réglage de la durée
openDuration = map(potValue, 0, 1023, 0, 20); // Durée entre 0 et 20 secondes
}
}
// Gestion du clignotement
if (editing && millis() - lastBlinkTime > 500) {
blinkState = !blinkState;
lastBlinkTime = millis();
}
// Vérification du bouton manuel pour ouvrir le servo
if (manualState == LOW && lastManualState == HIGH) {
manualOpenServo(); // Fonction pour ouvrir manuellement le servo
}
lastManualState = manualState;
// Affichage sur l'écran LCD
if (menuIndex == 0) {
displayLine(0, "Heure Actuelle:");
displayCurrentTime();
} else if (menuIndex == 1) {
displayLine(0, "Heure Ouverture:");
displayOpeningTime();
} else if (menuIndex == 2) {
displayLine(0, "Duree Ouverture:");
displayOpeningDuration();
}
// Contrôle automatique du servo moteur
DateTime now = rtc.now();
if (now.hour() == openHour && now.minute() == openMinute && now.second() == 0 && !editing && !manualOpening) {
openServo();
}
delay(100); // Pause pour éviter une mise à jour trop rapide
}
// Affiche l'heure actuelle sur l'écran LCD
void displayCurrentTime() {
DateTime now = rtc.now();
String line = String(now.hour() < 10 ? "0" : "") + now.hour() + ":" +
(now.minute() < 10 ? "0" : "") + now.minute() + ":" +
(now.second() < 10 ? "0" : "") + now.second();
displayLine(1, line);
}
// Affiche l'heure d'ouverture
void displayOpeningTime() {
String hour = (editing && selectHour && !blinkState) ? " " : (String(openHour < 10 ? "0" : "") + openHour);
String minute = (editing && !selectHour && !blinkState) ? " " : (String(openMinute < 10 ? "0" : "") + openMinute);
displayLine(1, hour + ":" + minute);
}
// Affiche la durée d'ouverture
void displayOpeningDuration() {
String duration = (editing && !blinkState) ? " " : String(openDuration) + " sec";
displayLine(1, duration);
}
// Affiche une ligne uniquement si elle est différente de la précédente
void displayLine(int line, String content) {
if (content != lastLine[line]) {
lcd.setCursor(0, line);
lcd.print(content + " "); // Efface le reste de la ligne
lastLine[line] = content;
}
}
// Sauvegarde des paramètres dans l'EEPROM
void saveParameters() {
EEPROM.write(0, openHour);
EEPROM.write(1, openMinute);
EEPROM.write(2, openDuration);
}
// Ouvre le servo automatiquement ou manuellement
void openServo() {
manualOpening = true;
servo.write(90); // Ouvrir le servo
delay(openDuration * 1000);
servo.write(0); // Fermer le servo
manualOpening = false;
}
// Ouvre le servo manuellement
void manualOpenServo() {
openServo();
}