Skyduino:~#
Articles
arduino, Corrigé, programmation, projet, python, tutoriel

[Tutoriel Arduino] Horloge RTC (DS1307) + librairie LiquidCrystal

Bonjour tous le monde !

Aujourd’hui je vous est préparé un tutoriel sur les horloges RTC, mais pas de librairies "RTC" toute prêtes pour ce tutoriel, nous allons tout faire "à la main" ;)
Au passage je vous montrerai comment utiliser la librairie "LiquidCrystal" pour afficher du texte sur un écran lcd (compatible HD44780).

Tout d’abord voici le matériel dont nous allons avoir besoin :
- une carte arduino UNO,
- un écran lcd 2x16 compatible HD44780,
- un potentiomètre de 10K,
- un circuit RTC sur base DS1307.

Le principe de fonctionnement de notre systéme final :
Démarage -> demande de synchronisation sur le port série ?
-> oui -> récupération de la date et de l’heure -> stockage sur le module RTC
-> non -> affichage de l’heure stocké dans le module RTC

Avant de commencer regardons comment lire/écrire dans nos modules RTC.

Le DS1307
Le module DS1307 ce contrôle par I2C, rien de bien compliquer donc, il nous suffira d’utiliser Wire.h.
Le DS1307 contient 63 octets de ram, sur c’est 63 octets de ram, 7 contiennent la date et l’heure (incrémenté automatiquement), plus un 8eme octet pour la configuration du DS1307 (nous ne nous y intéresseront pas pour le moment), les 56 octets restant sont un "bonus" pour nous développeurs, on pourra y stocker des données d’usage (des variables par exemples).
Une grosse chose à remarquer, c’est que les valeurs (jours, mois, années, …) sont stocké en BCD !

Alors le BCD (décimal codé binaire) c’est quoi ?
C’est très simple, prenons le nombre 42 :) en binaire cela ferait 00101010, car on converti la valeur sur 8 bits directement, en bcd on code les chiffres indépendamment, 42 donne donc 4 (0100) et 2 (0010) -> 01000010.
Maintenant que nous maitrisons le pouvoir du bcd (^^) nous allons pouvoir faire une fonction bcd -> valeur brute :

byte bcd2dec(byte bcd) {
  return ((bcd / 16 * 10) + (bcd % 16)); 
}

byte dec2bcd(byte dec) {
  return ((dec / 10 * 16) + (dec % 10));
}

Maintenant regardons de plus prés l’organisation interne de la ram du DS1307 :

En utilisant ce schéma on peut en déduire une série de fonction qui nous permettront de communiquer avec le module DS1307 :
(Je vais utiliser un structure pour stocker les valeurs jour, mois, … restez calme, une structure c’est juste une sorte de "super" variable qui peut en contenir d’autres de type différents)

#define DS1307_ADDRESS 0x68

typedef struct {
  uint8_t secondes;
  uint8_t minutes;
  uint8_t heures; // format 24h
  uint8_t jourDeLaSemaine; // 0~7 = lundi, mardi, ...
  uint8_t jour;
  uint8_t mois; 
  uint8_t annee; // format yy (ex 2012 -> 12)
} Date;
// Ps uint8_t est un synonyme de byte, byte ne pouvant etre utilise dans un structure contenu dans un .h externe

// Fonction configurant le DS1307 avec la date/heure fourni
void ecrire(Date *date) {
  Wire.beginTransmission(DS1307_ADDRESS); // Début de transaction I2C
  Wire.send(0); // Arrête l'oscillateur du DS1307
  Wire.send(dec2bcd(date->secondes)); // Envoi des données
  Wire.send(dec2bcd(date->minutes));
  Wire.send(dec2bcd(date->heures));
  Wire.send(dec2bcd(date->jourDeLaSemaine));
  Wire.send(dec2bcd(date->jour));
  Wire.send(dec2bcd(date->mois));
  Wire.send(dec2bcd(date->annee));
  Wire.send(0); // Redémarre l'oscillateur du DS1307
  Wire.endTransmission(); // Fin de transaction I2C
}

// Fonction récupérant l'heure et la date courante à partir du DS1307
void lire(Date *date) {
  Wire.beginTransmission(DS1307_ADDRESS); // Début de transaction I2C
  Wire.send(0); // Demande les info à partir de l'adresse 0 (soit toutes les info)
  Wire.endTransmission(); // Fin de transaction I2C

  Wire.requestFrom(DS1307_ADDRESS, 7); // Récupère les info (7 octets = 7 valeurs correspondant à l'heure et à la date courante)

  date->secondes = bcd2dec(Wire.receive()); // stockage et conversion des données reçu
  date->minutes = bcd2dec(Wire.receive());
  date->heures = bcd2dec(Wire.receive() & 0b111111);
  date->jourDeLaSemaine = bcd2dec(Wire.receive());
  date->jour = bcd2dec(Wire.receive());
  date->mois = bcd2dec(Wire.receive());
  date->annee = bcd2dec(Wire.receive());
}

Ps: si lors de la compilation vous avez une erreur au niveau de la structure, c’est normal, un bug dans l’ide arduino fait qu’il est impossible d’utiliser une structure en la déclarant dans un sketch, il faut obligatoirement la placer dans un .h dans le même dossier que le .pde (ou .ino) puis l’inclure avec #include "monheader.h" par exemple.

Récapitulons.
Nous savons maintenant comment convertir les données en provenance et en direction du DS1307.
Nous avons les différentes routines nécessaire à la communication avec le module DS1307.

Que nous manque t’il ?
Et bien il nous manque toute la partie affichage et toute la partie synchronisation.

Commençons par la partie synchronisation, il nous faut une fonction en mesure de vérifier lors du démarage de l’arduino si le pc souhaite synchroniser l’heure et selon stocker ou non l’heure en mémoire.

Comment allons nous faire ?
C’est trés simple, nous allons créer un protocole "maison".
Tout d’abord nous allons choisir (de manière totalement arbitraire) un message qui sera envoyé sur le port série, si le pc nous répond nous commenceront la phase de synchronisation sinon le programme continuera normalement.

Le message envoyé sera "SYNC", la réponse attendu sera "ACK", si lors de l’envoi de "SYNC" le pc répond "ACK" c’est que celui ci souhaite synchroniser l’heure.
Il faudra aussi prévoir un "timeout" dans le cas ou le pc ne souhaite pas synchroniser l’heure, voir que celui ci n’est pas relié à l’arduino.

// Fonction vérifiant la présence d'une demande de synchronisation en provenance du pc et récupérant les données de synchronisation ou à défaut récupérant la date et l'heure courante 
void synchronisation(Date *date) {
  Serial.print("SYNC"); // Envoi de la commande de synchronisation
  int i;
  for(i = 0 ; (Serial.available() < 3) && (i < 6) ; i++) // Attente de 3s max 
    delay(500);
  if(i != 6) { // Il n'y as pas eu de timeout
    if(Serial.read() == 'A') 
      if(Serial.read() == 'C')
        if(Serial.read() == 'K') { // Si le pc à répondu par une commande ACK c'est que la synchronisation peut commencer
          while(Serial.available() < 7); // Attente des 7 octets de configuration
          date->secondes = Serial.read(); // Réception et conversion des données reçu
          date->minutes = Serial.read();
          date->heures = Serial.read();
          date->jourDeLaSemaine = Serial.read();
          date->jour = Serial.read();
          date->mois = Serial.read();
          date->annee = Serial.read();
          ecrire(date); // Stockage dans le DS1307 des donnes recu
        }
  } 
  else 
    lire(date); // Si le pc n'as pas répondu à la demande de synchronisation la fonction ce content de lire les données courante du DS1307
}

