récupérer l'heure d'un rtc ds 1307 pour avoir des conditions de temps

Bonjour à tous !
Pour la suite de mon projet j'ai besoin d'avoir l'heure :slight_smile:
Pour cela j'utilise la carte ci dessous :

J'ai suivie le tuto du forum mais je ne comprends pas ou est l'erreur, j'ai bien l'heure exacte ainsi que le jour qui s'affiche au début puis après "pb accées horloge"

j'ai câblé le 5v sur le 5v, le gnd avec le gnd, borne sda avec d1, et borne scl avec d2

Voici le code provenant du forum :

//Exemple 2 : reglage automatique

#include <Wire.h>
#include "simpleRTC.h"

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Serial.println("Programme exemple 2 : reglage automatique RTC\n");

  Serial.print("Date de compil : ");
  Serial.println(__DATE__);
  uint8_t a, m, j;
  extraireDateCompil(__DATE__, &a, &m, &j);
  Serial.print("annee=");
  Serial.println(a);
  Serial.print("mois=");
  Serial.println(m);
  Serial.print("jour=");
  Serial.println(j);

  Serial.print("Heure de compil : ");
  Serial.println(__TIME__);
  uint8_t hh, mm, ss;
  extraireHeureCompil(__TIME__, &hh, &mm, &ss);
  Serial.print("heure=");
  Serial.println(hh);
  Serial.print("minute=");
  Serial.println(mm);
  Serial.print("seconde=");
  Serial.println(ss);

  if (RTC.regler(a, m, j, hh, mm, ss))
  {
    Serial.println("Reglage OK");
  }
  else
  {
    Serial.println("Probleme acces RTC");
  }
  Serial.println();
}

void loop()
{
  static uint32_t ref = 0;
  if (millis() - ref >= 1000)
  {
    ref += 1000;
    if (RTC.actualiser())
    {
      afficherRTC();
    }
    else
    {
      Serial.println("pb acces horloge");
    }
  }
}

void extraireDateCompil(char dateCompil[], uint8_t *annee, uint8_t *mois, uint8_t *jour)
{
  //__DATE__
  //The date of translation of the source file: a character string literal of the
  //form "Mmm dd yyyy", where the names of the months are the same as
  //those generated by the asctime function, and the first character of dd is
  //a space character if the value is less than 10. If the date of translation is not
  //available, an implementation-defined valid date shall be supplied.
  *mois = extraireMois(&dateCompil[0]);
  *jour = extraireNombre2Car(&dateCompil[4]);
  *annee = extraireNombre2Car(&dateCompil[9]);
}

void extraireHeureCompil(char heureCompil[], uint8_t *heure, uint8_t *minute, uint8_t *seconde)
{
  //__TIME__
  //The time of translation of the source file: a character string literal of the
  //form "hh:mm:ss" as in the time generated by the asctime function. If
  //the time of translation is not available, an implementation-defined valid
  //time shall be supplied.
  *heure = extraireNombre2Car(&heureCompil[0]);
  *minute = extraireNombre2Car(&heureCompil[3]);
  *seconde = extraireNombre2Car(&heureCompil[6]);
}

uint8_t extraireMois(char chaine[])
{
  uint8_t m = 0;
  if (chaine[0] == 'J')
  {
    if (chaine[1] == 'a') m = 1;
    else if (chaine[1] == 'u' && chaine[2] == 'n') m = 6;
    else if (chaine[1] == 'u' && chaine[2] == 'l') m = 7;
  }
  else if (chaine[0] == 'F') m = 2;
  else if (chaine[0] == 'M')
  {
    if (chaine[2] == 'r') m = 3;
    else if (chaine[2] == 'y') m = 5;
  }
  else if (chaine[0] == 'A')
  {
    if (chaine[1] == 'p') m = 4;
    else if (chaine[1] == 'u') m = 8;
  }
  else if (chaine[0] == 'S') m = 9;
  else if (chaine[0] == 'O') m = 10;
  else if (chaine[0] == 'N') m = 11;
  else if (chaine[0] == 'D') m = 12;
  return m;
}

