[Résolu] Librairie DS1307 pour IDE Arduino 1.01

Bonjour,

Sur mon (futur) système de domotique que je développe progressivement, j'ai fait fonctionner un certain nombre de choses, sur une arduino Mega 2560 :

  • afficheur LCD 4x16 caractères
  • capteur de température OneWire DS18B20
  • RTC DS1307
  • expander I2C8574

Tout fonctionne très bien avec l'IDE 023

Avant de continuer, je veux passer le programme en .ino pour l'IDE 1.01
J'ai réussi pour l'affichage LCD, et pour le capteur OneWire
Mais je n'arrive pas à trouver une librairie qui fonctionne pour l'horloge DS1307

J'ai essayé les deux librairies :

Mais rien n'y fait:

J'ai chaque fois une erreur de compilation à la ligne :
RTC.get(rtc,true);

Est ce que quelqu'un a déjà rencontré ce problème ?
Avez-vous trouvé une solution ?

Merci pour votre aide.
Bien à vous tous.

Sans libraire Ds1307, ici :

http://www.glacialwanderer.com/hobbyrobotics/?p=12

Si les exemples sont en PDE c'est qu'ils ont été écrits pour une version d'Arduino pre-1.0

Il y a eu de nombreux changements d'API entre la dernière 0023 et la 1.0 donc il est possible que cela impacte les libs et les exemples.

Il y a donc un petit travail de mise à jour a faire.

Merci Jean-François,

J'avais vu que skywodd a fait un tuto du même tonneau que celui que tu proposes sans librairie, j'ai envisagé de réécrire effectivement mon programme en ce sens, mais avant et pour gagner du temps (mais c'est vrai que j'en ai déjà perdu pas mal), je voulais voir s'il n'y avait pas une librairie "compatible" existante.

Encore merci, je sais maintenant ce qu'il me reste à faire, mais comme je ne sais pas trop comment créer des .h (c'est bien au delà de mes compétences actuelles), je vais avoir un programme très volumineux (donc pas très lisible) => enfin je vais essayer de faire au mieux et au moins je progresserai sûrement en C.

@+

barbudor:
Si les exemples sont en PDE c'est qu'ils ont été écrits pour une version d'Arduino pre-1.0

Ce qui est étonnant c'est que ces deux librairies sont données pour fonctionner en 1.0

barbudor:
Il y a eu de nombreux changements d'API entre la dernière 0023 et la 1.0 donc il est possible que cela impacte les libs et les exemples.

Il y a donc un petit travail de mise à jour a faire.

Je ne sais pas en quoi consiste ce petit travail (pour l'instant je suis trop léger en C).

Bonjour,

Voici un exemple minimum de lecture de la date/heure sur DS1307 sans lib autre que Wire.h
Cet exemple fonctionne sur Arduino 1.0.1
Je ne sais plus où je l'avais trouvé :roll_eyes:
Il y a quelques liens intéressants à partir de SparkFun Real Time Clock Module - BOB-12708 - SparkFun Electronics

Tu constateras que la partie 'comestible' de l'exemple est assez petite et peut donc être facilement intégrée à ton code. De plus, avec cette méthode (valable pour tout programme) tu peux élaguer et gagner de la ram et du cpu en ne traitant pas les infos inutiles à ton projet (exemple: secondes, mois et année pour un système domotique) :*
(le mettre en lib ne réduirait pas la taille du binaire final généré)

#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);
}