Maintenant intéressons nous à la partie affichage, nous allons faire un affichage de ce type :
Ligne 1 : XXX JJ / MM / AA -> XXX = les 3 1er lettres du jour (LUN, MAR, MER, JEU, VEN, SAM, DIM), JJ = jour, MM = mois, AA = année
Ligne 2 : HH : MM : SS -> HH = heures, MM = minutes, SS = secondes
Et petites contraintes (héhé ;)) : les 3 lettres du jour seront placée en PROGMEM, et les ‘:’ devront clignoter à la fréquence de ~1Hz.

Bon pour la partie progmem, vous ne pouvez pas l’inventer donc je vous la donne avec les explications qui vont bien :

#include <avr/pgmspace.h>
#define PSTR2(s) (__extension__({static unsigned char __c[] PROGMEM = (s); &__c[0];}))

// utilisation : lcd_print(PSTR2("Hello World !"));

void lcd_print(prog_uchar *data){
   char lcdBuf[16] = {0};
   byte c, i = 0;
   c = (char)pgm_read_byte(data);
   while(c != 0 && i < 16){
      lcdBuf[i++] = c;
      c =(char)(pgm_read_byte(++data));
   }
   lcd.print(lcdBuf);
}

De même pour la partie ‘:’ clignotants :

void blinkPoint(unsigned long interval, byte x, byte y) {
   static unsigned char state = 0;
   static unsigned long prevMillis = 0;
   unsigned long curMillis = millis();
   if(curMillis - prevMillis > interval) {
      prevMillis = curMillis;   
      lcd.setCursor(x, y);
      lcd.write(state ? ':' : ' ');
      state = !state;
   }
}

En bonus voici quelques autres morceaux de code de ma fabrication qui pourrait vous être utile plus tard :
Effacer des caractères d’un point A à un point B sur une même ligne :

void clear(byte ligne, byte debut, byte fin) {
  for(byte i = debut ; i <= fin ; i++){
    lcd.setCursor(i, ligne);
    lcd.print(' ');
  }
} 

Créer un caractères personnalisé stocker en PROGMEM :

#include <LiquidCrystal.h>
#include <avr/pgmspace.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

PROGMEM prog_uchar smiley[8] = {
  B00000,
  B10001,
  B00000,
  B00000,
  B10001,
  B01110,
  B00000,
};

void setup(){
   lcd.begin(16, 2);
   lcd.setCursor(0, 0);
   pCreateChar(0, smiley);
   lcd.write(0);
}

void loop(){

}

