#include <Wire.h>
/*** Module RTC DS1307 (Real Time Clock) *************/
#include <RTClib.h>
RTC_DS1307 rtc; // rtc = nom du module d'horloge en temps réel (rtc)
char Jour[7][10] = {"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"}; // Les jours de la semaine.
char Mois[13][10] = {"", "Janvier", "Fevrier", "Mars", "Avril", "Mai", "Juin",
"Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Decembre"
};
char Horloge[9], LaDate[20], ALARM[9];
DateTime now; // Variable de type DateTime nommée "now"
//DateTime, ajoute la capacité de chronométrage et donne accès aux heures, minutes, secondes, jours, mois et années.
/*** Afficheur lcd I2C2004 **************************/
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
/*** Les 2 DHT22 *************************************/
#include <DHT.h>
int dhtExtSignalPin = 13; // DHT extérieur
DHT capteurDHT_Ext(dhtExtSignalPin, DHT22); // Syntaxe: dhtExtSignalPin(pin, Type)
// Variable de type float "flottante" pour les DHT22.
float Hum, Cel, Far; // Variables à virgule flottante.
char tC[6], tF[6], H[6], buffer[20], buffer2[20]; // mémoires tampons (Buffers)
const int piezo = 12; // Broche du piezo
const int dhtPin = 13; // Broche de lecture du DHT22 extérieur
const int btnSelectSave = 4; // Bouton pin pour la navigation et la sauvegarde
const int btnSetting = 7; // Bouton pin pour modifier les valeurs
const int btnAlarmOnOff = 8; // Bouton pin pour activer et désactiver l'alarme
const int btnAlarmOff = 9; // Bouton pin pour taire l'alarme
bool AlarmOn = false; // Drapeau pour indiquer si l'alarme est activée
bool AlarmOff = false; // Indicateur pour indiquer si l'alarme a été déclenchée
int AlarmHeure = 0, alarmMinute = 0, AlarmSeconde = 0;
enum Etat {MAIN_MENU, SET_REMINDER, SET_ALARM, PRE_SET_REMINDER, PRE_SET_ALARM};
enum SubEtat {SET_ALARM_HEURE, SET_ALARM_MINUTE, SET_SAVING};
Etat currentEtat = MAIN_MENU;
SubEtat currentSubEtat = SET_ALARM_HEURE;
byte alarm[8] = { 0b00000, // Dessine une cloche.
0b00100,
0b01110,
0b01110,
0b01110,
0b11111,
0b00000,
0b00100
};
/*** Variables pour l'encodeur rotatif KY-040 ******/
int encodeur_CLK = 2, encodeur_DaTa = 3, encodeur_SWitch = 4;
int compteur = 0, dataValue, resultat, E_Clk, i ;
int currentValue, previousValue;
byte swPreviousEtat = false, buttonEtat;
void setup() {
rtc.begin(); capteurDHT_Ext.begin();
lcd.init(); lcd.backlight();
lcd.createChar(0, alarm);
capteurDHT_Ext.begin();
pinMode(dhtExtSignalPin, INPUT_PULLUP);
pinMode(btnSelectSave, INPUT_PULLUP);
pinMode(btnSetting, INPUT_PULLUP);
pinMode(btnAlarmOnOff, INPUT_PULLUP);
pinMode(btnAlarmOff, INPUT_PULLUP);
pinMode(piezo, OUTPUT);
attachInterrupt(digitalPinToInterrupt(encodeur_CLK), LireEncodeur, FALLING);
}
void LireEncodeur() { // ISR (Routine de Service d'Interruption)
dataValue = digitalRead(encodeur_DaTa);
if (dataValue == HIGH) {
compteur++; // Dans le sens horaire incrémente de 1
if (compteur > 9)compteur = 9;
}
if (dataValue == LOW) {
compteur--; // Sens antihoraire décrémente de 1
if (compteur < 0)compteur = 0;
}
tick();
}
int getCompteur() {
/* Obtenir la valeur du compteur, en désactivant les interruptions.
Cela garantit que LireEncodeur() ne modifie pas la valeur
pendant qu'elle est lue.
*/
resultat;
noInterrupts(); // pas d'interruptions
resultat = compteur;
interrupts(); // Interruptions
return resultat;
}
void loop() {
DateTime now = rtc.now();
switch (currentEtat) {
case MAIN_MENU:
displayMainMenu(now);
break;
case SET_ALARM:
switch (currentSubEtat) {
case SET_ALARM_HEURE:
setAlarmHeure(now);
break;
case SET_ALARM_MINUTE:
setAlarmMinute(now);
break;
case SET_SAVING:
setSaving();
break;
}
break;
case PRE_SET_ALARM:
menu();
break;
/*case SET_REMINDER:
lcd.setCursor(0, 0);
lcd.print("TEST");
break;*/
/*case PRE_SET_REMINDER:
menu();
break;*/
}
checkButtons();
if (AlarmOn) {
if (AlarmHeure == now.hour() && alarmMinute == now.minute() && AlarmSeconde == now.second()) {
AlarmOff = true; // Définir l'indicateur de déclenchement d'alarme
}
}
if (AlarmOff) {
Alarm();
} else {
noTone(piezo);
}
// Vérifiez si btnAlarmOnOff est enfoncé pour arrêter l'alarme
if (digitalRead(btnAlarmOnOff) == LOW && AlarmOff) {
AlarmOff = false; // Réinitialiser l'indicateur de déclenchement de l'alarme
}
Hum = capteurDHT_Ext.readHumidity(); // Pourcentage de l'humidité.
Cel = capteurDHT_Ext.readTemperature(); // Température en degré Celcius
delay(100); // Mise à jour toutes les 100 millisecondes
}
void menu() {
if (currentEtat == PRE_SET_ALARM) {
if (digitalRead(btnSetting) == LOW) {
currentEtat = SET_ALARM;
}
lcdPrintCenter("SET ALARM", 0);
}
}
void displayMainMenu(DateTime now) {
// Imprimer la date sur l'écran LCD
sprintf(LaDate,
"%8s %02d:%02d:%4d",
Jour[now.dayOfTheWeek()],
now.day(),
now.month(),
now.year());
lcd.setCursor(0, 1); lcd.print(LaDate);
// Imprimer l'heure sur l'écran LCD
sprintf(Horloge,
"%02d:%02d:%02d / %02d:%02d", // formattage
now.hour(), // heures
now.minute(), // minutes
now.second(), // secondes
AlarmHeure, // alarme heure
alarmMinute); // alarme minute
lcd.setCursor(0, 0); lcd.print(Horloge);
dtostrf(Cel, 5, 2, tC); // Converti float"Cel" en Chaine de caractères.
// pour afficher la température en degré Celcius
lcd.setCursor(0, 2); lcd.print("Temp: ");
lcd.print(String(tC) + (char)223 + "C ");
dtostrf(Hum, 5, 1, H); // Converti float"Far" en Chaine de caractères.
lcd.setCursor(0, 3); lcd.print("Humidity:" + String(H) + "% ");
/*
lcd.setCursor(12, 1);
printDigits(Cel);
lcd.setCursor(15, 1);
lcd.print("C");
*/
// Display alarm status
if (AlarmOn) {
lcd.setCursor(19, 0);
lcd.write(byte(0)); // Alarm icon
} else {
lcd.setCursor(19, 0);
lcd.print(" ");
}
}
void printDigits(int digits) {
// Ajouter un zéro non significatif si les chiffres sont < 10
if (digits < 10) {
lcd.print('0');
}
lcd.print(digits);
}
void printYear(int year) {
// Extract last two digits of the year
year = year % 100;
printDigits(year);
}
void setAlarmHeure(DateTime now) {
int AlarmHeureTemp = now.hour();
int alarmMinTemp = now.minute();
lcd.setCursor(0, 0);
lcd.print("SET ALARM TIME");
lcd.setCursor(4, 1);
lcd.print(">");
lcd.setCursor(8, 1);
lcd.print(':');
lcd.setCursor(10, 1);
printDigits(alarmMinTemp);
while (digitalRead(btnSelectSave) == HIGH) {
lcd.setCursor(5, 1);
printDigits(AlarmHeureTemp);
if (digitalRead(btnSetting) == LOW) {
AlarmHeureTemp = (AlarmHeureTemp + 1) % 24;
delay(300); // Button debounce
}
if (digitalRead(btnSelectSave) == LOW) {
AlarmHeure = AlarmHeureTemp;
alarmMinute = alarmMinTemp;
currentSubEtat = SET_ALARM_MINUTE;
break;
}
}
}
void setAlarmMinute(DateTime now) {
int alarmMinTemp = alarmMinute;
lcd.setCursor(0, 0);
lcd.print("SET ALARM TIME");
lcd.setCursor(4, 1);
lcd.print(" ");
lcd.setCursor(9, 1);
lcd.print(">");
lcd.setCursor(5, 1);
printDigits(AlarmHeure);
lcd.setCursor(8, 1);
lcd.print(':');
while (digitalRead(btnSelectSave) == HIGH) {
lcd.setCursor(10, 1);
printDigits(alarmMinTemp);
if (digitalRead(btnSetting) == LOW) {
alarmMinTemp = (alarmMinTemp + 1) % 60;
delay(300); // Button debounce
}
if (digitalRead(btnSelectSave) == LOW) {
alarmMinute = alarmMinTemp;
lcd.clear();
currentSubEtat = SET_SAVING;
break;
}
}
}
void setSaving() {
lcdPrintCenter("Saving !", 1);
delay(1000);
lcd.clear();
currentSubEtat = SET_ALARM_HEURE;
currentEtat = MAIN_MENU;
if (AlarmOn == false) {
AlarmOn = !AlarmOn;
}
}
void checkButtons() {
if (digitalRead(btnSelectSave) == LOW) {
switch (currentEtat) {
case MAIN_MENU:
lcd.clear();
currentEtat = PRE_SET_ALARM;
break;
case PRE_SET_ALARM:
currentEtat = PRE_SET_REMINDER;
break;
case PRE_SET_REMINDER:
lcd.clear();
currentEtat = MAIN_MENU;
break;
}
delay(100); // Button debounce
}
if (digitalRead(btnAlarmOnOff) == LOW && currentEtat == MAIN_MENU) {
// Enable or disable alarm
AlarmOn = !AlarmOn;
delay(100); // Button debounce
}
}
// Fonction d'Alarme
void Alarm() {
// Répète les 2 tonalitéd 10 fois chaque avant de se taire
lcdPrintCenter(" ",3); // efface la 4e ligne.
lcdPrintCenter("Press Alarm Off", 3); // Affiche instruction
for (int repeat = 0; repeat <= 10; ++repeat) {
// désactive l'alarme si bouton 3 pressé.
if (digitalRead(btnAlarmOff) == LOW && AlarmOff) {
AlarmOff = false; // Réinitialiser l'indicateur de déclenchement de l'alarme
goto ExitAlarm; // Oblige la sortie de de la fonction alarm
}
lcdPrintCenter("Press Alarm Off", 3); // Affiche instruction
// Émet une tonalité de 800Hz pendant 300 ms,
// suivi d'une interruption de 200ms
tone(piezo, 800, 300); delay(200);
// Émet une tonalité de 500Hz pendant 300 ms,
// suivi d'une interruption de 200ms
tone(piezo, 500, 300); delay(200);
// Fait clignoter le rétroéclairage de l'afficheur lcd
// par interval de 100ms.
for (int flash = 0; flash <= 10; ++flash) {
// Désactive le rétroéclairage de lcd3
lcd.noBacklight();
}
delay(100); // Vitesse du clignotement
lcd.backlight(); // Rétabli le rétroéclairage de l'afficheur.
}
ExitAlarm: lcd.clear();
}
// Émet une très brève tonalité de 5kHz pendant 4 ms
void tick() {
tone(piezo, 5000, 4); // Émet un son de 5 kHz pendant 1 ms
}
// fonction pour centrer le texte à afficher sur lcd.============
void lcdPrintCenter(String text, int ligne) {
int len = text.length();// longeur de la variable text
// positionne le curseur au centre de la ligne choisie et
// soustrait la longeur du text à afficher
lcd.setCursor((20 - len) / 2, ligne);
lcd.print(text); // affiche le text centré
}
Select
Save
Setting
Alarm
On/Off
Piezo
DHT22
RTC
DS1307
Alarm Off