void loop(){
  printDate();
  delay(1000);
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void printDate(){

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print the date EG   3/1/11 23:59:59
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

}

L'exemple se contente d'afficher la date et heure au format A/M/J H:M:S dans la fenêtre du terminal, sans 'zéro fill'

Note: dans certains cas, la platine contenant le DS1307 n'est pas initialisée bien que la doc dise le contraire et que la pile soit OK. Dans ce cas, l'exemple donnera 0/0/0 0:0:0. Il suffit de chercher un exemple pour la mise à l'heure.

:wink:

@Marc56

Merci beaucoup, c'est exactement ce qu'il me fallait !
J'avais trouvé des exemples, mais l'utilisation d'éléments trop complexes pour moi (pointeurs ou structures) rendait la compréhension très difficile pour le débutant en C que je suis, là c'est bien plus accessible !

Je vais essayer cela ce soir.

Encore merci.

@+

Bonjour à toi,

Pour mon projet (horloge Pong) j'utilise une librairie qui est compatible avec l'arduino 1.xx

Par-contre je ne retrouve plus le liens d'origine. :~
Je te le met dans la journée lorsque je l'aurai retrouvé.

La voici :

DS1307.cpp

/*
 *
 ********************************************************************************************************
 * 			DS1307.cpp 	 library for DS1307 I2C rtc clock				*
 ********************************************************************************************************
 *
 * Created by D. Sjunnesson 1scale1.com d.sjunnesson (at) 1scale1.com
 * Modified by bricofoy - bricofoy (at) free.fr
 *
 * Created with combined information from
 *  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1180908809
 *  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1191209057
 *
 * Big credit to  mattt (please contact me for a more correct name...) from the Arduino forum
 * which has written the main part of the library which I have modified
 *
 * Rev history :
 *
 * ??-??-??	- mattt & dsjunnesson 	- creation
 * 19-feb-2012	- bricofoy 		- added arduino 1.0 compatibility
 * 20-feb-2012	- bricofoy 		- bugfix : time was not preserved when setting or stopping clock
 * 21-feb-2012	- bricofoy 		- bugfix : preserve existing seconds when starting/stopping clock
 *
 *TODO: enable AM/PM
 *	enable square wave output
 *
 */
#include "DS1307.h"

DS1307::DS1307()
{
  Wire.begin();
}

DS1307 RTC=DS1307();

// PRIVATE FUNCTIONS

// Aquire data from the RTC chip in BCD format
// refresh the buffer
void DS1307::read(void)
{
  // use the Wire lib to connect to the rtc
  // reset the register pointer to zero
  Wire.beginTransmission(DS1307_CTRL_ID);

  #if defined(ARDUINO) && ARDUINO >= 100
  Wire.write((byte)0x00);//workaround for issue #527
  #else
  Wire.send(0x00);
  #endif

  Wire.endTransmission();

  // request the 7 bytes of data    (secs, min, hr, dow, date. mth, yr)
  Wire.requestFrom(DS1307_CTRL_ID, 7);
  for(int i=0; i<7; i++)
  {
    // store data in raw bcd format
    #if defined(ARDUINO) && ARDUINO >= 100
    rtc_bcd[i]=Wire.read();
    #else
    rtc_bcd[i]=Wire.receive();
    #endif
  }
}

// update the data on the IC from the bcd formatted data in the buffer
void DS1307::save(void)
{
  Wire.beginTransmission(DS1307_CTRL_ID);

  #if defined(ARDUINO) && ARDUINO >= 100
  Wire.write((byte)0x00);// reset register pointer
  #else
  Wire.send(0x00);
  #endif

  for(int i=0; i<7; i++)
  {
    #if defined(ARDUINO) && ARDUINO >= 100
    Wire.write(rtc_bcd[i]);
    #else
    Wire.send(rtc_bcd[i]);
    #endif
  }
  Wire.endTransmission();
}


// PUBLIC FUNCTIONS
void DS1307::get(int *rtc, boolean refresh)   // Aquire data from buffer and convert to int, refresh buffer if required
{
  if(refresh) read();
  for(int i=0;i<7;i++)  // cycle through each component, create array of data
  {
    rtc[i]=get(i, 0);
  }
}

int DS1307::get(int c, boolean refresh)  // aquire individual RTC item from buffer, return as int, refresh buffer if required
{
  if(refresh) read();
  int v=-1;
  switch(c)
  {
  case DS1307_SEC:
    v=(10*((rtc_bcd[DS1307_SEC] & DS1307_HI_SEC)>>4))+(rtc_bcd[DS1307_SEC] & DS1307_LO_BCD);
    break;
  case DS1307_MIN:
    v=(10*((rtc_bcd[DS1307_MIN] & DS1307_HI_MIN)>>4))+(rtc_bcd[DS1307_MIN] & DS1307_LO_BCD);
    break;
  case DS1307_HR:
    v=(10*((rtc_bcd[DS1307_HR] & DS1307_HI_HR)>>4))+(rtc_bcd[DS1307_HR] & DS1307_LO_BCD);
    break;
  case DS1307_DOW:
    v=rtc_bcd[DS1307_DOW] & DS1307_LO_DOW;
    break;
  case DS1307_DATE:
    v=rtc_bcd[DS1307_DATE]/16 * 10 +  rtc_bcd[DS1307_DATE] % 16;
    break;
  case DS1307_MTH:
    v=(10*((rtc_bcd[DS1307_MTH] & DS1307_HI_MTH)>>4))+(rtc_bcd[DS1307_MTH] & DS1307_LO_BCD);
    break;
  case DS1307_YR:
    v=2000 + rtc_bcd[DS1307_YR]/16 * 10 + rtc_bcd[DS1307_YR] % 16;
    break;
  } // end switch
  return v;
}

void DS1307::set(int c, int v)  // Update buffer, then update the chip
{
  read(); //first read the buffer to preserve current time when writing modified values, as the function writes all values at the same time
  switch(c)
  {
  case DS1307_SEC:
    if(v<60 && v>-1)
    {
      //preserve existing clock state (running/stopped)
      int state=rtc_bcd[DS1307_SEC] & DS1307_CLOCKHALT;
      rtc_bcd[DS1307_SEC]=state | ((v / 10)<<4) + (v % 10);
    }
    break;
  case DS1307_MIN:
    if(v<60 && v>-1)
    {
      rtc_bcd[DS1307_MIN]=((v / 10)<<4) + (v % 10);
    }
    break;
  case DS1307_HR:
    // TODO : AM/PM  12HR/24HR
    if(v<24 && v>-1)
    {
      rtc_bcd[DS1307_HR]=((v / 10)<<4) + (v % 10);
    }
    break;
  case DS1307_DOW:
    if(v<8 && v>-1)
    {
      rtc_bcd[DS1307_DOW]=v;
    }
    break;
  case DS1307_DATE:
    if(v<32 && v>-1)
    {
      rtc_bcd[DS1307_DATE]=((v / 10)<<4) + (v % 10);
    }
    break;
  case DS1307_MTH:
    if(v<13 && v>-1)
    {
      rtc_bcd[DS1307_MTH]=((v / 10)<<4) + (v % 10);
    }
    break;
  case DS1307_YR:
    if(v<50 && v>-1)
    {
      rtc_bcd[DS1307_YR]=((v / 10)<<4) + (v % 10);
    }
    break;
  } // end switch
  save();
}

void DS1307::stop(void)
{
  // set the ClockHalt bit high to stop the rtc
  // this bit is part of the seconds byte
  read(); 	//refresh buffer first to preserve existing time
  rtc_bcd[DS1307_SEC]=rtc_bcd[DS1307_SEC] | DS1307_CLOCKHALT; //set the halt bit in the seconds value
  save(); //write register to the chip
}

void DS1307::start(void)
{
  // unset the ClockHalt bit to start the rtc
  read();				 //refresh buffer to get existing time
  rtc_bcd[DS1307_SEC]-=DS1307_CLOCKHALT; //unset the halt bit in the seconds value
  save(); //write register to the chip
}

DS1307.h

/*
 *
 ********************************************************************************************************
 * 			DS1307.h 	 library for DS1307 I2C rtc clock				*
 ********************************************************************************************************
 *
 * Created by D. Sjunnesson 1scale1.com d.sjunnesson (at) 1scale1.com
 * Modified by bricofoy - bricofoy (at) free.fr
 *
 * Created with combined information from
 *  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1180908809
 *  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1191209057
 *
 * Big credit to  mattt (please contact me for a more correct name...) from the Arduino forum
 * which has written the main part of the library which I have modified
 *
 * Rev history :
 *
 * ??-??-??	- mattt & dsjunnesson 	- creation
 * 19-feb-2012	- bricofoy 		- added arduino 1.0 compatibility
 * 20-feb-2012	- bricofoy 		- bugfix : time was not preserved when setting or stopping clock
 * 21-feb-2012	- bricofoy 		- bugfix : preserve existing seconds when starting/stopping clock
 *
 *TODO: enable AM/PM
 *	enable square wave output
 *
 */


// ensure this library description is only included once
#ifndef DS1307_h
#define DS1307_h

// include types & constants of Wiring core API
// this "if" is for compatibility with both arduino 1.0 and previous versions
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

// include types & constants of Wire ic2 lib
#include <../Wire/Wire.h>

#define DS1307_SEC 0
#define DS1307_MIN 1
#define DS1307_HR 2
#define DS1307_DOW 3
#define DS1307_DATE 4
#define DS1307_MTH 5
#define DS1307_YR 6

#define DS1307_BASE_YR 2000

#define DS1307_CTRL_ID B1101000  //DS1307

 // Define register bit masks
#define DS1307_CLOCKHALT B10000000

#define DS1307_LO_BCD  B00001111
#define DS1307_HI_BCD  B11110000

#define DS1307_HI_SEC  B01110000
#define DS1307_HI_MIN  B01110000
#define DS1307_HI_HR   B00110000
#define DS1307_LO_DOW  B00000111
#define DS1307_HI_DATE B00110000
#define DS1307_HI_MTH  B00110000
#define DS1307_HI_YR   B11110000

// library interface description
class DS1307
{
  // user-accessible "public" interface
  public:
    DS1307();
    void get(int *, boolean);
    int get(int, boolean);
    void set(int, int);
    void start(void);
    void stop(void);

  // library-accessible "private" interface
  private:
    byte rtc_bcd[7]; // used prior to read/set ds1307 registers;
    void read(void);
    void save(void);
};

extern DS1307 RTC;

#endif

Merci beaucoup DizHell,

C'est super, aurais-tu un exemple simple de mise en œuvre.
Je sais, je suis pénible et exigent !

Mais comme j'ai du mal, avec les appels de fonctions, les passages de paramètres, ... (et si ce n'était que ça !), je prends les exemples de mise en œuvre et j'essaye de comprendre, (et des fois même j'y arrive !).