void pCreateChar(uint8_t location, prog_uchar *charmap) {
  location &= 0x7;
  lcd.command(LCD_SETCGRAMADDR | (location << 3));
  for (uint8_t i = 0; i < 8; i++) {
    lcd.write(pgm_read_byte_near(charmap + i));
  }

Bien à présent réfléchissons à notre affichage, il va nous falloir une fonction qui s’occupera d’afficher tout nos données et de faire clignoter nos ‘:’.
Il faudra que celle ci affiche les valeurs qui lui seront passer, il faudra aussi qu’elle transforme le numéro correspond au jour de la semaine en lettre et quelle fasse clignoter les deux ‘:’.

// Fonction affichant les données contenu dans la structure Date passé en référence
void affichage(Date *date) {
  clear(0, 0, 16); // Efface la 1er ligne de l'écran
  lcd.setCursor(0, 0); // Place le curseur à (0,0)
  switch(date->jourDeLaSemaine) { // Affiche sur 3 lettres le jour en cours
  case 1:
    lcd_print(PSTR2("LUN "));
    break;

  case 2:
    lcd_print(PSTR2("MAR "));
    break;

  case 3:
    lcd_print(PSTR2("MER "));
    break;

  case 4:
    lcd_print(PSTR2("JEU "));
    break;

  case 5:
    lcd_print(PSTR2("VEN "));
    break;

  case 6:
    lcd_print(PSTR2("SAM "));
    break;

  case 7:
    lcd_print(PSTR2("DIM "));
    break;
  }
  
  lcd.setCursor(4, 0); // Place le curseur à (0,4) (juste aprés les 3 lettres du jour + espace)
  lcd.print(date->jour / 10, DEC);// Affichage du jour sur deux caractères
  lcd.setCursor(5, 0);
  lcd.print(date->jour % 10, DEC);
  lcd.setCursor(6, 0);
  lcd.print(" / ");
  lcd.setCursor(9, 0);
  lcd.print(date->mois / 10, DEC);// Affichage du mois sur deux caractères
  lcd.setCursor(10, 0);
  lcd.print(date->mois % 10, DEC);
  lcd.setCursor(11, 0);
  lcd.print(" / ");
  lcd.setCursor(14, 0);
  lcd.print(date->annee / 10, DEC);// Affichage de l'année sur deux caractères
  lcd.setCursor(15, 0);
  lcd.print(date->annee % 10, DEC);
  
  clear(1, 0, 16); // Efface la 2eme ligne de l'écran
  lcd.setCursor(0, 1); // Place le curseur en début de la 2eme ligne
  lcd.print(date->heures / 10, DEC); // Affichage de l'heure sur deux caractères
  lcd.setCursor(1, 1);
  lcd.print(date->heures % 10, DEC);
  lcd.setCursor(2, 1);
  lcd.print(" : ");
  lcd.setCursor(5, 1);
  lcd.print(date->minutes / 10, DEC); // Affichage des minutes sur deux caractères
  lcd.setCursor(6, 1);
  lcd.print(date->minutes % 10, DEC);
  lcd.setCursor(7, 1);
  lcd.print(" : ");
  lcd.setCursor(10, 1);
  lcd.print(date->secondes / 10, DEC); // Affichage des secondes sur deux caractères
  lcd.setCursor(11, 1);
  lcd.print(date->secondes % 10, DEC);

  blinkPoint1(1000, 3, 1); // Clignotement du 1er ':'
  blinkPoint2(1000, 8, 1); // Clignotement du 2eme ':'
}

Voila voila, tous est prét ! Rassemblons tout les morceau et voyons ce que ça donne !

Le code principal complet :

#include <Wire.h> // Inclusion de la librairie Wire pour la gestion de l'I2C qui nous permettra de communiquer avec le DS1307
#include "structure.h" // Inclusion de notre fichier de structure qui définit le type "Date"
#include <avr/pgmspace.h> // Inclusion de la librairie PGMSPACE qui permet l'utilisation de PROGMEM
#include <LiquidCrystal.h> // Inclusion de la librairie LiquidCrystal qui permet de gérer un écran lcd (ici 2x16)

#define PSTR2(s) (__extension__({static unsigned char __c[] PROGMEM = (s); &__c[0];})) // Macro permettant de stocker facilement du texte en PROGMEM
#define DS1307_ADDRESS 0x68 // Adresse I2C du module DS1307

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Création de l'objet lcd, notre lcd sera câbler sur les broches D2~D5 (bus de données) D11 (ENABLE) et D12 (RS)
Date date; // Création de l'objet date qui contiendra les données sur la date/heure courante

// Fonction de convertion bcd -> décimal
byte bcd2dec(byte bcd) {
  return ((bcd / 16 * 10) + (bcd % 16)); 
}

// Fonction de convertion decimal -> bcd
byte dec2bcd(byte dec) {
  return ((dec / 10 * 16) + (dec % 10));
}

// Fonction configurant le DS1307 avec la date/heure fourni
void ecrire(Date *date) {
  Wire.beginTransmission(DS1307_ADDRESS); // Début de transaction I2C
  Wire.send(0); // Arrête l'oscillateur du DS1307
  Wire.send(dec2bcd(date->secondes)); // Envoi des données
  Wire.send(dec2bcd(date->minutes));
  Wire.send(dec2bcd(date->heures));
  Wire.send(dec2bcd(date->jourDeLaSemaine));
  Wire.send(dec2bcd(date->jour));
  Wire.send(dec2bcd(date->mois));
  Wire.send(dec2bcd(date->annee));
  Wire.send(0); // Redémarre l'oscillateur du DS1307
  Wire.endTransmission(); // Fin de transaction I2C
}

// Fonction récupérant l'heure et la date courante à partir du DS1307
void lire(Date *date) {
  Wire.beginTransmission(DS1307_ADDRESS); // Début de transaction I2C
  Wire.send(0); // Demande les info à partir de l'adresse 0 (soit toutes les info)
  Wire.endTransmission(); // Fin de transaction I2C

  Wire.requestFrom(DS1307_ADDRESS, 7); // Récupère les info (7 octets = 7 valeurs correspondant à l'heure et à la date courante)

  date->secondes = bcd2dec(Wire.receive()); // stockage et conversion des données reçu
  date->minutes = bcd2dec(Wire.receive());
  date->heures = bcd2dec(Wire.receive() & 0b111111);
  date->jourDeLaSemaine = bcd2dec(Wire.receive());
  date->jour = bcd2dec(Wire.receive());
  date->mois = bcd2dec(Wire.receive());
  date->annee = bcd2dec(Wire.receive());
}

// Fonction vérifiant la présence d'une demande de synchronisation en provenance du pc et récupérant les données de synchronisation ou à défaut récupérant la date et l'heure courante 
void synchronisation(Date *date) {
  Serial.print("SYNC"); // Envoi de la commande de synchronisation
  int i;
  for(i = 0 ; (Serial.available() < 3) && (i < 6) ; i++) // Attente de 3s max 
    delay(500);
  if(i != 6) { // Il n'y as pas eu de timeout
    if(Serial.read() == 'A') 
      if(Serial.read() == 'C')
        if(Serial.read() == 'K') { // Si le pc à répondu par une commande ACK c'est que la synchronisation peut commencer
          while(Serial.available() < 7); // Attente des 7 octets de configuration
          date->secondes = Serial.read(); // Réception et conversion des données reçu
          date->minutes = Serial.read();
          date->heures = Serial.read();
          date->jourDeLaSemaine = Serial.read();
          date->jour = Serial.read();
          date->mois = Serial.read();
          date->annee = Serial.read();
          ecrire(date); // Stockage dans le DS1307 des donnes reçu
        }
  } 
  else 
    lire(date); // Si le pc n'as pas répondu à la demande de synchronisation la fonction ce content de lire les données courante du DS1307
}

// Fonction affichant au maximum une ligne de 16 caractéres depuis la PROGMEM sur l'écran lcd
void lcd_print(prog_uchar *data){
  char lcdBuf[17] = {0};
  byte c, i = 0;
  c = (char)pgm_read_byte(data);
  while(c != 0 && i < 17){
    lcdBuf[i++] = c;
    c =(char)(pgm_read_byte(++data));
  }
  lcd.print(lcdBuf);
}

// Fonction faisant clignoter un ':' à interval régulier spécifier par "interval" et ce aux coordonnées (x, y) (ligne , colonne) 
void blinkPoint1(unsigned long interval, byte x, byte y) {
  static unsigned char state = 0;
  static unsigned long prevMillis = 0;
  unsigned long curMillis = millis();
  if(curMillis - prevMillis > interval) {
    prevMillis = curMillis;   
    lcd.setCursor(x, y);
    lcd.write(state ? ':' : ' ');
    state = !state;
  }
}
void blinkPoint2(unsigned long interval, byte x, byte y) {
  static unsigned char state = 0;
  static unsigned long prevMillis = 0;
  unsigned long curMillis = millis();
  if(curMillis - prevMillis > interval) {
    prevMillis = curMillis;   
    lcd.setCursor(x, y);
    lcd.write(state ? ':' : ' ');
    state = !state;
  }
}

// Fonction effacant l'écran à la ligne spécifié d'un point debut à un point fin inclut
void clear(byte ligne, byte debut, byte fin) {
  for(byte i = debut ; i <= fin ; i++){
    lcd.setCursor(i, ligne);
    lcd.print(' ');
  }
}

// Fonction affichant les données contenu dans la structure Date passé en référence
void affichage(Date *date) {
  clear(0, 0, 16); // Efface la 1er ligne de l'écran
  lcd.setCursor(0, 0); // Place le curseur à (0,0)
  switch(date->jourDeLaSemaine) { // Affiche sur 3 lettres le jour en cours
  case 1:
    lcd_print(PSTR2("LUN "));
    break;

  case 2:
    lcd_print(PSTR2("MAR "));
    break;

  case 3:
    lcd_print(PSTR2("MER "));
    break;

  case 4:
    lcd_print(PSTR2("JEU "));
    break;

  case 5:
    lcd_print(PSTR2("VEN "));
    break;

  case 6:
    lcd_print(PSTR2("SAM "));
    break;

  case 7:
    lcd_print(PSTR2("DIM "));
    break;
  }
  
  lcd.setCursor(4, 0); // Place le curseur à (0,4) (juste aprés les 3 lettres du jour + espace)
  lcd.print(date->jour / 10, DEC);// Affichage du jour sur deux caractéres
  lcd.setCursor(5, 0);
  lcd.print(date->jour % 10, DEC);
  lcd.setCursor(6, 0);
  lcd.print(" / ");
  lcd.setCursor(9, 0);
  lcd.print(date->mois / 10, DEC);// Affichage du mois sur deux caractéres
  lcd.setCursor(10, 0);
  lcd.print(date->mois % 10, DEC);
  lcd.setCursor(11, 0);
  lcd.print(" / ");
  lcd.setCursor(14, 0);
  lcd.print(date->annee / 10, DEC);// Affichage de l'année sur deux caractéres
  lcd.setCursor(15, 0);
  lcd.print(date->annee % 10, DEC);
  
  clear(1, 0, 16); // Efface la 2eme ligne de l'écran
  lcd.setCursor(0, 1); // Place le curseur en début de la 2eme ligne
  lcd.print(date->heures / 10, DEC); // Affichage de l'heure sur deux caractéres
  lcd.setCursor(1, 1);
  lcd.print(date->heures % 10, DEC);
  lcd.setCursor(2, 1);
  lcd.print(" : ");
  lcd.setCursor(5, 1);
  lcd.print(date->minutes / 10, DEC); // Affichage des minutes sur deux caractéres
  lcd.setCursor(6, 1);
  lcd.print(date->minutes % 10, DEC);
  lcd.setCursor(7, 1);
  lcd.print(" : ");
  lcd.setCursor(10, 1);
  lcd.print(date->secondes / 10, DEC); // Affichage des secondes sur deux caractéres
  lcd.setCursor(11, 1);
  lcd.print(date->secondes % 10, DEC);

  blinkPoint1(1000, 3, 1); // Clignotement du 1er ':'
  blinkPoint2(1000, 8, 1); // Clignotement du 2eme ':'
}

// Setup()
void setup() {
  lcd.begin(16, 2); // Initialisation du lcd
  Serial.begin(9600); // Initialisation du port série
  Wire.begin(); // Initialisation du bus I2C
  synchronisation(&date); // Tentative de synchronisation avec le pc
}

// loop()
void loop() {
  lire(&date);
  affichage(&date); // Affichage de l'heure
  delay(1000); // Rafraichissement de 1Hz
}

Le fichier structure.h

/* La strutucture suivante "Date" permet de manipuler facilement les données de date / heure
 * Pour faire simple une structure est une sorte de "super variable" pouvant contenir d'autres variables de type différents.
 * Son principe de fonctionnement est cependant totalement différent d'un tableau, pour accéder à un membre d'une structure il faut utiliser .
 * Exemple : Date date;
 *           date.mois = 1;
 *
 * Attention ! Lorsque la structure est passé en argument via un pointeur, ou qu'on accède à celle ci via un pointeur il faut utiliser ->
 * Exemple : Date *date, date2;
 *           date = &date2; // le pointeur date (*date) pointe désormais sur l'adresse de date2 (&date2)
 *           date->mois = 1; // correspond à date2.mois = 1;
 * /!\ Quand une strucuture ou une variable est passé en référence via un pointeur à une fonction c'est la variable pointé qui est modifié ET NON UNE COPIE de la variable comme c'est le cas dans un passage d'arguments normal.  
 */

typedef struct {
  uint8_t secondes;
  uint8_t minutes;
  uint8_t heures; // format 24h
  uint8_t jourDeLaSemaine; // 1~7 => lundi, mardi, ...
  uint8_t jour;
  uint8_t mois; 
  uint8_t annee; // format yy (ex 2012 -> 12)
} Date;

Et voici le code python qui s’occupera de faire la synchronisation (à exécuter une fois)

# -*- coding: cp1252 -*-
import serial, datetime, time

# Port Série utilisez par l'arduino
SERIALPORT = "COM4"

# Vitesse du port série
SERIALSPEED = 9600

# ---------------------------------------------------------------------

print "~ Arduino Clock - Sync Tool ~"
print "Created by SkyWodd"
print " "

print "Openning serial port ... ",
try:
    arduino = serial.Serial(SERIALPORT, SERIALSPEED, timeout=1)
except:
    print "FAILLED !"
    exit(-1)
print "OK !"

print "Booting up arduino ... ",
arduino.setDTR(level = True)
time.sleep(0.5)
arduino.setDTR(level = False)
ligne = arduino.readline()
while not "SYNC" in ligne: 
    ligne = arduino.readline()
print "Ok !"

time.sleep(1)

now = datetime.datetime.now()
print "Current year: %d" % int(str(now.year)[-2:])
print "Current month: %d" % now.month
print "Current day: %d" % now.day
print "Current hour: %d" % now.hour
print "Current minute: %d" % now.minute
print "Current second: %d" % now.second

sdow = time.strftime("%A")
dow = 0
if sdow == "Monday" :
    dow = 1
if sdow == "Tuesday" :
    dow = 2
if sdow == "Wednesday" :
    dow = 3
if sdow == "Thursday" :
    dow = 4
if sdow == "Friday" :
    dow = 5
if sdow == "Saturday" :
    dow = 6
if sdow == "Sunday" :
    dow = 7

print "Current Day Of Week : %d" % dow

arduino.write("ACK")
arduino.write(chr(now.second))
arduino.write(chr(now.minute))
arduino.write(chr(now.hour))
arduino.write(chr(dow))
arduino.write(chr(now.day))
arduino.write(chr(now.month))
arduino.write(chr(int(str(now.year)[-2:])))

print "Closing serial port ... ",
arduino.close()
print "OK !"

print "Bye bye !"

Bon je vous ai donné le code mais ça ne fait pas tout il faut aussi faire le câblage !
Pour le lcd :
Arduino -> LCD
GND -> GND
+5v -> VCC
(curseur du potentiomètre, voir schéma) -> VO
D5 -> Dr4
D4 -> Dr5
D3 -> Dr6
D2 -> Dr7
D11 -> ENABLE
D12 -> RS
GND -> R/W

Schéma du câblage

Pour le DS1307 :
Arduino -> DS1307
+5v -> VCC
GND -> GND
A4 -> SDA
A5 -> SCL

Lançons le programme python :
~ Arduino Clock - Sync Tool ~
Created by SkyWodd

Openning serial port ... OK !
Booting up arduino ... Ok !
Current year: 1
Current month: 1
Current day: 7
Current hour: 17
Current minute: 20
Current second: 48
Current Day Of Week : 6
Closing serial port ... OK !
Bye bye !

Et maintenant regardons du coté du lcd :

Et après un reset ?

Ça marche !!

Voila, à présent vous ne devriez plus avoir de mal à utiliser des modules DS1307.
Vous devriez pouvoir réaliser votre propre Arduino-Horloge vous même sans problémes ;)