uint8_t extraireNombre2Car(char chaine[])
{
  return extraireChiffre(chaine[0]) * 10 + extraireChiffre(chaine[1]);
}

uint8_t extraireChiffre(char c)
{
  return ('0' <= c && c <= '9') ? c - '0' : 0;
}

void afficherRTC()
{
  afficherJourSemaineJJJ(RTC.jourSemaine());
  Serial.print(' ');
  afficherDateHeure(RTC.annee(), RTC.mois(), RTC.jour(), RTC.heure(), RTC.minute(), RTC.seconde());
  Serial.print(" heure d'");
  if (RTC.heureEte())
  {
    Serial.print("ete");
  }
  else
  {
    Serial.print("hiver");
  }
  Serial.print(" (");
  afficherDateHeure(RTC.anneeUTC(), RTC.moisUTC(), RTC.jourUTC(), RTC.heureUTC(), RTC.minute(), RTC.seconde());
  Serial.println(" UTC)");
}

void afficherJourSemaineJJJ(uint8_t joursem)
{
  switch (joursem)
  {
    case 0  : Serial.print("Dim"); break;
    case 1  : Serial.print("Lun"); break;
    case 2  : Serial.print("Mar"); break;
    case 3  : Serial.print("Mer"); break;
    case 4  : Serial.print("Jeu"); break;
    case 5  : Serial.print("Ven"); break;
    case 6  : Serial.print("Sam"); break;
    default : Serial.print("xxx");
  }
}

void afficherDateHeure(uint8_t annee, uint8_t mois, uint8_t jour, uint8_t heure, uint8_t minute, uint8_t seconde)
{
  afficherDate(annee, mois, jour);
  Serial.print(' ');
  afficherHeure(heure, minute, seconde);
}

void afficherDate(uint8_t annee, uint8_t mois, uint8_t jour)
{
  Serial_print_nn(jour);
  Serial.print('/');
  Serial_print_nn(mois);
  Serial.print("/20");
  Serial_print_nn(annee);
}

void afficherHeure(uint8_t heure, uint8_t minute, uint8_t seconde)
{
  Serial_print_nn(heure);
  Serial.print(':');
  Serial_print_nn(minute);
  Serial.print(':');
  Serial_print_nn(seconde);
}

void Serial_print_nn(uint8_t nombre)
{
  if (nombre < 10) Serial.print('0');
  Serial.print(nombre);
}

Si quelqu'un à une idée je suis preneur :slight_smile:
Merci :

Salut ,

il faut faire 2 choses pour utiliser un RTC , un petit programme qui sert uniquement a mettre a l ' heure est la premiere chose .

quand c' est fait , on reprend son programme de base , puis on le modifie afin de l ' utiliser uniquement .

Dans votre code , il y a les 2 " choses " reunies je pense , d' ou l ' erreur qui apparait apres .

Le problème peut aussi venir de ta façon de gérer les millis().
Tu devrais essayer un truc comme ça :

void loop()
{
  static uint32_t ref = millis();
  if (millis() - ref >= 1000ul) {
    ref = millis();
    if (RTC.actualiser()) afficherRTC();
    else Serial.println("pb acces horloge");
  }
}

Le code est juste l'exemple fourni avec la lib, testé ok en son temps :slight_smile:

Cherche plutôt dans le montage physique.
Soudures ok?

@lesept :

ref += 1000 au lieu de ref=millis() permet une meilleure régularité de l'actualisation.

Si le reste de la fonction loop dure par exemple 5 ms, ref=millis() conduirait à une actualisation toutes les 1005 ms. Donc le programme sauterait une seconde une fois de temps en temps.

Alors que ref += 1000 rattrape le temps passé ailleurs

