/****************************************************************************************************************************************
Projet Chronomètre et minuteur cyclique avec LCD 20X4 réalisé par: Daniel Talbot Technicien
Pour Ez-Weekend-Project au Club Technique des Laurentides
Dans le cadre du programme C.I.P.A.D. (Cours d'initiation à la Programmation Arduino pour Débutant(e)s) gratuit et sans inscription.
Copiez ce lien pour accéder à la vidéo concernant ce projet
https://???
ou celui-ci pour accéder à toutes les leçons déjà publiées...
https://www.youtube.com/playlist?list=PLoffRtP427acSg1FbpFuH_g5ptz-aovFN
* *
****************************************************************************************************************************************/
#include <LiquidCrystal_I2C.h>
// Déclare l'adresse I2C du LCD à 0x27, 30 colones, 4 lignes.
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Assignation des broches IN/OUT
int ledRouge = 9; // Assigne la broche 9 à la led rouge
int buzzer = 13; // Assigne la broche 13 au piezo.
int SSR_relais = 10; bool etat_SSRrelais = LOW;
int btn_StartStop = 2; bool EtatBtn_StartStop;
int btn_Set_TimeON = 3; bool EtatBtn_Set_TimeON;
int btn_Set_TimeOFF = 4; bool EtatBtn_Set_TimeOFF;
int btn_RecordSet = 5; bool EtatBtn_RecordSet;
int Record, Start;
// Buffers: Variables de type Char.
char tempsON[20], tempsOFF[20];
char Chrono[20], MinuteurON[20], MinuteurOFF[20];
// Contrôle: de type Bool
bool FlagON = false, etatBtnPresser, EtatChronoOnOFF;
bool etatRecord = false;
// Variable de temps:
//long Min = 60000, Sec = 1000;
long onTime, offTime;
long MyTimeON, H_ON = 0, M_ON = 0, S_ON = 0, MS_ON = 0;
long MyTimeOFF, H_OFF = 0, M_OFF = 0, S_OFF = 0, MS_OFF = 0;
//long minutes_OFF = 0, minutes_ON = 0;
long secondes_OFF = 0, secondes_ON = 0;
long Milliseconde, Seconde, Minute, Heure, TempsEcoule;
unsigned long currentTime = 0, previousTime = 0;
unsigned long startMillis, currentMillis;
//unsigned long period = 5000;
void setup() {
// initialise lcd I2C 2004 & active le rétro éclairage
lcd.init(); lcd.backlight();
// Assigne le mode INPUT_PULLUP aux 5 boutons poussoirs.
for (int pin = 2; pin <= 5; pin++)pinMode(pin, INPUT_PULLUP);
/*
pinMode(btn_StartStop, INPUT_PULLUP);
pinMode(btn_Reset, INPUT_PULLUP);
pinMode(btn_RecordSet, INPUT_PULLUP);
pinMode(btn_Set_TimeON, INPUT_PULLUP);
pinMode(btn_Set_TimeOFF, INPUT_PULLUP);
*/
// Assigne le mode OUTPUT aux 3 broche de sortie.
pinMode(ledRouge, OUTPUT);
pinMode(SSR_relais, OUTPUT);
pinMode(buzzer, OUTPUT);
digitalWrite(SSR_relais, LOW); // État du relais au démarrage = Off.
//Affichage au démarrage
lcd.setCursor(0, 0); lcd.print(" Chronometre: "); // titre
}
void loop() {
fn_boutons(); // Appel la fonctions boutons.
fn_Chrono();
fn_display(); // Appel la Fonction d'affichage sur lcd.
}
void fn_boutons() { // Regroupe les Fonctions des boutons poussoirs.
// Lit la broche d'entrée du btn_StartStop et stock
// sa valeur dans EtatBtn_xxx.
EtatBtn_StartStop = digitalRead(btn_StartStop);
EtatBtn_RecordSet = digitalRead(btn_RecordSet);
EtatBtn_Set_TimeON = digitalRead(btn_Set_TimeON);
EtatBtn_Set_TimeOFF = digitalRead(btn_Set_TimeOFF);
digitalWrite(ledRouge, EtatChronoOnOFF); // Indique que le chrono est en marche
if (!EtatBtn_Set_TimeON) { // Réglage du temps ON
secondes_ON = secondes_ON + 1; // Incrémente de 1 à chaque pression du bouton bleu.
if (secondes_ON > 59) { // si dépassement de 59, remet à 0.
secondes_ON = 0;
} tick();
S_ON = secondes_ON; fn_display();
delay(60); // Délais de 60 ms entre chaque pression du bouton
// Empêche les rebonds des boutons poussoirs
while (EtatBtn_Set_TimeON) EtatBtn_Set_TimeON = digitalRead(btn_Set_TimeON);
}
if (!EtatBtn_Set_TimeOFF) { // Réglage du temps OFF
secondes_OFF = secondes_OFF + 1; //Incrémente de 1 à chaque pression du bouton jaune.
if (secondes_OFF > 59) { // si dépassement de 59, remet à 0.
secondes_OFF = 0;
} tick();
S_OFF = secondes_OFF;
fn_display(); // Rafraîchi l'affichage.
delay(60); // Délais de 60 ms entre chaque pression du bouton
while (EtatBtn_Set_TimeOFF) // anti rebond
EtatBtn_Set_TimeOFF = digitalRead(btn_Set_TimeOFF);
}
// Enregitrement des temps ON/OFF du minuteur
if (!EtatBtn_RecordSet) {
beep(); delay(250);
Record = Record + 1; // Nombre de fois que le bouton gris est pressé.
if (Record == 1) { // S'il est égale à 1, exécute les instructions entre ses accolades.
lcd.setCursor(17, 2); lcd.print("SET");// Set indique que la valeur du temps ON est stocké.
onTime = secondes_ON; MyTimeON = onTime; S_ON = MyTimeON; // Enregistre les variables.
fn_display(); // Rafraîchi l'affichage.
}
if (Record == 2) { // S'il est égale à 2, exécute les instructions entre ses accolades.
lcd.setCursor(17, 3); lcd.print("SET"); // Set indique que la valeur du temps OFF est stocké.
offTime = secondes_OFF; MyTimeOFF = offTime; S_OFF = MyTimeOFF; // Enregistre les variables.
fn_display(); // Rafraîchi l'affichage.
etatRecord = true; // Confirme que les valeurs sélectionnées on été engeristrées.
delay(1000); // Délais de 1 secondes avant d'afficher les messages qui suivent...
lcd.setCursor(14, 2); lcd.print("Ready!"); // Ready! indique que le minuteur ON est programmé et prêt à être lancé.
lcd.setCursor(14, 3); lcd.print("Ready!"); // Ready! indique que le minuteur OFF est programmé et prêt à être lancé.
tone(buzzer, 400, 250); delay(250); tone(buzzer, 600, 250);
delay(2000);// Délais de 1 secondes avant d'afficher les messages qui suivent..
lcd.setCursor(14, 2); lcd.print("Relais");
lcd.setCursor(14, 3); lcd.print(" OFF "); // État actuel du relais. Prêt à être lancé avec le chronomètre (bouton rouge Start/Stop).
}
delay(60); // Délais de 60 ms entre chaque pression du bouton
// Empêche les rebonds des boutons poussoirs
while (EtatBtn_RecordSet)
EtatBtn_RecordSet = digitalRead(btn_RecordSet);
}
// Si EtatBtnStartStop == LOW et etatBtnPresser == 0 on exécute les actions entre {}
if (EtatBtn_StartStop == LOW && etatBtnPresser == 0) {
// La variable etatBtnPresser prend la valeur de 1.
etatBtnPresser = HIGH;
// Inverse l'EtatEtatChronoOnOFF ON ou OFF
EtatChronoOnOFF = !EtatChronoOnOFF;
beep();
if ((onTime > 0) && (offTime > 0)) {
digitalWrite(SSR_relais, EtatChronoOnOFF);
}
}
// Si EtatBtnStartStop == HIGH et etatBtnPresser == HIGH
// on exécute les actions entre {}
if (EtatBtn_StartStop == HIGH && etatBtnPresser == HIGH) {
// La variable etatBtnPresser prend la valeur de 0.
etatBtnPresser = !etatBtnPresser; // inversion etatBtnPresser
}
}
void fn_Chrono() {
// On stocke la valeur du timer interne du microcontrôleur récupéré grâce
// à millis() dans la variable currentTime
currentTime = millis();
// On calcule la valeur de TempsEcoule en effectuant une
// soustraction entre currentTime et previousTime.
TempsEcoule = currentTime - previousTime;
// On stocke la valeur du timer interne du microcontrôleur récupéré
// grace à millis() dans la variable previousTime
previousTime = millis();
if (EtatChronoOnOFF == 1) { // Si EtatChronoOnOFF = HIGH...
Milliseconde = Milliseconde + TempsEcoule;
if (Milliseconde > 999) { // Compteur des secondes
Milliseconde = Milliseconde - 1000;
fn_compteur_A_Rebour();
Seconde++; // Incrémente de 1 à chaque 1000ms.
}
if (Seconde > 59) { // Compteur des minutes
Seconde = 0; Minute++; // incrémente de 1 minute toutes les 60 secondes
}
if (Minute > 59) { // Compteur des heures
Minute = 0; Heure++; // incrémente de 1 heure toutes les 60 minutes
}
}
//fn_display(); // Appel la Fonction d'affichage sur lcd.
}
void fn_display() { // Fonction d'affichage sur lcd.
// sprintf: Formate l'affichage pour les buffer.
sprintf(MinuteurON, "T-ON: %02ld sec", S_ON);
sprintf(MinuteurOFF, "T-OFF: %02ld sec", S_OFF); //Formate l'affichage.
sprintf(Chrono, "%02ld:%02ld:%02ld:%03ld", Heure, Minute, Seconde, Milliseconde);//Formate l'affichage.
lcd.setCursor(4, 1); lcd.print(Chrono); //Affiche le chronomètre sur la 2e ligne du lcd.
lcd.setCursor(0, 2); lcd.print(MinuteurON); // Afffiche le minuteur ON sur la 3e ligne du lcd.
lcd.setCursor(0, 3); lcd.print(MinuteurOFF);// Afffiche le minuteur OFF sur la 4e ligne du lcd.
}
void fn_compteur_A_Rebour() { // Compte à rebour Temps On et OFF.
if (MyTimeON > 0) { // Si MyTimeON = 1... ou programmé.
MyTimeON--; // décrémentation de 1 seconde le temps ON
S_ON = MyTimeON ; // Stock la valeur du temps ON pour l'afficheur.
FlagON = true; // FlagON passe à Vrai
etat_SSRrelais = FlagON; // active le relais
digitalWrite(SSR_relais, etat_SSRrelais); // Contrôle les relais externes
// Affiche lorsque le relais est ON
lcd.setCursor(14, 3); lcd.print("Relais");
lcd.setCursor(14, 2); lcd.print(" ON ");
}
if ((MyTimeOFF > 0) && (MyTimeON == 0)) {
MyTimeOFF--; // décrémentation de 1 seconde le temps OFF
S_OFF = MyTimeOFF;// Stock la valeur du temps OFF pour l'afficheur.
FlagON = false ; // FlagON passe à faux
etat_SSRrelais = FlagON; //désactive les relais
digitalWrite(SSR_relais, FlagON); // Mettre à jour le relais selon la valeur de FlagOn (On/OFF ou 1/0 ou true/false)
// Affiche si le relais est OFF
lcd.setCursor(14, 2); lcd.print("Relais");
lcd.setCursor(14, 3); lcd.print(" OFF ");
if ((MyTimeOFF == 0) && (MyTimeON == 0)) {
MyTimeON = onTime; // Stock la valeur du temps ON.
MyTimeOFF = offTime; // Stock la valeur du temps OFF.
}
}
}
// Fonctions du buzzer ==========================================
// fonction beep pour Émettre une tonalité de x kHz pendant x ms
void beep() {// Émet une tonalité de 2,5kHz pendant 100 ms
tone(buzzer, 2500, 100);
}
// Émet une très brève tonalité de 5kHz pendant 4 ms
void tick() {
tone(buzzer, 5000, 4); // Émet un son de 5 kHz pendant 1 ms
}