@+

Bonjour,
Pour mon horloge j'utilise la lib RTClib: https://github.com/adafruit/RTClib
Avec le module breakout board DC1307 d'Adafruit.
C'est très simple à mettre en oeuvre et ça mache impec.
Y'a un tutoriel ici:
DS1307 RTC tutorial

Merci patg_

As-tu essayer de la faire fonctionner avec l'IDE 1.0x ?

@+

Brisebee:
Merci beaucoup DizHell,
C'est super, aurais-tu un exemple simple de mise en œuvre.

ok je vais essayer :

#include <DS1307.h>

int hours=0;
int mins=0;
int sec=0;
int date=0;
int mois=0;
int annee=0;
int jour=0;

void setup() {

// Mise à jour de l'heure
// utilisation d'une heure bidon pour test
  RTC.stop(); // Arret du module RTC pour mise à jour des registre interne !!! important, il faut toujours arréter le RTC avant une mise à jour de l'heure.
   RTC.set(DS1307_SEC,1); //Réglage des secondes
   RTC.set(DS1307_MIN,57); //Réglage des minutes
   RTC.set(DS1307_HR,17); //Réglage des heures
   RTC.set(DS1307_DOW,2); //Réglage du jour de la semaine (Valeur qui va de 1 à 7)
   RTC.set(DS1307_DATE,18); //Réglage de la date
   RTC.set(DS1307_MTH,1); //Réglage du mois
   RTC.set(DS1307_YR,10); //Réglage de l'année (ici 2010)
   RTC.start(); //Re-mise en marche du module RTC

}
loop() {

// Récupération des valeur dans le RTC
hours = RTC.get(DS1307_HR,true); //récupère l'heure, le true dans la fonction sert à dire au RTC de se mettre à jour son registre, afin de récupéré les dernières valeurs.
  mins = RTC.get(DS1307_MIN,false); // ici on récupère les minutes, et l'on met false afin de ne pas forcer sur le RTC les actualisations.
  sec = RTC.get(DS1307_SEC,false); // idem pour les secondes
  date = RTC.get(DS1307_DATE,false); // ect....
  mois = RTC.get(DS1307_MTH,false);
  annee = RTC.get(DS1307_YR,false);
  jour = RTC.get(DS1307_DOW,false);

// par la suite les valeurs hours, mins,sec.... seront à jour avec l'heure actuel à toi d'utilisé au mieux ces données. via SERIAL par exemple pour les affiché sur le terminal
}