Non puisque ref est mis à jour avec millis dès que le if est vrai

Bonjour à tous et merci de vos réponses

oui effectivement le code viens d'un des tutos de bricoleau ^^

j'ai vérifier les soudures tout est ok mais peut etre niveau branchement il manque quelque chose ? je suis en sda=D2 et scl = D1

En utilisant juste un code pour la lecture comme vous dites j'ai la même erreur aussi :confused:


Merci !

lesept:
Non puisque ref est mis à jour avec millis dès que le if est vrai

Pardon je me suis mal exprimé.

Pas évident à expliquer en français alors voici un code tout simple, à charger sur n'importe quel arduino, et qui montre la différence entre les deux méthodes.

Dans le terminal série on peut observer qu'il y a une dérive temporelle sur le timer2 alors que le timer1 reste toujours bien cadencé.

void setup() {
  Serial.begin(115200);
}

long maintenant;

void loop() {
  maintenant = millis();
  
  static unsigned long ref1 = 0;
  if (maintenant - ref1 >= 1000) {
    ref1 += 1000;
    afficher(1);
  }

  static unsigned long ref2 = 0;
  if (maintenant - ref2 >= 1000) {
    ref2 = maintenant;
    afficher(2);
  }

  //Et ensuite le loop fait autre chose pendant quelques ms...
  delay(3);
}

void afficher(int timer) {
  Serial.print("timer");
  Serial.print(timer);
  Serial.print(" - millis()=");
  Serial.print(maintenant);
  Serial.print(", ecart = ");
  Serial.print(((maintenant + 500 ) % 1000) - 500);
  Serial.println(" ms");
}

Je ne pense pas que la partie software soit en cause.

SDA sur D2, donc tu n'es pas sur un arduino mais vraisemblablement sur un ESP.

Je n'ai jamais eu l'usage d'un RTC avec un ESP car les miens ont toujours un accès à internet.
Donc quand je veux l'heure je demande à internet, et après millis() est suffisamment précise pour rester à l'heure exacte pendant quasiment une journée.
Il suffit d'une resynchro NTP toutes les 12 heures et c'est nickel.

Ceci dit, un ESP fonctionne en 3V3.
Tu indiques que tu alimentes le RTC en 5V.
Je me demande s'il ne va pas tirer SDA et SCL vers 5V, ce qui peut poser problème.
Essaye plutôt de brancher le RTC en 3V3.

Pour vérifier le cablage avec le RTC, commence par exécuter un scanner I2C.

Normalement il doit t'indiquer avoir trouvé les deux composants I2C présents sur ton module (le DS1307 et une eeprom).

Re je ne sais pas pourquoi mais tout est ok x) entre temps j'ai envoyer un programme pour tester autre chose et en rechargeant le programme afficher heure tout s'affiche je ne comprends pas pourquoi x)

Il ne me reste plus qu'a trouver comment activer une sortie suivant un créneau horaire :stuck_out_tongue:

Merci de votre aide ! :slight_smile:

Ps : tu parles de resynchronisé il faut le joindre au programme d'affichage ? ou pas la peine ?
il me dit ceci :
14:43:48.309 -> Scanning...
14:43:48.309 -> I2C device found at address 0x68 !
14:43:48.344 -> done
14:43:48.344 ->

Très probablement un faux contact quelque part.
Y aurait pas une breadboard entre les deux modules?

PS : ah oui effectivement la photo de ton module montre qu'il ne contient pas d'eeprom, juste un ds1307.

Le DS 1307 est le pire des RTC, avec une dérive quotidienne bien supérieure à celle de la fonction millis() de ton ESP. Si tu dois absolument utiliser un RTC, passe sur un DS3231.

Je ne peux pas faire le test, mais je pense que la dérive peut être due à

ref2 = maintenant;

au lieu de

ref2 = millis () ;

puisque ref2 est mis à jour avec l'heure stockée avant l'affichage du timer 1.