J’espère que ce tutoriel vous a plu, il m’as demandé 4h de programmation et … 2 jours de rédaction (oui je sais on dirait pas qu’il y a 2 jours de rédaction vu le nombre de fautes T_T).

Si vous avez des questions n’hésitez pas à poster un commentaire ;)

About these ads

Discussion

91 réflexions sur “[Tutoriel Arduino] Horloge RTC (DS1307) + librairie LiquidCrystal

  1. bonjour,
    et avec ds1302 rtc module+pcd8544 monochrome sur arduino uno
    quel sont les modif a faire pour que cela fonctionne?
    je rencontre un probleme pour garde l heure avec la pile apres un reset

    Publié par axel_67 | 8 janvier 2012, 12 h 14 min
  2. Super article !

    pour l’utilisation de PROGMEM, un petit lien sur ce que c’est permet de mieux comprendre les mécaniques en oeuvre. J’ai toruvé ce lien http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38003

    Publié par coliss | 8 janvier 2012, 16 h 25 min
  3. bonjour.
    très intéressant votre projet.
    la routine de clignotement est super!!!

    void blinkPoint1(unsigned long interval, byte x, byte y) {
    093 static unsigned char state = 0;
    094 static unsigned long prevMillis = 0;
    095 unsigned long curMillis = millis();
    096 if(curMillis – prevMillis > interval) {
    097 prevMillis = curMillis;
    098 lcd.setCursor(x, y);
    099 lcd.write(state ? ‘:’ : ‘ ‘);
    100 state = !state;
    101 }
    je voudrai remplacer les ":" par la valeur d’une variable est ce possible ?
    j’ai essayé lcd.write(state ? ‘ ma variable : ‘ ‘) pas possible!!!!
    avez vous une idée?
    merci de votre lecture

    Publié par moni | 11 juin 2012, 14 h 03 min
    • Il suffit de remplacer lcd.write() par lcd.print().

      Ps: ne pas oublier de remplacer ‘ ‘ par une chaine de caractére vide de la longueur de la variable ;)
      Sinon il restera des morceaux de l’ancienne valeur par moment ;)

      Publié par skywodd | 11 juin 2012, 14 h 07 min
  4. merci SKYWODD.

    Publié par moni | 12 juin 2012, 6 h 58 min
  5. Cool ce progamme !!
    Felicitation au concepteur…
    J’aimerai ajouter un capteur de temperature (LM35 ou DS1631) a ce systeme et afficher la temperature sur le LCD…
    Pourriez vous m’aider ?

    Publié par bulletshit17 | 22 juin 2012, 14 h 16 min
  6. Bonsoir,
    Dites le code en python, comment l’ajoute t-on au programme ?
    Helpe me !

    Et s’il vous plaît où trouver la librairie pgmspace

    Publié par bulletshit17 | 22 juin 2012, 22 h 26 min
  7. Bonjour,
    Merci pour ce tutoriel.

    J’ai un problème au niveau de la déclaration de ma libraire structure.h.
    J’ai bien mis la libraire dans le même fichier que mon .ino
    Mais j’ai le message d’erreur "error: structure.h: No such file or directory"
    Je l’appelle bien par #include "structure.h" pourtant … (et le nom est bien orthographié)
    L’erreur disparaît lorsque j’écris #include , mais c’est sans effet (il ne connaît pas la structure Date lorsque je l’utilise).

    Une idée de comment corriger ce problème ?

    Publié par Spirale | 25 juin 2012, 16 h 18 min
    • >> J’ai bien mis la libraire dans le même fichier que mon .ino
      >> Mais j’ai le message d’erreur “error: structure.h: No such file or directory”

      J’ai bien précisé dans l’article :
      Ps: si lors de la compilation vous avez une erreur au niveau de la structure, c’est normal, un bug dans l’ide arduino fait qu’il est impossible d’utiliser une structure en la déclarant dans un sketch, il faut obligatoirement la placer dans un .h dans le même dossier que le .pde (ou .ino) puis l’inclure avec #include “monheader.h” par exemple.

      La structure doit être déclaré dans un fichier structure.h présent dans le même dossier que le .ino, mais pas dans le .ino.

      Publié par skywodd | 25 juin 2012, 18 h 37 min
      • Oui c’est ce que j’ai fait, désolé je me suis mal exprimé.
        J’ai un dossier avec dedans mon .ino et mon .h (structure.h).

        Publié par Spirale | 26 juin 2012, 9 h 06 min
  8. J’ai réussi à corriger le problème.
    En fait il fallait placer le .h dans le dossier où se trouve le dossier contenant le .ino (et pas dans le même dossier que le .ino).
    Par contre j’ai un autre problème. La librairie Wire.h ne connaît pas pas "Wire.send(donnee)", et me "conseille" d’utiliser "Wire.write(donnee)".
    Quand je regarde dans la libraire, ça me semble en effet être juste. Tu peux me confirmer que ça a bien le même effet ?

    Merci pour ton aide en tout cas.

    Publié par Spirale | 26 juin 2012, 9 h 28 min
    • >> En fait il fallait placer le .h dans le dossier où se trouve le dossier contenant le .ino (et pas dans le même dossier que le .ino).

      Oui c’est ça, pourquoi tu avais un dossier dans le dossier ?

      >> Par contre j’ai un autre problème. La librairie Wire.h ne connaît pas pas “Wire.send(donnee)”, et me “conseille” d’utiliser “Wire.write(donnee)”.
      >> Quand je regarde dans la libraire, ça me semble en effet être juste. Tu peux me confirmer que ça a bien le même effet ?

      Tu est sous arduino 1.0 ?
      Il y a eu des modifications entre 0023 et 1.0 :
      - Wire.send est devenu Wire.write
      - Wire.receive est devenu Wire.read
      Il suffit juste de remplacer send / receive par write / read ;)

      Publié par skywodd | 26 juin 2012, 15 h 42 min
  9. Bonsoir,
    Pourrais-tu nous aider, pour nous qui n’avons pas de connaissance sur le langage python, en nous montrant concrètement la manip qu’il faut faire avec le code python pour la synchronisation de l’heure ?
    PS. La procédure à suivre
    Merci !

    Publié par bulletshit17 | 28 juin 2012, 6 h 29 min
    • 1 – Installer python 2.7.x
      2 – Modifier le script pour que le port série correspondent à celui de l’arduino
      SERIALPORT = "LeNomDuPortSérieIci"
      3 – Brancher l’arduino
      4 – Enregistrer et lancer le script
      5 – Enjoy

      Il n’y a absolument rien à comprendre dans le script python, juste changer le port série et exécuter le tout ;)

      Publié par skywodd | 28 juin 2012, 10 h 03 min
  10. Bonjour
    Totalement novice dans la programmation j’ai le probleme ci dessous
    sketch_jun30a.cpp:2:98: error: structure.h: No such file or directory
    sketch_jun30a:-1: error: variable or field ‘ecrire’ declared void
    sketch_jun30a:-1: error: ‘Date’ was not declared in this scope
    sketch_jun30a:-1: error: ‘date’ was not declared in this scope
    sketch_jun30a:-1: error: variable or …… etc
    Merci de bien vouloir m’aider

    Publié par Dominique | 30 juin 2012, 9 h 28 min
  11. ok merci mais je comprend pas tout le dossier structure je ne le trouve pas je le doit le crée comment ? il vas bien dans le dossier librarie ?
    merci

    Publié par dominique | 30 juin 2012, 13 h 44 min
    • Les fichiers sont agencé comme ceci :
      - Ma_super_horloge (-> le dossier contenant le programme arduino)
      | – Ma_super_horloge.ino (-> le programme arduino)
      | – structure.h (-> le code de structure.h)

      Publié par skywodd | 30 juin 2012, 13 h 51 min
  12. Bonsoir,

    j´ai adoré votre tutoriel je suis entrain de l´adapter pour mes besoin ( car je n´ai pas de lcd mais plus pour faire du data loggin sur carte SD)

    par contre en lisant votre code j´ai du mal a comprendre cette ligne de code:

    " date->heures = bcd2dec(Wire.receive() & 0b111111); " (ligne 39)

    j´ai du mal a comprende pouquoi est il necesseraire de faire " & 0b111111 " ?

    je vous remercie d´avance

    Publié par Thierry | 26 janvier 2013, 3 h 29 min
  13. Bonsoir, j’essaye de voir comment votre code fonctionne.
    j’ai une carte mega 2560. Apres quelques modifs, le code fonctionne sur l’arduino et affiche l’heure (non à jours). Maintenant, j’essaye de lancer le code sous python pour mettre à l’heure et j’ai un problème :
    Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32
    Type "copyright", "credits" or "license()" for more information.
    >>> ================================ RESTART ================================
    >>>

    Traceback (most recent call last):
    File "C:\Users\Rodolphe\Documents\Arduino\ds1307\ds1307\Nouveau document texte.txt", line 2, in
    import serial, datetime, time
    ImportError: No module named serial
    >>>

    Pourtant j’ai bien modifé le port serie à "com16", je ne vois pas ou est le probleme,
    merci de votre aide.

    Publié par Rodolphe | 16 février 2013, 0 h 50 min
  14. C’est bon j’ai trouvé.
    J’avais un problème d’installation de Py-serial, ça fonctionne maintenant ;-)

    Par contre, j’ai un problème avec l’année, affiché à 01 ???

    Publié par Rodolphe | 16 février 2013, 11 h 08 min
    • A priori, la ligne : print "Current year: %d" % int(str(now.year)[-2]) me renvoie juste "1"

      Avec un peu d’aide exterieur avec cette ligne ca fonctionne : print "Current year: %s" % str(now.year)[-2:]

      Publié par Rodolphe | 18 février 2013, 22 h 07 min
      • Petit problème avec wordpress et la balise code désolé …

        La ligne devrait être :

        print "Current year: %d" % int(str(now.year)[-2:])
        

        Publié par skywodd | 18 février 2013, 22 h 42 min
      • et rajouter le : sur la ligne
        arduino.write(chr(int(str(now.year)[-2:])))
        j’avais le bug de l’année 01 sans.

        Publié par RB | 30 mai 2013, 21 h 35 min
  15. Bonjour, quand je rentre ton code complet arduino dans le logiciel Arduino 1.5.2 il me trouve des erreurs a la ligne 13 ,
    il me dit sa :

    HelloWorld:55: error: variable or field ‘synchronisation’ declared void
    HelloWorld:55: error: ‘Date’ was not declared in this scope
    HelloWorld:55: error: ‘date’ was not declared in this scope

    merci de ton aide et ton tuto et parfait, continue comme sa

    Publié par tomlaves | 19 février 2013, 21 h 27 min
  16. Merci pour ce tuto très complet!
    Mais…étant débutant(j’ai 17 ans et l’arduino est imposé dans mon projet pour le BAC, je découvre) j’aimerais savoir pour le code python, où le placer et dans quoi colle t’on le code, car au lancement de python j’ai une console qui me propose juste les copyright, la licence et les crédits… :/

    Publié par Benjamin | 20 mars 2013, 22 h 33 min
  17. Quand je lance le code python dans python shell, il m’affiche:
    "import serial, datetime, time
    ImportError: No module named serial", sans doute a cause de la libraire pyserial et je ne sais pas comment (bien) l’installer

    Publié par Benjamin | 21 mars 2013, 19 h 11 min
    • Manifestement PySerial n’est pas installé …

      Il suffit de ce rendre sur le site de PySerial, télécharger l’installateur pour ta version de python (j’utilise python 2.7 personnellement) et le reste ce fait tout seul normalement.

      Publié par skywodd | 21 mars 2013, 19 h 38 min
      • c’est ce que j’ai fait mais ça n’a pas marché, rien ne c’est fait, j’ai finalement trouvé une solution sur internet mais c’etait plutôt compliqué…Je pense que ça marche mais je confirmerais demain avec les arduinos du lycée

        Publié par Benjamin | 21 mars 2013, 19 h 40 min
  18. Maintenant que j’ai réussi a tout téléversser, j’ai un autre problème…
    L’afficheur me met 4 espace vide puis 15 / 15 / 15 puis à la ligne 45 : 15 :15
    Comment ajuster l’heure et la date? :/

    Publié par Benjamin | 22 mars 2013, 15 h 31 min
    • Il faut lancer le script python au moins une fois avec la carte arduino connecter en usb.
      C’est lui qui se charge de mettre à jour l’heure, la date et le jour en fonction de l’horloge de l’ordinateur.

      Publié par skywodd | 22 mars 2013, 16 h 06 min
      • C’est ce que j’ai fais, mais python m’affiche à son exécution la bonne date et la bonne heure mais a mon avis ne le transmet pas à l’arduino et donc ne l’affiche pas sur l’afficheur…

        Publié par Benjamin | 22 mars 2013, 19 h 14 min
      • Essaye un code d’exemple de la librairie RTClib pour tester ton module RTC ;)

        Publié par skywodd | 22 mars 2013, 19 h 16 min
  19. Mon erreur doit venir de là, je n’ai pas la librarie RTClib. Les arduinos étant au lycée(je ne peux presque rien tester sans), je testerais ça une autre fois.
    Merci beaucoup!

    Publié par Benjamin | 22 mars 2013, 19 h 29 min
  20. Avec le prof, je me suis rendu compte que l’heure et la date dépende des résistances placés sur SCL et SDA.(l’heure changeait tout le temps ou restait fixe mais il était 45 : 15 : 15). Il faut mettre quel résistance pour que ça marche?

    Publié par Benjamin | 28 mars 2013, 12 h 53 min
    • 10K marche sans probléme normalement.

      C’est surement une erreur de câblage, vérifie que les lignes SCL et SDA ne sont pas inversée et qu’elles soit bien sur A4 et A5 (broches analogique).

      Sinon c’est peut être le DS1307 qui est défectueux ?

      Publié par skywodd | 28 mars 2013, 13 h 06 min
      • Avec 10k il était 45 :15 15, avec 2.2k l’heure et la date changeais toute les secondes. Donc je pense que le module peut être défectueuse mais le module est neuf… :/ (sur les broches, je suis sur de ne pas m’être trompé)

        Publié par Benjamin | 28 mars 2013, 19 h 58 min
      • Essaye sans résistances, elle sont peut être déjà intégré dans ton module ;)

        Publié par skywodd | 28 mars 2013, 20 h 00 min
  21. C’est un module sparkfun, j’essayerais la semaine prochaine(je peut pas avant T.T), j’ai vu un schéma où ça marche sur un autre microcontroleur merci ;)

    Publié par Benjamin | 28 mars 2013, 20 h 03 min
  22. J’ai toujours un problème x_x
    J’ai remarqué qu’en fait l’affichage de l’heure et la date dépend de la "forme" du câble, quand je déplace le câble(en le laissant connecté) quelques rares fois(mais très rare et environ 2 secondes) l’affichage de l’heure et la date est bon (sauf l’année mais je n’en ai pas besoin). Comment faire pour pouvoir réussir a l’avoir sans toucher au câble?changer la breadboard?

    Publié par Benjamin | 8 avril 2013, 18 h 58 min
    • C’est un probléme de câblage, c’est sûr, check tes câbles et tes connections je peut pas t’aider plus …

      Publié par skywodd | 8 avril 2013, 19 h 02 min
      • J’ai déjà vérifier mes câbles très souvent, ça doit être la breadboard. Merci de ton aide quand même :)
        (j’ai quand même assez "pollué" les commentaires, tu peux en supprimer quelques un de moi si tu veux ;) )

        Publié par Benjamin | 8 avril 2013, 19 h 06 min
  23. (désolé de t’embêter encore^^) en fait le programme marche uniquement (je l’ai découvert par hasard) lorsque la masse est débranché sur le module d’horloge. C’est assez étrange mais j’aimerais juste savoir s’il n’y a aucun risque sur le montage du coup…

    Publié par Benjamin | 11 avril 2013, 8 h 46 min
  24. bonjour
    je suis à la recherche du logiciel qui me permetra de simuler mes montages avec arduino

    merci pour….

    Publié par FRETAX | 25 avril 2013, 12 h 28 min
  25. Bonjour et merci de ce tuto génial. Je débute et j’ai un pb sur la synchro date/heure de l’appli python au niveau de la ligne while not "SYNC" in ligne: où "SYNC" n’est pas reconnu. Le message d’erreur obtenu est :

    while not "SYNC" in ligne:
    TypeError: Type str doesn’t support the buffer API

    Heeeeelp merci d’avance !

    Publié par RB | 30 mai 2013, 15 h 51 min
  26. Effectivement c’est une version 2.7. Pourquoi la 33 n’est pas compatible ? branche ???

    Publié par RB | 30 mai 2013, 19 h 53 min
  27. Bonjour,
    Merci pour cette excellent article, je débute, pouvez vous me dire comment je peux télécharger les librairie.
    j’ai fait un copier coller dans ARDUINO 1.5 et j’ai plein d’erreur, je pens qu’il manque les librairie

    Merci pour votre réponse

    Charles

    Publié par ROUX CHARLES | 10 juin 2013, 19 h 52 min
    • Arduino 1.5 c’est UNIQUEMENT pour l’arduino Due qui utilise un processeur bien différent des autres cartes et qui est encore en beta.
      Si tu veut utiliser mon code sur une carte classique utilise l’ide "classique" 1.0.5.

      Publié par skywodd | 10 juin 2013, 19 h 55 min
      • Bonsoir,
        j’ai installé la version 1.0.5 d’arduino, j’ai carte UNO
        j’ai fait un copier coller
        et voilà les fautes, je pense qu’il me manque quelquechose

        sketch_jun10a.ino:2:98: error: structure.h: No such file or directory
        sketch_jun10a:12: error: variable or field ‘ecrire’ declared void
        sketch_jun10a:12: error: ‘Date’ was not declared in this scope
        sketch_jun10a:12: error: ‘date’ was not declared in this scope
        sketch_jun10a:13: error: variable or field ‘lire’ declared void
        sketch_jun10a:13: error: ‘Date’ was not declared in this scope
        sketch_jun10a:13: error: ‘date’ was not declared in this scope
        sketch_jun10a:14: error: variable or field ‘synchronisation’ declared void
        sketch_jun10a:14: error: ‘Date’ was not declared in this scope
        sketch_jun10a:14: error: ‘date’ was not declared in this scope
        sketch_jun10a:19: error: variable or field ‘affichage’ declared void
        sketch_jun10a:19: error: ‘Date’ was not declared in this scope
        sketch_jun10a:19: error: ‘date’ was not declared in this scope
        sketch_jun10a:10: error: ‘Date’ does not name a type
        sketch_jun10a:23: error: variable or field ‘ecrire’ declared void
        sketch_jun10a:23: error: ‘Date’ was not declared in this scope
        sketch_jun10a:23: error: ‘date’ was not declared in this scope
        sketch_jun10a:38: error: variable or field ‘lire’ declared void
        sketch_jun10a:38: error: ‘Date’ was not declared in this scope

        Il faudrait que je puise chargé la librairie structure .h

        Charles

        Publié par ROUX CHARLES | 10 juin 2013, 22 h 15 min
  28. Bonsoir,
    j’ai fait un copier coller de structure .h dans un fichier avec wordpad, que j’ai copié dans le répertoire du fichier principale et là les erreurs ont evoluées

    Horloge_RTC__DS1307____librairie_LiquidCrystal.ino:2:98: error: structure.h: No such file or directory
    Horloge_RTC__DS1307____librairie_LiquidCrystal:12: error: variable or field ‘ecrire’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:12: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:12: error: ‘date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:13: error: variable or field ‘lire’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:13: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:13: error: ‘date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:14: error: variable or field ‘synchronisation’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:14: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:14: error: ‘date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:19: error: variable or field ‘affichage’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:19: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:19: error: ‘date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:10: error: ‘Date’ does not name a type
    Horloge_RTC__DS1307____librairie_LiquidCrystal:23: error: variable or field ‘ecrire’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:23: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:23: error: ‘date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:38: error: variable or field ‘lire’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:38: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:38: error: ‘date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:55: error: variable or field ‘synchronisation’ declared void
    Horloge_RTC__DS1307____librairie_LiquidCrystal:55: error: ‘Date’ was not declared in this scope
    Horloge_RTC__DS1307____librairie_LiquidCrystal:55: error: ‘date’ was not declared in this scope

    là je pense qu’il me manque le fichier LiquidCristal.ino

    Charles

    Publié par ROUX CHARLES | 10 juin 2013, 22 h 26 min
  29. salut, je test ton tuto pour l’introduire dans un projet, et je n’arrive pas a utiliser ton script python, j’ai un
    I2C DS1307 que j’ai cablé comme ton tuto, mais lorsque je lance le script sa reste bloqué sur Booting up arduino …

    aurais tu une idée ? pour m’aider ?

    Merci

    Publié par Mcolivia | 30 octobre 2013, 12 h 51 min
  30. sa marche, j’avais mal cablé dsl et merci encore SKYWOOD!!

    Publié par Mcolivia | 30 octobre 2013, 13 h 36 min
  31. par contre j’ai l’année qui m’affiche 01 au lieu de 13 alors que j’ai bien Current year: 13

    Publié par Mcolivia | 30 octobre 2013, 13 h 39 min
  32. Bonjour Skywodd, et bravo pour ton superbe tutoriel. C’est vraiment une aide précieuse pour tous les débutants qui se lancent dans l’électronique

    J’ai moi aussi quelques soucis avec mon RTC.

    Après quelques adaptations,
    - création d’une variable "int zero =0;" et remplacement des "Wire.send(0);" par "Wire.send(zero);"
    - remplacement des Wire.send et Wire.receive par Wire.write et Wire.read
    le sketch compile sans alertes et semble tourner correctement.

    Le script Python se déroule normalement jusqu’au "bye bye", mais l’heure ne s’ajuste pas comme prévu.
    Mon écran LCD affiche irrémédiablement 13/15/2031…

    Quelques infos sur mon setup :
    - Arduino Uno R3
    - module "TinyRTC by Waiwan" sur base de DS1037 avec l’I2C connecté aux ports A4 et A5 de l’arduino
    - j’ai aussi un module barometrique BMP085 qui fonctionne sur ce bus, sans soucis.
    - j’ai vérifié les connections, tout semble bon. La pile du RTC est neuve…

    Aurais-tu une idée ?

    J’ai aussi des petites questions complémentaires :
    - Dans ton code, je vois plusieurs fois la même instruction avec des significations différentes :
    Wire.send(0); // Arrête l’oscillateur du DS1307
    Wire.send(0); // Redémarre l’oscillateur du DS1307
    Wire.send(0); // Demande les info à partir de l’adresse 0 (soit toutes les info)
    Quelle en est l’explication ?
    - J’ai essayé de régler le RTC manuellement via le serial monitor. Si je veux programmer la date du 01/01/2001, dois-je entrer 010101 ou 111 ? Comment le RTC fait-il la distinction ?
    Cela fait-il une différence si j’envoie chaque byte séparément, ou si je tape tout à la file ?

    Merci d’avance !

    Publié par Max | 26 novembre 2013, 3 h 36 min
    • Pourquoi avoir créé une variable "zero" ?
      Wire.send((byte) 0); au lieu de Wire.send(zero); devrait résoudre quelques soucis à mon avis ;)

      Pour les autres questions c’est très simple :
      - Ce n’est pas parce que l’instruction est la même que le contexte et la signification est le même.
      Suivant où et quand tu envois "0" dans un registre le résultat est totalement différent, c’est la doc constructeur qui dit quoi faire et quand ;)

      - Tu ne peut pas changer l’heure manuellement avec le serial monitor. Il faut transmettre les valeurs sous forme d’octets bruts, pas de caractères. "010101" ça fait 6 octets en ASCII par exemple ;)
      Si tu veut faire le changement manuellement il te faut un vrai terminal série qui permet d’envoyer des données brutes au lieu de texte ASCII.

      Publié par skywodd | 1 décembre 2013, 18 h 22 min
  33. Salut, merci d’avoir pris le temps de répondre à mes questions.

    J’ai créé la variable "zero" afin d’éviter le message d’erreur suivant :
    "RTC.cpp:39:15: error: call of overloaded ‘write(int)’ is ambiguous"

    En fouillant sur le web, plusieurs sources expliquaient que ce message indique que le compilateur ne sait pas quel type de variable utiliser. Je me suis dit qu’en utilisant un entier déclaré au début du programme, le doute serait levé.

    Wire.send((byte) 0) me renvoie une erreur, mais effectivement, avec Wire.write((byte) 0) c’est plus simple et il n’y a pas d’erreur au compilage.

    Par contre, je n’arrive toujours pas à un résultat correct.
    Les secondes défilent bien, le temps continue à s’incrémenter quand je débranche l’arduino, mais le réglage de la date ne se fait pas :(

    Infos à tout hasard : après l’exécution du script Python, l’écran LCD reste noir. Il faut que je reset manuellement l’arduino.

    Aurais-tu une autre idée ?

    Publié par MAX | 4 décembre 2013, 15 h 56 min
    • Revérifie ton câblage à mon avis il y a un truc qui va pas. Le code devrait marcher en remplaçant Wire.send par Wire.write et en ajoutant le (byte) 0 où il faut, il y a rien d’autre à faire normalement.

      Publié par skywodd | 6 décembre 2013, 20 h 23 min
  34. Salut SKYWODD , et Salut a tous
    Super code BRAVO très belle réalisation,
    mais j’aimerais l’intégrer dans mon programme en menu veille et étant novice j’aimerai savoir comment il faut que je m’y prenne.
    J’ai tenté d’ajouté une fonction void veille(){ ton code } mais sans résultat

    cordialement un novice arduino

    Publié par nico | 6 avril 2014, 10 h 54 min
    • Le contenu de loop() permet de lire la date et de l’afficher.
      Si tu as une fonction qui est appelée lors de la veille il te suffit de mettre le code dedans pour faire l’affichage.

      /!\ Si cette fonction n’est pas appelée en boucle comme pour loop() il faudra que tu fasse toi même une boucle avec une condition de fin pour quitter le mode veille (sinon tu resteras éternellement en mode veille).

      Publié par skywodd | 9 avril 2014, 11 h 44 min
  35. OK géniale désoler de ne pas avoir répondu tout de suite merci pour ta raiponce ça fonctionne par contre comment avec la fonction:
    lire(&date); peut t’ont comparer l’heure actuel pour créer une interruption suivant l’heure actuel.
    Par exemple: si il est 22h fait ceci

    cordialement

    Publié par nico | 19 avril 2014, 18 h 09 min
  36. Merci de ta raiponce,
    en revanche que faut t’il apporter comme librairie
    car il me met en erreur
    in function ‘ void loop() ‘:
    error: expected primary-expression before ‘<' token
    error: 'span' was not declared in this scop
    error: expected ')' before 'class'

    merci pour ton aide
    cordialement

    Publié par nico | 21 avril 2014, 16 h 26 min
  37. OK,
    finalement c’est bon j’ai trouvé mon erreur
    en revanche autre problème comment faire pour que le code ne s’exécute une seule fois par jour car j’ai écris

    void loop(){
    lire(&date);
    if(date.heures == 22) {
    digitalWrite(led, HIGH);
    delay(10000);
    digitalWrite(led, LOW);
    }
    et le code s’exécute en boucle sur une heure
    y a t’il un moyen de cassé la boucle mais quelle reparte la prochaine fois que 22h00 arrive

    si non je suis obliger d’écrire (bien que ce ne soit pas dérangent)
    c’est juste pour accroître mes faible connaissance car le code dessous fonctionne
    void loop(){
    lire(&date);
    if(date.heures == 22)&&(date.minutes==1)&&(date.secondes==1) ) {
    digitalWrite(led, HIGH);
    delay(10000);
    digitalWrite(led, LOW);
    }

    cordialement

    Publié par nico | 21 avril 2014, 17 h 15 min
    • Tu as deux solutions :
      - soit tu test les heures/minutes/secondes
      - soit tu fait une variables dans laquelle tu stocks le jour de la dernière exécution.

      Ensuite le code deviendrait quelques chose dans ce style :
      lire(&date);
      if(date.heures == 22 && data.jour != lastJour) {
      digitalWrite(led, HIGH);
      delay(10000);
      digitalWrite(led, LOW);
      lastJour = date.jour;
      }

      Publié par skywodd | 21 avril 2014, 19 h 59 min
  38. Bonjour,
    Merci pour ces exemples très utiles.
    Est-il possible de décaler l’horloge en milli-secondes sans réinitialiser ?
    Cela pour le réglage à l’aide de boutons + et – par exemple.
    Cordialement.

    Publié par Hasler | 22 avril 2014, 18 h 17 min
  39. Salut SKYWOOD
    merci pour ta raiponce,
    Que pence tu du bouclier LCD 16*2 sainsmart?
    A tu déjà travailler avec?
    Car j’ai un petit soucis lors des appuie sur mes bouton
    j’ai essayer avec un condensateur 10nF derrière en touchant les soudure et rien n’y fait et suivant comment j’appuie sur les bouton mon texte passe de affichage jour a mode incendie aurait tu une idée?

    void menu(){
    key = read_LCD_buttons(); //lecture des boutons déclarer ligne 24 à 33
    lcd.clear();//efface l’afficheur LCD pour enlever les charactère qui ne seront pas remplacer.
    lcd.setCursor(0,0);
    lcd.print(" MENU");
    while(key != btnRIGHT){
    key = read_LCD_buttons();
    switch(key){

    case btnDOWN:{
    if(key == btnDOWN)
    {afficheur = afficheur++;}
    }

    case btnUP:{
    if (key == btnUP)
    {afficheur = afficheur–;}
    }

    if(afficheur <= 0)
    {
    afficheur = 0 ;
    }
    affiche(afficheur);
    }

    }}
    void affiche(int valeurRecue)
    {
    if(valeurRecue ==1)
    {
    key = read_LCD_buttons();
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" ESPACE JOUR");
    lcd.setCursor(0,1);
    lcd.print(" OK RETOUR");
    while(key != btnRIGHT){
    key = read_LCD_buttons();
    switch(key){
    case btnLEFT:{
    if(key == btnLEFT)
    {voletEspaceJourUP();}
    }}}}

    if(valeurRecue ==2)
    {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" ESPACE NUIT");
    lcd.setCursor(0,1);
    lcd.print(" OK RETOUR");
    }
    if(valeurRecue ==3)
    {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("TOUS LES VOLETS");
    lcd.setCursor(0,1);
    lcd.print(" OK RETOUR");
    }
    if(valeurRecue ==4)
    {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" MODE INCENDIE");
    lcd.setCursor(0,1);
    lcd.print(" OK RETOUR");
    }
    }

    Publié par nico | 22 avril 2014, 20 h 49 min

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Archives

Wow. Dogecoin. Amaze.

Laissez un tip en Dogecoin

DMMNFk6WBVTpx2Wu1Z35GL61QXSd6r6WQx

Suivre

Recevez les nouvelles publications par mail.

Joignez-vous à 678 followers