RTC DC1307 qui avance d'une heure

Bonjour à tous.

J'ai un petit programme permettant de gérer l'allumage et l'extinction progressive d'une rampe LED fonctionnant grâce à un Arduino Nano et une RTC DS1307.
Le programme fonctionne nickel, pas de souci de ce coté là seulement quand je compile puis téléverse sur la carte, l'heure affichée sur mon écran marque un décalage entre 50 min et 1h par rapport à l'heure normale.
Bien que fondamentalement ça ne nuise pas au bon fonctionnement du programme, j'aimerai corriger ce petit problème.
Au passage, dites-moi si vous voyez des erreurs ou des choses pouvant être améliorées/simplifiées.

En vous remerciant.

Voici mon programme :

#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Wire.h>


#define LiquidCrystal_I2c_ADRESS 0x3F
#define DS1307_I2C_ADDRESS 0x68
#define LCD_WIDTH 16
#define LCD_HEIGHT 2


#define ARRAYSTEP 15
#define WHITE_LED 11
#define BLUE_LED 5


char lcdbuf[LCD_WIDTH];
char lcdbufb[LCD_WIDTH];


int DsHour , DsMin , DsSec;

//LiquidCrystal_I2C lcd(0x3F,LCD_WIDTH, LCD_HEIGHT);
LiquidCrystal_I2C lcd(0x3F,LCD_WIDTH, LCD_HEIGHT);

RTC_DS1307 rtc;

int lcdw, lcdwb;

static unsigned long LastTimer ;

byte whiteled[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1h45
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3h45
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5h45
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7h45
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9h45
  13, 13, 26, 26, 38, 38, 51, 51,  //10 - 11h45
  64, 64, 77, 77, 89, 89, 102, 102,  //12 - 13h45
  115, 115, 115, 115, 115, 115, 115, 115,  //14 - 15h45
  115, 115, 115, 115, 115, 115, 102, 102,  //16 - 17h45
  89, 89, 89, 89, 89, 77, 77, 64,  //18 - 19h45
  64, 51, 51, 38, 38 , 26, 26, 13, //20 - 21h45
  13, 0, 0, 0, 0, 0, 0, 0  //22 - 23h45
};



byte blueled[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1h45
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3h45
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5h45
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7h45
  0, 0, 3, 7, 13, 13, 15, 20,  //8 - 9h45
  26, 51, 77, 102, 128, 153, 179, 210,  //10 - 11h45
  217, 217, 217, 230, 230, 230, 230, 230,  //12 - 13h45
  230, 230, 230, 230, 230, 230, 230, 230,  //14 - 15h45
  230, 230, 230, 230, 230, 230, 230, 230,  //16 - 17h45
  230, 217, 217, 217, 210, 191, 179, 153,  //18 - 19h45
  128, 102, 77, 64, 51 , 38, 26,  26, //20 - 21h45
  26, 26, 13, 7, 3, 0, 0, 0  //22 - 23h45
};

void setup(void)
{

  pinMode(WHITE_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);

  Serial.begin(9600);
  Serial.println("Entrée dans Setup()");

  Wire.begin();
  rtc.begin();

  
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  lcd.begin(LCD_WIDTH, LCD_HEIGHT,1);


  if (! rtc.isrunning()) {
    Serial.println("Module RTC non initialisé !");
    //Si le DS1307 ne tourne pas (changement de pile et pas d'alim, montage tout neuf, on le règle avec la date/l'heure de la compilation
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }

  lcd.clear();

  LastTimer  = 0;

}



// renvoie la valeur intermédiaire
byte average( byte *pt1, byte *pt2, int lstep)
{

  byte result;

  float fresult;

  // Les 2 valeurs des indices sont égales donc on ne change rien
  if (*pt1 == *pt2) {
    result = *pt1; // Pas de changement
  }

  // Cas 1 on augmente la luminosité
  else if (*pt1 < *pt2)
    // Calcul de la valeur intermédiaire (cf Tuto)
  { fresult = ((float(*pt2 - *pt1) / 15.0) * float(lstep)) + float(*pt1);
    result = byte(fresult);
  }
  else
    // Cas 2 on diminue la luminosité
  {
    fresult = -((float(*pt1 - *pt2) / 15.0) * float(lstep)) + float(*pt1);
    result = byte(fresult);
  }

  return result;
}