Mais je peux me tromper...

peut être oui

Ok merci des infos pour le futur voulant faire un web serveur je possède une ESP32

est ce que cela peut remplacer la DS du coup ?

S'il est connecté à internet, il peut aller chercher l'heure régulièrement sur un serveur NTP. Il existe une bibliothèque dédiée et des tutos

lesept:
...
Mais je peux me tromper...

hihi
oui je te confirme :wink:

Modifie le code test à ta convenance, tu verras que dès lors que la fonction loop() dans sa globalité dure plus d'une milliseconde, il y a une dérive temporelle observable avec un timer recallé en permanence sur millis().

ref += 1000 est adapté aux cas où on souhaite que la fonction périodique s'exécute "en moyenne" toutes les 1000 ms.

ref = millis() est adapté aux cas où on souhaite avoir "au moins 1000 ms" entre deux exécutions consécutives de la fonction périodique.

je suis loin de tout comprendre et d' avoir un bon niveau , mais pourquoi le type de la variable maintenant est un long ? et pas un UL comme tout le monde dis qu il faut faire pour stocker la valeur de millis() ?

c ' est pas plutot ca qui produirait la derive ?

Non, ça ne joue pas sur la dérive.

@Bricoleau : je n'ai pas de RTC sous la main, je te fais confiance.

Bonjour à tous ,

je ré-ouvre le post car de nouveau je n'ais plus de retour de la rtc...

le câblage est ok je suis carrément en direct : sortie sda et scl directement sur la carte rtc.

Le scan trouve bien la carte...

voici le code il provient de la bibliothèque je ne sais pas quoi faire de plus :frowning:

//Exemple 2 : reglage automatique

#include <Wire.h>
#include "simpleRTC.h"

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  Serial.println("Programme exemple 2 : reglage automatique RTC\n");

  Serial.print("Date de compil : ");
  Serial.println(__DATE__);
  uint8_t a,m,j;
  extraireDateCompil(__DATE__, &a, &m, &j);
  Serial.print("annee=");
  Serial.println(a);
  Serial.print("mois=");
  Serial.println(m);
  Serial.print("jour=");
  Serial.println(j);

  Serial.print("Heure de compil : ");
  Serial.println(__TIME__);
  uint8_t hh,mm,ss;
  extraireHeureCompil(__TIME__, &hh, &mm, &ss);
  Serial.print("heure=");
  Serial.println(hh);
  Serial.print("minute=");
  Serial.println(mm);
  Serial.print("seconde=");
  Serial.println(ss);

  if (RTC.regler(a,m,j,hh,mm,ss))
  {
    Serial.println("Reglage OK");
  }
  else
  {
    Serial.println("Probleme acces RTC");
  }
  Serial.println();
}

void loop()
{
  static uint32_t ref = 0;
  if (millis() - ref >= 1000)
  {
    ref += 1000;
    if (RTC.actualiser())
    {
      afficherRTC();
    }
    else
    {
      Serial.println("pb acces horloge");
    }
  }
}

void extraireDateCompil(char dateCompil[], uint8_t *annee, uint8_t *mois, uint8_t *jour)
{
//__DATE__
//The date of translation of the source file: a character string literal of the
//form "Mmm dd yyyy", where the names of the months are the same as
//those generated by the asctime function, and the first character of dd is
//a space character if the value is less than 10. If the date of translation is not
//available, an implementation-defined valid date shall be supplied.
  *mois = extraireMois(&dateCompil[0]);
  *jour = extraireNombre2Car(&dateCompil[4]);
  *annee = extraireNombre2Car(&dateCompil[9]);
}

void extraireHeureCompil(char heureCompil[], uint8_t *heure, uint8_t *minute, uint8_t *seconde)
{
//__TIME__
//The time of translation of the source file: a character string literal of the
//form "hh:mm:ss" as in the time generated by the asctime function. If
//the time of translation is not available, an implementation-defined valid
//time shall be supplied.
  *heure = extraireNombre2Car(&heureCompil[0]);
  *minute = extraireNombre2Car(&heureCompil[3]);
  *seconde = extraireNombre2Car(&heureCompil[6]);
}