Voilà en espérant que cela t'aide. Pour info L'objet RTC est creer directement dans la librairie fournit plus haut.

Désolé pour le coté brouillon je viens de tapé tout ce code spécialement pour toi.

Comme patg_ j'utilise la bibliothèque RTClib d'Adafruit, elle fonctionne sans problème avec Arduino 1.0.x :wink:

++

DizHell:
je viens de tapé tout ce code spécialement pour toi.

Mille fois merci.

Je vais le tester ce soir.

Merci à tous pour votre aide précieuse.

J'ai testé la librairie RTClib d'Adafruit => elle fonctionne très bien avec l'IDE 1.01 et elle est simple à mettre en oeuvre.
Cependant les jours de le semaine ne sont pas utilisables, je pense qu'il faudrait modifier la librairie, mais c'est au dessus de mes moyens actuels.

J'ai donc utilisé la librairie et le bout de programme fourni dans ce topic par DizHell => J'ai réussi à faire ce que je voulais.

Il me reste encore un autre problème avec la superbe librairie PCF8574 du Skywood, mais je vais ouvrir un nouveau topic sur le sujet.

Encore merci à tous !

Que serai-je sans vous ! => En galère grave comme diraient mes enfants.

Brisebee:
J'ai testé la librairie RTClib d'Adafruit => elle fonctionne très bien avec l'IDE 1.01 et elle est simple à mettre en oeuvre.
Cependant les jours de le semaine ne sont pas utilisables, je pense qu'il faudrait modifier la librairie, mais c'est au dessus de mes moyens actuels.