void SetPWMForLed()
{

  int indice, sstep, t1, t2, min_cnt, pwmmod, pwmmodb;

  Serial.println("Entrée SetPWMForLed");

  min_cnt = (DsHour * 60) + DsMin;

  // on calcule l'indice ((heure * 60) + minute) divisé par le pas du tableau
  indice = min_cnt / ARRAYSTEP;
  // Fonction modulo qui donne la partie décimale du calcul ci dessus (donc valeur entre 0 et le pas soit entre 0 et 15)  .
  sstep = min_cnt % ARRAYSTEP;

  t1 = indice;

  // cas où l'indice est le dernier du tableau, le suivant est donc le premier !
  if (t1 == 95) {
    t2 = 0;
  }

  // sinon indice suivant
  else {
    t2 = t1 + 1;
  }


  // on est tombé sur un indice entier (multiple de 1/4h), donc on envoie directement la valeur
  if (sstep == 0)
  {
    pwmmod = whiteled[t1];
    pwmmodb = blueled[t1];
  }
  else
  {
    pwmmod = average(&whiteled[t1], &whiteled[t2], sstep);
    pwmmodb = average(&blueled[t1], &blueled[t2], sstep);
  }


  Serial.print("pwmmod:");
  Serial.println(pwmmod);

  Serial.print("pwmmodb:");
  Serial.println(pwmmodb);
  
  

  analogWrite(WHITE_LED, pwmmod);
  analogWrite(BLUE_LED, pwmmodb);
  
  lcdw = pwmmod;
  lcdwb = pwmmodb;
}

void GetTimeFromRTC()
{
  DateTime now = rtc.now();

  DsHour = now.hour();
  DsMin = now.minute();
  DsSec = now.second();
}


void FlushLCD()
{
  

  lcd.setCursor(0, 0);

  sprintf(lcdbuf, "%.2d:%.2d:%.2d", DsHour, DsMin, DsSec);
  lcd.print(lcdbuf);

  lcd.setCursor(0, 1);

  // Ex: Blanc : 32%
  sprintf(lcdbuf, "Wh: %d%%", lcdw * 100 / 255);
  lcd.print(lcdbuf);

  // BLEU
  sprintf(lcdbufb, "  Bl: %d%%", lcdwb * 100 / 255);
  lcd.print(lcdbufb);

lcd.setCursor(1, 0);

  
}

void loop(void)
{

  GetTimeFromRTC();

  if ( (long)( millis() - LastTimer ) >= 0)
  {
    SetPWMForLed();
    LastTimer += 60000;
  }

  Serial.print("Heure RTC : ");
  Serial.println(lcdbuf);
  Serial.println(lcdbufb);
  

  FlushLCD();


}

Cette ligne de codertc.adjust(DateTime(__DATE__, __TIME__));initialise l’horloge avec la date et heure de dernière compilation de votre sketch.

Voyez vous le message Module RTC non initialisé apparaître au boot ?

Bonjour J-M-L,

Non aucun message de ce genre.
J'ai essayé de changer la batterie de le DS1307, pensant qu'elle était faible, mais pas de changement.
Au tout début de la vie du programme elle n'avançait que de 6 minutes, puis au fil du temps elle prend quelques minutes de plus chaque semaine, j'ai cherché sur internet, et à priori c'est un peu la maladie de cette horloge.

Ah ok - oui si c’est au bout d’un moment c’est normal que cette horloge dérive.

Il faut que votre programme offre un moyen de régler l’heure ou que vous mesuriez la dérive moyenne de la votre et de temps en temps (une fois par jour par exemple) vous mettez l’heure à jour « statistiquement ».

Sinon faut mettre ce composant de côté et passer au DS3231 ou similaire qui ont bcp moins de dérive

La DS3231 j'ai vu qu'elle est assez performante, j'étais justement en train de regarder comment modifier le programme si je place cette horloge....j'ai fait des tests en incluant les librairies de cette horloge, mais du coup j'ai plein de message d'erreur....et comme je ne suis pas programmeur, ça va me donner mal à la tête encore :slight_smile:
Quand j'inclue la librairie "DS3231", elle s'affiche #include <wire.h>

Non ce n'est pas "la maladie" de ce CI. C'est celle des fabricants de modules.
Il faut distinguer le CI du quartz.

Le CI n'est en fait qu'un compteur et il fonctionne parfaitement en foncton de la fréquence qu'on lui applique.
C'est le Quartz qui fixe cette fréquence.
Un quartz bouge avec la température. La fréquence centrale est donnée pour 25°C.
De part et d'autre de cette température la fréquence diminue plus au moins fortement selon la taille du quartz.
Il existe plusieurs façon de tailler un cristal de quartz, bien évidement celle qui donne les coûts de fabrication les plus bas est aussi celle qui donne les variations en température les plus pourries. Quand on achète pas cher il ne faut pas s'attendre à avoir une Rolls.
Il faut aussi prendre en compte un mauvais centrage ou une mauvaise mise en oeuvre du quartz.

