Comme indiqué précédemment dans un autre topic, voici un petit tuto pour mettre votre ds1307 à l'heure NTP (network time protocol).
Il subsiste une petite latence de quelques dixièmes de secondes, mais pour du NTP c'est correct :D.
J'ai utilisé ce schéma pour monter ma puce RTC sur une plaque de prototypage (pas de pcb laser pour cette fois :D).
Ce qui a donné cela :
Un quartz de 32.768kHz doit être monté sur les broches 1 et 2, pas besoins de condensateur (dixit le constructeur).
La pile est de 3V.
Le code Arduino n'utilise pas de librairie ds1307, je trouvais plus intéressant d'utiliser une partie de ce code ( source).
J'ai ajouté la partie qui demande à Processing d'envoyer une chaine indiquant l'heure de l'ordinateur hôte.
Le code est commenté pour Arduino et Processing.
Une petite vidéo qui explique la procédure :
Le code coté Arduino :
/*
Permet de mettre une horloge ds1307 en synchronisation avec l'heure NTP
Par le biais d'une application Arduino-Processing
*/
/*
Comporte des parties de code écrites par :
- Maurice Ribble
4-17-2008
http://www.glacialwanderer.com/hobbyrobotics
Pour le ds1307
- X. HINAULT
01/2010
http://www.mon-club-elec.fr
Pour le LCD
*/
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(0x80);
Wire.endTransmission();
}*/
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(
byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.receive() & 0x7f);
*minute = bcdToDec(Wire.receive());
*hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month = bcdToDec(Wire.receive());
*year = bcdToDec(Wire.receive());
}
#include <LiquidCrystal.h>
const int RS=2; //declaration constante de broche
const int E=3; //declaration constante de broche
const int D4=4; //declaration constante de broche
const int D5=5; //declaration constante de broche
const int D6=6; //declaration constante de broche
const int D7=7; //declaration constante de broche
LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
int octetReception=0; // variable de stockage des valeurs reçues sur le port Série (ASCII)
char caractereRecu=0; // variable pour stockage caractère recu
int compt=0; // variable comptage caractères reçus
String chaineReception=""; // déclare un objet String vide pour reception chaine
int oldSecond;
void setup() {
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin(); // initialise 1wire
Serial.begin(115200); // Initialise la communication série
// lit les valeurs de l'horloge pour les replacer si elle est déjà à l'heure
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
if ((year)== NULL){ // si l'année = NULL
// preinitialise l'horloge mets les valeurs lue précédement (à 0 si premier allumage)
setDateDs1307(int(second), int(minute), int(hour), int(dayOfWeek), int(dayOfMonth), int(month), int(year));
}
//***** LCD *****//
lcd.begin(20,4); // Initialise le LCD avec 20 colonnes x 4 lignes
delay(10); // pause rapide pour laisser temps initialisation
lcd.print("initialisation") ; // affiche la chaîne texte - message de test
lcd.setCursor(0, 1) ;
lcd.print("de l'horloge") ;
delay(2000); // pause de 2 secondes
lcd.clear(); // // efface écran et met le curseur en haut à gauche
delay(100); // pour laisser temps effacer écran
//**** liaison pour l'heure NTP ****//
Serial.println('A'); // envoi un "top" à Processing
while (millis()<5000) { // attente pendant 5 secondes d'une liaison série (ne fonctionne pas en dessous)
while (Serial.available()>0) { // tant qu'un octet est dans la liaison série
octetReception=Serial.read(); // Lit le 1er octet reçu et le met dans la variable
if (octetReception==13) { // si l'octet reçu est le retour chariot (CR ou 13)
// converti la chaine en entier pour les valeurs de temps
second = int((chaineReception.charAt(0)-48)*10)+int(chaineReception.charAt(1)-48) ;
minute = int((chaineReception.charAt(2)-48)*10)+int(chaineReception.charAt(3)-48);
hour = int((chaineReception.charAt(4)-48)*10)+int(chaineReception.charAt(5)-48);
dayOfWeek = 1;
dayOfMonth = int((chaineReception.charAt(6)-48)*10)+int(chaineReception.charAt(7)-48);
month = int((chaineReception.charAt(8)-48)*10)+int(chaineReception.charAt(9)-48);
year = int((chaineReception.charAt(12)-48)*10)+int(chaineReception.charAt(13)-48); //int((chaineReception.charAt(10)-48)*1000)+int((chaineReception.charAt(11)-48)*100)+
//mets le DS1307 en syncronisation avec l'horloge de l'ordinateur
setDateDs1307(int(second), int(minute), int(hour), int(dayOfWeek), int(dayOfMonth), int(month), int(year));
chaineReception=""; //RAZ de la chaine de réception
break; // sort de la boucle while
}
else { // si le caractère reçu n'est pas un saut de ligne
caractereRecu=char(octetReception); // convertit l'octet reçu en caractère
chaineReception=chaineReception+caractereRecu; // ajoute le caratère à la chaine
}
}
}
}
void loop(){
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
if(second!=oldSecond){ // change l'affichage uniquement au changement de seconde
Serial.print(hour, DEC);
Serial.print(":");
Serial.print(minute, DEC);
Serial.print(":");
Serial.print(second, DEC);
Serial.print(" ");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.print(" Day_of_week:");
Serial.println(dayOfWeek, DEC);
lcd.home();
if (int(hour)<=9)lcd.print(0);
lcd.print(int(hour));
lcd.print (":");
if (int(minute)<=9)lcd.print(0);
lcd.print(int(minute));
lcd.print (":");
if (int(second)<=9)lcd.print(0);
lcd.print(int(second));
lcd.setCursor (0,1);
if (int(dayOfMonth)<=9)lcd.print(0);
lcd.print(int(dayOfMonth));
lcd.print ("/");
if (int(month)<=9)lcd.print(0);
lcd.print(int(month));
lcd.print ("/20");
lcd.print(int(year));
}
oldSecond=second; // réinitialise oldSecond
}