/****************************************************************************************************************************************
* 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 *
* lien à venir *
* 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> // Bibliothèque pour l'écran LCD fonctionnant avec I2C.
LiquidCrystal_I2C lcd(0x27, 20, 4); // Définitions des paramètres de lcd 2004 à l'adresse 0x27.
// Déclaration des entrées/sorties de l'Arduino Uno R3.
const int btn_StartStop = 2; // START/STOP, BP activé à l'état bas
const int btn_Reset = 3; // RESET, BP activé à l'état bas
const int btn_Mute = 4; // Mute , BP activé à l'état bas
const int buzzerPin = 13; // Buzzer relié à la broche 13
// Déclaration des variables de type booléenne
bool etat_btn_StartStop, etat_btn_Reset, etat_BoutonAppuyer; // Variable qu'on passe à 1 après avoir presser un bouton afin d'éviter l'effet rebond
bool etat_ChronoOnOFF, etat_btn_Mute, etat_Mute; // Variable qui détermine l'état de marche du chronomètre et la fonction Mute.
long TempsEcoule, Milliseconde, Seconde, Minute, Heure, Jour; // Variable de temps.
unsigned long currentTime = 0; // Variable utilisée pour récupérer la valeur de millis()
unsigned long previousTime = 0; // Variable utilisée pour stocker la valeur de millis() pour le prochain "loop"
// Variable de type char. Réserve en mémoire tampon 20 espaces de caractères pour chaque variable. Permet de créer des chaine de caratères.
char tempsON[20], tempsOFF[20];
char Chrono[20], MinuteurON[20], MinuteurOFF[20], Ref[20], Btn[20];
// Création de tableaux contenant plusieurs chaines de caractères prédéfinis et accessible par le nom du tableau et le No. d'index
// char* nom_du_tableau[index] = {"index 0" , index 1", "index 2", "ect...""};
char* Label[20] = {"Stop |Reset |",
"Start|Reset |"
};
char* selectMenu[] = {"Chronometre", "Minuteur", "Minuteur Cyclique",
"Chrono & Minuteur", "Test Alarm !", "press again"
};
//Liste des entêtes.
char* header[7] = {"Menu principal Fn", "ALARM TESTING!", "CHRONOMETRE:",
"MINUTEUR", "MINUTEUR CYCLIQUE", "CHRONO & MINUTEUR",
"jour:hh:mm:ss:millis"
};
// Liste des instructions.
char* instructions[6] = {" ", "For select function",
"Press Yellow button", "For this function",
"Press red button", "Or Yellow button"
};
// Variables pour la fonction "printCenter()"
int wide = 20; // nombre de caractères: 20 pour un afficheur de 20 caractères par ligne et 16 pour un afficheur de 16 caractères par ligne
int ligne = 0 ; // Numéro de la ligne de l'afficheur: 0 à 3 pour un afficheur à 4 ligne.
String text = ""; // Chaine de caractère nommée "text" à afficher.
int len = text.length(); // Longeur de la chaine de caratères "text".
int Mute = 0; //Variable antirebond utilisée dans la fonction Mute
void setup()
{
pinMode(btn_StartStop, INPUT_PULLUP); // Activation du mode ENTREE et résistance PULL UP
pinMode(btn_Reset, INPUT_PULLUP); // Activation du mode ENTREE et résistance PULL UP
pinMode(btn_Mute, INPUT_PULLUP); // Activation du mode ENTREE et résistance PULL UP
pinMode(buzzerPin, OUTPUT); // Activation du mode SORTIE.
lcd.init(); lcd.backlight(); // Initialisation de l'écran LCD, et active le rétroéclairage de l'écran LCD
printCenter(selectMenu[0], 0); // écran de démarrage
delay(1000); // pause de 1 seconde
beep(); // Beep
Fn_Display(); // fonction de l'Affichage principal
//Alarm();
}
// fonction perso beep pour Émettre une tonalité de x kHz pendant x ms
void beep() { // Émet une tonalité de 2,5kHz pendant 100 ms
tone(buzzerPin, 2500, 100); // Plays 2,5kHz tone for 100ms
}
void tick() { // fonction perso beep pour Émettre une très brèvetonalité de 3kHz pendant 5 ms
if (!etat_Mute) { // si la fonction Mute est false
tone(buzzerPin, 5000, 5); // Plays 5kHz tone for 5ms
}
}
void Alarm() { // Fonction d'Alarme ou réveil matin
lcd.clear(); printCenter(header[1], 0); // Affiche l'état de l'alarme
for (int repeat = 0; repeat <= 10; ++repeat) { // répète les 2 tonalitéd 10 fois chaque avant de se taire
tone(buzzerPin, 800, 300); delay(200); // Émet une tonalité de 800Hz pendant 300 ms, suivi d'une interruption de 200ms
tone(buzzerPin, 500, 300); delay(200); // Émet une tonalité de 500Hz pendant 300 ms, suivi d'une interruption de 200ms
for (int flash = 0; flash <= 10; ++flash) { // Fait clignoter le rétroéclairage de l'afficheur lcd par interval de 100ms.
lcd.noBacklight();
}
delay(100);
lcd.backlight(); // rétabli le rétroéclairage de l'afficheur lcd.
}
}
// fonction perso pour centrer le texte à afficher.
void printCenter(String text, int ligne) {
len = text.length(); // défini la longeur de la variable text
lcd.setCursor((wide - len) / 2, ligne); // positionne le curseur au centre de la ligne choisie et soustrait la longeur du text à afficher
lcd.print(text); // affiche le text centré
}
void loop() {
Fn_Scan_Buttons(); // Fonction de balayage de l'état de tous les boutons poussoirs
Fn_Chronometre(); // Fonction de gestion du temps qui passe lorsque le chrono est à ON
}
void Fn_Scan_Buttons() { //balayage de l'état de tous les boutons poussoirs
etat_btn_StartStop = digitalRead(btn_StartStop); // État Bouton Start/Stop
etat_btn_Reset = digitalRead(btn_Reset); // État Bouton Start/Stop
etat_btn_Mute = digitalRead(btn_Mute); // État Bouton Mute
if (etat_btn_Mute == LOW && Mute == 0 ) { // Contrôle le mute des tick()
beep(); etat_Mute = !etat_Mute; // Inverse l'état Mute (ON/OFF)
delay(500); while (etat_btn_Mute)etat_btn_Mute = digitalRead(btn_Mute); // fonction anti rebond
}
if (etat_btn_StartStop == LOW && etat_BoutonAppuyer == 0) { // Test pression bouton START/STOP
etat_BoutonAppuyer = 1; beep(); // Evite l'effet rebond
etat_ChronoOnOFF = !etat_ChronoOnOFF; // Inverse l'état du chronomètre
}
if (etat_btn_Reset == LOW && etat_ChronoOnOFF == 0 && etat_BoutonAppuyer == 0) { // Test pression bouton RESET
etat_BoutonAppuyer = 1; beep(); // Evite l'effet rebond
Milliseconde = 0; Seconde = 0; Minute = 0; Heure = 0; // Remet toutes les variables de temps à 0.
lcd.clear(); // Efface complétement le contenu de l'écran LCD
}
}
void Fn_Chronometre() // Fonction pricipale de la gestion de l'horloge du chrono
{
// Incrémentation du compteur de chrono en utilisant la fonction millis()
currentTime = millis(); // Le temps courant = l'horloge interne en ms.
TempsEcoule = currentTime - previousTime; // Le temps écoulée = au temps courant - le temps précédant
previousTime = millis(); // nouveau temps précédant = l'horloge interne en ms.
// Fonction compteur d'incrémentation des variables Milliseconde, Seconde, Minute, Heure et jour
if (etat_ChronoOnOFF == 1) { // Si Etat_ChronoOnOff = true exécute le code entre {}.
Milliseconde = Milliseconde + TempsEcoule; // Incrémentation des millisecondes
if (Milliseconde > 999) { // Si Milliseconde est supérieure à 999... (1000ms)
Milliseconde = Milliseconde - 1000; // ...Remise à 0 de la variable Milliseconde
tick(); // Si Mute est OFF un tick par seconde se fait entendre
Seconde++; // Incrémentation de 1 seconde toutes les 1000 Millisecondes
}
if (Seconde > 59) { // Si Seconde est supérieure à 59... (60sec)
Seconde = 0; // ...Remise à 0 de la variable Seconde
beep(); // un beep par minute se fait entendre
Minute++; // Incrémentation de 1 Minute toutes les 60 Secondes
}
if (Minute > 59) { // Si Minute est supérieure à 59... (60 minutes)
Minute = 0; // ...Remise à 0 de la variable Minute
Heure++; // Incrémentation de 1 Heure toutes les 60 Minutes
}
if (Heure > 23) { // Si Heure est supérieure à 23... (minuit ou 24 hr)
Heure = 0; // ...Remise à 0 de la variable heure
Jour++; // Incrémentation de 1 Jour toutes les 24 Heures
}
}
if (etat_btn_StartStop == HIGH && etat_btn_Reset == HIGH) {
etat_BoutonAppuyer = 0; // réinitialise la variable "etat_BoutonAppuyer" à "0" cequi évite l'effet rebond
}
Fn_Display(); // Fonction principale d'Affichage en temps réel.
}
void Fn_Display() { // rafraîchi l'Affichage en temps réel toutes le millisecondes.
sprintf(Chrono, "%02ld:%02ld:%02ld:%02ld:%03ld", Jour, Heure, Minute, Seconde, Milliseconde); //Formate l'affichage.
printCenter(header[2], 0); // Affiche le titre de la fonction en cours
printCenter(Chrono, 1); // Affiche tous les chiffres composant le temps chrono
printCenter(header[6], 2); // Identifie chaque colonne de l'affichage sous le chrono
switch (etat_ChronoOnOFF) { // Affiche le rôle des boutons "Start/Stop & Reset "
case true: lcd.setCursor(0, 3); lcd.print(Label[0]); // si etat_ChronoOnOFF = vrai
break;
case false: lcd.setCursor(0, 3); lcd.print(Label[1]);// si etat_ChronoOnOFF = faux
break;
}
// Affiche l'état de la fonction Mute/Tick
if (etat_Mute) {
lcd.setCursor(14, 3);
lcd.print("MUTE");
}
else if (!etat_Mute) {
lcd.setCursor(14, 3);
lcd.print("Tick");
}
}
//********************************************************************************//
// Fonction Affichage des Chronos //
// "Ligne" = numéro de ligne ET "TypeTime" = texte fin ligne //
//********************************************************************************//
/*
void AffichageChrono (int Ligne, char TypeTime[])
{
// Affichage du type de temps en bout de ligne
lcd.setCursor(10, Ligne);
lcd.print(TypeTime);
// Affichage des ":"
lcd.setCursor(2, Ligne);
lcd.print(":");
lcd.setCursor(5, Ligne);
lcd.print(":");
// Affichage des Millisecondes en fonction de sa valeur
if (Milliseconde > 99) {
lcd.setCursor(6, Ligne);
lcd.print(Milliseconde);
}
else if (Milliseconde > 9 && Milliseconde < 100) {
lcd.setCursor(6, Ligne);
lcd.print("0");
lcd.setCursor(7, Ligne);
lcd.print(Milliseconde);
}
else if (Milliseconde > 0 && Milliseconde < 10) {
lcd.setCursor(6, Ligne);
lcd.print("00");
lcd.setCursor(8, Ligne);
lcd.print(Milliseconde);
}
else {
lcd.setCursor(6, Ligne);
lcd.print("000");
}
// Affichage des Secondes en fonction de sa valeur
if (Seconde < 10) {
lcd.setCursor(3, Ligne);
lcd.print("0");
lcd.setCursor(4, Ligne);
lcd.print(Seconde);
}
else {
lcd.setCursor(3, Ligne);
lcd.print(Seconde);
}
// Affichage des Minutes en fonction de sa valeur
if (Minute < 10) {
lcd.setCursor(0, Ligne);
lcd.print("0");
lcd.setCursor(1, Ligne);
lcd.print(Minute);
}
else {
lcd.setCursor(0, Ligne);
lcd.print(Minute);
}
}
*/