Faire une horloge avec Arduino, le module DS3231 et l’écran LCD.
Ce projet vise à régler l’heure et la date actuelle. Le module DS3231 RTC intègre une pile bouton que nous permet d’enregistrer internement l’information dans le cas où la source d’alimentation soit interrompue.
La communication du module se réalise par le biais du bus I2C et la tension de tenue est de 2.3 V à 5.5 V.
Table de matières:
Mettre le module DS3231 à l’ heure et montrer le résultat sur un écran LCD.
Il est nécessaire:
- Plaque Arduino UNO ou équivalent.
- Module DS3231 RTC Horloge.
- Écran LCD.
- Potentiomètre.
- Plaque d’essai ou breadboard.
- cables.
- Résistance de 10KΩ.
Schéma:
Nous commençons par faire les connexions de l’écran LCD. Vous pouvez suivre le tutoriel Comment relier l’écran LCD à l’Arduino Uno.
Pour faire les connexions du module RTC: on connecte la broche GND à la masse sur la plaque d’essai; la broche VCC, avec la source d’alimentation sur la plaque; la SDA, avec le pin analogique 4 d’ Arduino; et la broche SLC, avec le pin analogique 5:
Code:
Tout d’abord on inclut la bibliothèque Wire.h, elle contient les fonctions nécessaires pour faire fonctionner le bus I2C d’ Arduino. Sur les cartes Arduino, la broche SDA (ligne de données) correspond au pin analogique 4 et la broche SLC (ligne horloge), au pin analogique 5. Après, on défini l’adresse I2C afin de contrôler et recevoir des données du module RTC:
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
Nous commençons par ajuster l’heure de notre module dans l’instruction setup(). Pour indiquer qu’elle est finalement ajustée, dans la commande loop() on fera clignoter la diode du pin 13 de la carte Arduino.
void setup(){
byte secondes, minutes, heure, jourSemaine, jourMois, mois, annee;
Wire.begin();
pinMode(13, OUTPUT);
/* mettre à l'heure*/
secondes = 0;
minutes = 30;
heure = 11;
jourSemaine = 4;
jourMois = 14;
mois = 01;
annee = 21;
Dater(secondes, minutes, heure, jourSemaine, jourMois, mois, annee);
}
Dans la fonction setup() on configure les variables: secondes, minutes, heure, jourSemaine, jourMois, mois et année comme byte. On initialise la bibliothèque: Wire.begin(), on configure le pin 13 comme sortie et on donne des valeurs aux variables:
- secondes: valeurs entre 0 et 59
- minutes: entre 0 et 59
- heure: entre 0 et 23
- jourSemaine: entre 1 et 7 (lundi = 1, mardi = 2…)
- jourMois: entre 1 et 31
- mois: entre 1 et 12
- année: de 0 à 99
Finalement, on fait appel à la fonction Dater(), chargée d’ajuster la date.
void loop(){
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}
Dans la fonction loop() on demande de faire clignoter la diode en alternant High et Low.
byte decToBcd(byte val){
return ( (val/10*16) + (val%10) );
}
La fonction ci-desus nous servira à transformer les données décimales en code binaire.
void Dater(
byte secondes, // 0-59
byte minutes, // 0-59
byte heure, // 0-23
byte jourSemaine, // 1-7 1=Lundi, 7=Dimanche
byte jourMois, // 1-28/29/30/31
byte mois, // 1-12
byte annee // 0-99
){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(secondes));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(heure));
Wire.write(decToBcd(jourSemaine));
Wire.write(decToBcd(jourMois));
Wire.write(decToBcd(mois));
Wire.write(decToBcd(annee));
Wire.endTransmission();
}
Dans la fonction Dater() on commence le transfer avec le mandat beginTransmission, ensuite, on écrit les données avec write, et finalment, on ferme la fonction avec endTransmission.
Code complet:
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
byte decToBcd(byte val){
return ( (val/10*16) + (val%10) );
}
void Dater(
byte secondes, // 0-59
byte minutes, // 0-59
byte heure, // 0-23
byte jourSemaine, // 1-7 1=Lundi, 7=Dimanche
byte jourMois, // 1-28/29/30/31
byte mois, // 1-12
byte annee // 0-99
){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(secondes));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(heure));
Wire.write(decToBcd(jourSemaine));
Wire.write(decToBcd(jourMois));
Wire.write(decToBcd(mois));
Wire.write(decToBcd(annee));
Wire.endTransmission();
}
void setup(){
byte secondes, minutes, heure, jourSemaine, jourMois, mois, annee;
Wire.begin();
pinMode(13, OUTPUT);
/* mettre à l'heure*/
secondes = 0;
minutes = 01;
heure = 13;
jourSemaine = 4;
jourMois = 14;
mois = 01;
annee = 21;
Dater(secondes, minutes, heure, jourSemaine, jourMois, mois, annee);
}
void loop(){
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}
Le code complet pour montrer la date sur l’écran LCD:
Une fois que l’horloge est ajustée, si nous voulons le montrer sur l’écran LCD, nous devons utiliser la bibliothèque LiquidCrystal.h et on configure les pins que nous allons utiliser pour la connexion de l’écran.
Dans la fonction setup() on ajoute l’ initialiseation du LCD.
Dans la fonction loop() on demande de faire imprimer les données sur l’écran en faisant appel a la fonction TrouverDate() et on transfert les données à string pour pouvoir les imprimer.
Dans la fonction TrouverDate() on obtient les données du module RTC: on initialise le transfert, on redémarre le registre du pointeur et on demande les données nécessaires.
#include "Wire.h"
#include <LiquidCrystal.h>
#define DS3231_I2C_ADDRESS 0x68
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
byte bcdToDec(byte val){
return ( (val/16*10) + (val%16) );
}
void TrouverDate(byte *secondes,byte *minutes,byte *heure,byte *jourSemaine,byte *jourMois,byte *mois,byte *annee){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
*secondes = bcdToDec(Wire.read() & 0x7f);
*minutes = bcdToDec(Wire.read());
*heure = bcdToDec(Wire.read() & 0x3f);
*jourSemaine = bcdToDec(Wire.read());
*jourMois = bcdToDec(Wire.read());
*mois = bcdToDec(Wire.read());
*annee = bcdToDec(Wire.read());
}
void setup(){
byte secondes, minutes, heure, jourSemaine, jourMois, mois, annee;
Wire.begin();
lcd.begin(16, 2);
}
void loop(){
byte secondes, minutes, heure, jourSemaine, jourMois, mois, annee;
String s, m, d, mth, h, mty;
TrouverDate(&secondes, &minutes, &heure, &jourSemaine, &jourMois, &mois, &annee);
if (secondes < 10) { s = "0" + String(secondes); } else { s = String(secondes); }
if (minutes < 10) { m = "0" + String(minutes); } else { m = String(minutes); }
h = String(heure);
if (jourMois < 10) { d = "0" + String(jourMois); } else { d = String(jourMois); }
if (mois < 10) { mth = "0" + String(mois); } else { mth = String(mois); }
if (annee < 10) { mty = "0" + String(annee); } else { mty = String(annee); }
char* days[] = { "NA", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do" };
lcd.clear();
lcd.setCursor(4,0);
lcd.print(h + ":" + m + ":" + s);
lcd.setCursor(1,1);
lcd.print(String(days[jourSemaine]) + " " + d + "/" + mth + "/20" + mty);
delay(1000); // on attend
}
Horloge à trois boutons pour régler l’heure et la date.
Gérer deux programmes pour contrôler une horloge est vraiment confus. Il est beaucoup plus simple le fait de pouvoir manipuler l’heure et la date à travers d’un menu avec des boutons.
Il est nécessaire:
- Carte Arduino Uno ou équivalent.
- Module DS3231 RTC.
- Écran LCD.
- Potentiomètre.
- Plaque d’essai ou breadboard.
- Cables
- 3 résistances de 10 KΩ.
- 3 boutons-poussoirs.
Schéma:
On peut partir du modèle antérieur en ajoutant trois pulsateurs. Le premier, on l’utilisera pour redémarrer et sélectionner l’option que nous voulons changer; il sera relié au pin 6 de la carte Arduino. Le deuxième bouton, servirá à diminuer la valeur; relié au pin 5. Le troisième bouton, augmentera la valeur et sera connecté au pin 4 de la carte Arduino.
Code:
Dans la fonction loop() on vérifiera l’heure et la date et si nous voulons la changer. Pour cela, on configure la variable etatActuel pour nous indiquer si le bouton Reset est pressé (bouton 1). Ce bouton activera un compteur de 0 à 7. Selon le nombre de fois où nous le pressons, on aura accès à différentes options:
- 1 pression: modifier l’heure (le compteur se trouve à 1)
- 2 pressions: modifier les minutes (compteur à 2)
- 3 pressions: modifier le jour de la semaine (compteur à 3)
- 4 pressions: modifier le jour du mois (compteur à 4)
- 5 pressions: modifier le mois (compteur à 5)
- 6 pressions: modifier l’année (compteur á 6)
- 7 pressions: montrer la date complète (compteur à 0)
Pour gérer les données on crée la fonction modifier_temps(). Pour montrer l’heure et la date sur l’écran, on fait appel à la fonction VoirDate().
#include "Wire.h"
#include <LiquidCrystal.h>
#define DS3231_I2C_ADDRESS 0x68
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int etatActuel = 0;
int etatUltime = 0;
int compteur = 0;
int MoinsAnterieur =0;
int etatPlus = 0;
int etatMoins = 0;
int PlusAnterieur =0;
byte decToBcd(byte val){
return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val){
return ( (val/16*10) + (val%16) );
}
void TrouverDate(byte *secondes,byte *minutes,byte *heure,byte *jourSemaine,byte *jourMois,byte *mois,byte *annee){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
*secondes = bcdToDec(Wire.read() & 0x7f);
*minutes = bcdToDec(Wire.read());
*heure = bcdToDec(Wire.read() & 0x3f);
*jourSemaine = bcdToDec(Wire.read());
*jourMois = bcdToDec(Wire.read());
*mois = bcdToDec(Wire.read());
*annee = bcdToDec(Wire.read());
}
void VoirDate(){
byte secondes, minutes, heure, jourSemaine, jourMois, mois, annee;
String s, m, d, mth, h, mty;
TrouverDate(&secondes, &minutes, &heure, &jourSemaine, &jourMois, &mois, &annee);
if (secondes < 10) { s = "0" + String(secondes); } else { s = String(secondes); }
if (minutes < 10) { m = "0" + String(minutes); } else { m = String(minutes); }
h = String(heure);
if (jourMois < 10) { d = "0" + String(jourMois); } else { d = String(jourMois); }
if (mois < 10) { mth = "0" + String(mois); } else { mth = String(mois); }
if (annee < 10) { mty = "0" + String(annee); } else { mty = String(annee); }
char* days[] = { "NA", "Lu", "Ma", "Me", "Je", "Ve", "Sa", "Di" };
lcd.clear();
lcd.noBlink();
lcd.setCursor(4,0);
lcd.print(h + ":" + m + ":" + s);
lcd.setCursor(1,1);
lcd.print(String(days[jourSemaine]) + " " + d + "/" + mth + "/20" + mty);
}
void modifier_temps(int type){
byte secondes, minutes, heure, jourSemaine, jourMois, mois, annee;
TrouverDate(&secondes, &minutes, &heure, &jourSemaine, &jourMois, &mois, &annee);
Serial.println("pressé");
int addition = 0;
int soustraction = 0;
if(etatMoins != MoinsAnterieur){
if(etatMoins == HIGH){
soustraction = 1;
}
}
if(etatPlus != PlusAnterieur){
if(etatPlus == HIGH){
addition = 1;
}
}
if(type == 1){ // modifier l'heure
String h;
h = String(heure);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write("Modifier l'heure");
lcd.setCursor(0, 1);
lcd.print(h);
lcd.blink();
if(soustraction == 1){
heure = heure-1;
}
if(addition == 1){
heure = heure+1;
}
if(heure > 23) heure=0;
}
if(type == 2){ // modifier les minutes
String m;
m = String(minutes);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write("Modifier minutes");
lcd.setCursor(0, 1);
lcd.print(m);
lcd.blink();
if(soustraction == 1){
minutes = minutes-1;
}
if(addition == 1){
minutes = minutes+1;
}
if(minutes > 59) minutes=0;
}
if(type == 3){ // modifier le jour de la semaine
String d;
d = String(jourSemaine);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write("Modifier jour semaine");
lcd.setCursor(0, 1);
lcd.print(d);
lcd.blink();
if(soustraction == 1){
jourSemaine = jourSemaine-1;
}
if(addition == 1){
jourSemaine = jourSemaine+1;
}
if(jourSemaine == 8) jourSemaine=1;
if(jourSemaine == 0) jourSemaine=7;
}
if(type == 4){ // modifier le jour du mois
String m;
m = String(jourMois);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write("Modifier jour mois");
lcd.setCursor(0, 1);
lcd.print(m);
lcd.blink();
if(soustraction == 1){
jourMois = jourMois-1;
}
if(addition == 1){
jourMois = jourMois+1;
}
if(jourMois == 32) jourMois=1;
if(jourMois == 0) jourMois=31;
}
if(type == 5){ // modifier mois
String ms;
ms = String(mois);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write("Modifier mois");
lcd.setCursor(0, 1);
lcd.print(ms);
lcd.blink();
if(soustraction == 1){
mois = mois-1;
}
if(addition == 1){
mois = mois+1;
}
if(mois == 13) mois=1;
if(mois == 0) mois=12;
}
if(type == 6){ // modifier annee
String a;
a = String(annee);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write("Modifier annee");
lcd.setCursor(0, 1);
lcd.print(a);
lcd.blink();
if(soustraction == 1){
annee = annee-1;
}
if(addition == 1){
annee = annee+1;
}
if(annee == 100) annee=1;
if(annee == 0) annee=99;
}
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(secondes));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(heure));
Wire.write(decToBcd(jourSemaine));
Wire.write(decToBcd(jourMois));
Wire.write(decToBcd(mois));
Wire.write(decToBcd(annee));
Wire.endTransmission();
}
void setup(){
byte secondess, minutes, heure, jourSemaine, jourMois, mois, annee;
Wire.begin();
lcd.begin(16, 2);
//Serial.begin(9600);
pinMode(6,INPUT); // bouton - menu
pinMode(5,INPUT); // bouton - moins
pinMode(4,INPUT); // bouton - plus
}
void loop(){
etatActuel=digitalRead(6);
etatMoins=digitalRead(5);
etatPlus=digitalRead(4);
//Serial.println(etatActuel);
if(etatActuel != etatUltime){
if(etatActuel == HIGH){
compteur = compteur +1;
//Serial.println(compteur);
}
}
if(compteur == 0){
VoirDate();
delay(1000);
}else if(compteur == 1){
modifier_temps(1); // modifier l'heure
delay(500);
}else if(compteur == 2){
modifier_temps(2); // modifier les minutes
delay(500);
}else if(compteur == 3){
modifier_temps(3); // modifier jour de la semaine
delay(500);
}else if(compteur == 4){
modifier_temps(4); // modifier jour du mois
delay(500);
}else if(compteur == 5){
modifier_temps(5); // modifier mois
delay(500);
}else if(compteur == 6){
modifier_temps(6); // modifier annee
delay(500);
}else if(compteur == 7){
compteur = 0;
delay(1000);
}
}