C'est quoi exactement le probléme ?

Si tu arrive a avoir le bug à chaque fois avec une morceau (basique) de code, tu peut le signaler sur le github de adafruit pour qu'ils corrigent le bug :wink:

skywodd:
C'est quoi exactement le probléme ?

Je ne pense pas qu'il s'agisse réellement d'un bug, le jour de la semaine (lundi, mardi,...) en fait le 3ème octet en RAM du RTC, qui contient DAY (de 1à7) n'est pas géré par la librairie, certainement que le dévéloppeur de la librairie n'en a pas eu besoin.

Mais pour mon projet domotique je veux gérer des plages horaires qui seront différentes selon les jours de la semaine, j'avais besoin de cette donnée, c'est pourquoi, je vais utiliser une autre librairie.

@+

Brisebee:
Je ne pense pas qu'il s'agisse réellement d'un bug, le jour de la semaine (lundi, mardi,...) en fait le 3ème octet en RAM du RTC, qui contient DAY (de 1à7) n'est pas géré par la librairie, certainement que le dévéloppeur de la librairie n'en a pas eu besoin.

Mais pour mon projet domotique je veux gérer des plages horaires qui seront différentes selon les jours de la semaine, j'avais besoin de cette donnée, c'est pourquoi, je vais utiliser une autre librairie.

Je sait pas quelle version tu as exactement mais la version la plus récente sur le github de adafruit :

Contient une fonction dayOfWeek() qui retourne le jour de la semaine.
(Bon ok en fait c'est un calcul en fonction de l'année du mois et du jour, ça n'utilise pas le champ DayOfWeek du DS1307 mais bon ça marche.)

skywodd:
Contient une fonction dayOfWeek() qui retourne le jour de la semaine.
(Bon ok en fait c'est un calcul en fonction de l'année du mois et du jour, ça n'utilise pas le champ DayOfWeek du DS1307 mais bon ça marche.)

Je n'ai pas vu qu'il y avait cette fonction, et comme j'ai vu que le champ DayOfWeek du DS 1307 n'était pas exploité, j'en ai conclu trop hativement que cette donnée n'était pas disponible.

Merci pour cette précision.

Brisebee:

skywodd:
Contient une fonction dayOfWeek() qui retourne le jour de la semaine.
(Bon ok en fait c'est un calcul en fonction de l'année du mois et du jour, ça n'utilise pas le champ DayOfWeek du DS1307 mais bon ça marche.)

Je n'ai pas vu qu'il y avait cette fonction, et comme j'ai vu que le champ DayOfWeek du DS 1307 n'était pas exploité, j'en ai conclu trop hativement que cette donnée n'était pas disponible.

Merci pour cette précision.

bonsoir
En fait le champ "day week" du ds1307 (O3H) est initialisable avec n'importe quelle valeur (1-->7)
il est simplement incrementé par passage à 00:00 de l'horloge, mais n'a pas d'existence/correspondance definie :
selon les endroits du monde le jour 1 de la semaine n'est pas le même pour tous.
Le code de la lady ne fait qu'attribuer par soft une "référence" par dérivation convenue .