uint8_t extraireMois(char chaine[])
{
  uint8_t m = 0;
  if (chaine[0] == 'J')
  {
    if (chaine[1] == 'a') m = 1;
    else if (chaine[1] == 'u' && chaine[2] == 'n') m = 6;
    else if (chaine[1] == 'u' && chaine[2] == 'l') m = 7;
  }
  else if (chaine[0] == 'F') m = 2;
  else if (chaine[0] == 'M')
  {
    if (chaine[2] == 'r') m = 3;
    else if (chaine[2] == 'y') m = 5;
  }
  else if (chaine[0] == 'A')
  {
    if (chaine[1] == 'p') m = 4;
    else if (chaine[1] == 'u') m = 8;
  }
  else if (chaine[0] == 'S') m = 9;
  else if (chaine[0] == 'O') m = 10;
  else if (chaine[0] == 'N') m = 11;
  else if (chaine[0] == 'D') m = 12;
  return m;
}

uint8_t extraireNombre2Car(char chaine[])
{
  return extraireChiffre(chaine[0]) * 10 + extraireChiffre(chaine[1]);
}

uint8_t extraireChiffre(char c)
{
  return ('0' <= c && c <= '9') ? c - '0' : 0;
}

void afficherRTC()
{
  afficherJourSemaineJJJ(RTC.jourSemaine());
  Serial.print(' ');
  afficherDateHeure(RTC.annee(), RTC.mois(), RTC.jour(), RTC.heure(), RTC.minute(), RTC.seconde());
  Serial.print(" heure d'");
  if (RTC.heureEte())
  {
    Serial.print("ete");
  }
  else
  {
    Serial.print("hiver");
  }
  Serial.print(" (");
  afficherDateHeure(RTC.anneeUTC(), RTC.moisUTC(), RTC.jourUTC(), RTC.heureUTC(), RTC.minute(), RTC.seconde());
  Serial.println(" UTC)");
}

void afficherJourSemaineJJJ(uint8_t joursem)
{
  switch (joursem)
  {
    case 0  : Serial.print("Dim");break;
    case 1  : Serial.print("Lun");break;
    case 2  : Serial.print("Mar");break;
    case 3  : Serial.print("Mer");break;
    case 4  : Serial.print("Jeu");break;
    case 5  : Serial.print("Ven");break;
    case 6  : Serial.print("Sam");break;
    default : Serial.print("xxx");
  }
}

void afficherDateHeure(uint8_t annee, uint8_t mois, uint8_t jour, uint8_t heure, uint8_t minute, uint8_t seconde)
{
  afficherDate(annee, mois, jour);
  Serial.print(' ');
  afficherHeure(heure, minute, seconde);
}

void afficherDate(uint8_t annee, uint8_t mois, uint8_t jour)
{
  Serial_print_nn(jour);
  Serial.print('/');
  Serial_print_nn(mois);
  Serial.print("/20");
  Serial_print_nn(annee);
}

void afficherHeure(uint8_t heure, uint8_t minute, uint8_t seconde)
{
  Serial_print_nn(heure);
  Serial.print(':');
  Serial_print_nn(minute);
  Serial.print(':');
  Serial_print_nn(seconde);
}

void Serial_print_nn(uint8_t nombre)
{
  if (nombre < 10) Serial.print('0');
  Serial.print(nombre);
}

Si le code de la bibliothèque ne marche pas, c'est soit un problème de connexion, soit un problème hardware (la RTC ou la carte Arduino). Vérifie et re-vérifie les connexions... et la continuité avec un multimètre.

Teste ta carte, si possible avec un autre périphérique I2C (un écran OLED si tu as).
Teste ta RTC sur une autre carte...