Le DS3231 est comme un DS1307, c'est la génération de la fréquence qui change. Plus de quartz mais des Mems gravés sur le silcium en même temps que la puce.
Comme tout est intégré le DS3231 comporte même une compensation en température.
Egalement comme tout est dans le boïtier on échappe dans les modules pas cher au mauvais travail des fabricants de modules.

Pour un usage "basique" la plus part des "bibliothèques" fonctionnent aussi bien avec un DS1307 comme avec un DS3231 vu que l'électronique des "compteurs" est la même.

Le DS3231 ne possède pas les 56 octets de ram du DS1307 ( il faut passer au DS3232 qui en contient beaucoup plus que 56), par contre il possède deux alarmes.
C'est dans ce cas qu'il faut obligatoirement changer de "Bibliothèque"

Ok, merci de la précision technique 68tjs, donc, comme mon horloge est dans le même boitier fermé que ma carte arduino, il se peut que la T° monte au-delà des 25°C que vous évoquez d'où son fonctionnement perturbé, si je ventile l'intérieur du boitier, ça "pourrait" être un début de solution....

Je vais quand même mesurer la dérive de mon horloge sur plusieurs jours comme me l'a dit J-M-L avant de me lancer dans des modification de mon système

Ce qu'il faut bien voir c'est qu'à 20°C ou à 30°C la fréquence du quartz ralentie par raaport à 25 °C indépendement de toutes les autres causes comme des perturbations d'alimentation qui ne sont pas anodines.

Le DS3231, même prix que le 1307 : environ 1 €, est compensé en température.
Faut l'effort de télécharger sa datasheet et tu y verra une courbe très claire qui montre la différence entre les deux modèles.

Je te conseille d'approvisionner des ds3231.

Merci pepe
Même si je dois t'avouer que je ne suis pas sûr de pouvoir ressortir un jour dans une conversation ce que tu viens de me dire, ça m'aide à comprendre un petit peu plus l'origine de mon problème, avoir des gens comme toi qui maîtrisent parfaitement des choses aussi pointues est très enrichissant.

Bref, le problème en question est donc bien la qualité de mon horloge si je résume bien.

Effectivement, étant donné que c'est mon tout premier montage à base d'Arduino, j'ai fait le choix de ne pas investir de grosses sommes dans le matériel de peur de tout griller à la première mise en service.
Mais, maintenant que je sais que mon montage et mon programme tiennent la route, je vais pourvoir en commander d'une gamme supérieure (genre de l'officiel Arduino) = exit Aliexpress :smiley: :smiley: :smiley:

Bonjour a tous,
Ludo32100, j'ai devant moi une carte "Aliexpress" avec un DS3231 qui affiche l'heure sur un display OLED.
Mise a l'heure le 16 mars 2018.
Comparaison avec une horloge "internet" placee juste a cote, les 2 horloges sont, ce jour, dans la meme seconde.
Precision absolument ahurissante.
Cette carte coute moins de 1€ frais de port gratuit
Merci Aliexpress
Jacques

Un module à base de DS3231 est extrêmement simple à concevoir, attendu qu'il ne requiert aucun composant critique, en particulier pas d'oscillateur.
L'oscillateur est intégré à la puce et il est compensé en température. Le résultat est garanti.

Tu peux acheter ce genre de module où tu veux les yeux fermés, y compris sur AliExpress.

@+

Quant à ton module DS1307 les performances des "modules ds1307" ne peuvent pas expliquer la dérive : je n'y crois pas.

Par contre je crois plus volontiers à des erreurs de manipulation involontaires, certes, mais bien réelles qui ont pu faire "souffrir l'électronique".
Ce que je peut te conseiller c'est d'acheter en double ( à 1 € pièces tu ne te ruinera pas) et de faire tout le développement avec un jeu de composant. Pour le montage définitif tu prend le deuxième jeu qui sera encore tout neuf.

Ce n'est pas en payant plus cher que tu aura l'assurance d'avoir de la meilleure qualité.
Quasiment tout est fabriqué au même endroit et on peut trouver des sites d'enchères sur Ebay (généralement chez les grands bretons) qui vendent 20 ou 40 € un module vendus 3€ par 99,999% des vendeurs--> ce n'est pas une blague je l'ai constaté et pas qu'une fois en ce qui concerne les breixiteurs.
A ce niveau cela s'appelle de l'escroquerie.