↵ Horloge temps réel DS1307 + picaxe + LCD série
Il est parfois utile dans une application de disposer d'une horloge temps réel.
Cahier des charges:
Afficher sur un LCD la date et l'heure en temps réel.
Option 1: Sélection des paramètres d'initialisation par potentiomètre.
Option 2: Sélection des données par poussoir.
Remarque: La date donnée par le DS1307 est juste, à condition que l'initialisation soit cohérente. Un 30 février ou un 31 avril est accepté. De même, le jour de la semaine n'est pas calculé. Toute erreur conduit à une date incohérente.
La version poussoir interdit l'introduction de date farfelue (au prix d'un code plus touffu). Mais c'est pour le fun, on est pas non plus obligé de faire n'importe quoi.
Voilà déjà le schéma, potentiomètre ou poussoir, au choix.
Une erreur sur ce shéma: il n'y a pas de résistance de 10k en série avec le potentiomètre.
C'est un circuit horloge, fabriqué par Maxim avec liaison par bus I2C .
Adresse %11010000
Cadensé par quartz et sauvegardé par batterie lithium (10 ans).
Le calendrier couvre la période 2000 à 2100
Les données sont enregistrées dans 7 registres au format BCD, dans l'ordre
secondes,minutes,heures, j de sem,jour,mois, année (ss,mm,hh,JS,JJ,MM,YY)
Ex: pour initialiser le DS1307, à la date du 25 décembre 2012 à 23h 15,
(c'est un mardi, jour 3 de la semaine) nous utiliserons la commande suivante:
hi2cout 0, ($00,$15,$23,$03,$25,$12,$12,%00010000)
Et pourquoi les $ ? Explication:
Chaque registre est composé d'un octet et reçoit 2 chiffres et chaque chiffre est codé sur 4 bits.
Le premier chiffre va dans les 4 premiers bits de l'octet, le second chiffre dans les 4 derniers bits. C'est le codage BCD (décimal codé binaire)
Ex pour 29:
2 = %0010
9 = %1001
en BCD, 29 = % 0010 1001 ce qui est bien 29 en hexadécimal et donc noté $29
En décimal, $29 = 41
Donc, envoyer dans un registre %00101001 ou $29 ou 41, c'est pareil, ce n'est qu'une notation différente du même octet.
Le premier registre des secondes est à 0 pour partir sur une minute entière
Le dernier octet est un registre de contrôle et règle en particulier la sortie 1 Hz sur la sortie SQ.
Il faut introduire "manuellement" le bon jour de la semaine correspondant à la date. Pour limiter les erreurs, il sera calculé avec l'algorithme de Mike Keith (il a déclaré lui même que c'était le plus court et le meilleur), à partir du jour, du mois et de l'année.
Le choix minimaliste du picaxe 08M2 est juste suffisant pour remplir toutes les fonctions: lecture du DS1307, réglage initial des registres et affichage sur LCD série (voir cette page). Le réglage des données utilise un potentiomètre sur une entrée ADC ou un poussoir et occupe le dernier port.
Dans cette vidéo de démo de la version poussoir, on voit que l'on peut cliquer n'importe comment mais ça ne donne pas n'importe quoi. (en regardant la vidéo, j'ai vu les heures monter à 24 !...C'est corrigé, maintenant c'est 23 max).
Pour limiter les possibilités aux seules dates cohérentes, il faut introduire la date dans l'ordre: année, mois, jour.
- L'année pour calculer les années bissextiles.
- Le mois pour calculer le nombres de jours max (28,29,30,31).
- Le jour, en calculant le chiffre mini et maxi des dizaines et des unités (pas de 00 pour le mois et le jour).
- Il faut l'année, le mois et le jour pour calculer le jour de la semaine avec l'algorithme.
Le choix des chiffres est limité au stricte nécessaire
On trouve facilement sur eBay des modules complets, avec quartz et batterie (là, il faut bien lire si elle est fournie ou non) pour 1 euro (oui, 1 euros !, port gratuit !).
MAIS ATTENTION: Remarque valable pour les modules DS1307 ou DS3132 (à 1 euro aussi).
Ces modules comportent un circuit de charge destiné à la recharge d'une batterie LIR2032
Pour ce prix, plusieurs cas possibles:
- La batterie n'est pas fournie avec le module (et c'est dommage)
- La batterie est fournie, bien lire les caractéristiques détaillées pour s'en assurer
- La batterie LIR2032 est remplacée par une pile CR2032, les détails mentionnent parfois "une pile rechargeable CR2032" et il est conseillé de couper le circuit de charge,
Conclusion : faire attention à ce que l'on achète
| |
Le module commandé sur ebay 1,86 € port gratuit reçu en 15 jours | Pile comprise, avec une EEPROM A si, le connecteur a été ajouté.. |
Le schéma correspondant (trouvé sur internet):
Remarques:
- Les modules reçus sont conformes au schéma (oui "les modules", j'ai vu une offre avec un module marqué "designed by Newman" pour voir. J'ai vu, vendu plus de 4 euros, non marqué, c'est exactement le même !).
- Les résistances de pull up de la liaison I2C sont cablées sur le module.
- La batterie LIR 2032 (3,6v) est rechargeable et rechargée par D1, R5 donc, il faut en tenir compte si vous recevez un modèle sans batterie (ce qui serait dommage).
- L'emplacement pour un capteur thermique DS18B20 est là, avec la broche DS, mais pas le capteur (Ah, les radins!).
- l'EEPROM AT24C32 a les pattes A0,A1,A2 reliées au 0v. L'adresse est donc figée à %1010000X, X étant le bit R/W.
Doc de l'EEPROM:
http://www.datasheetcatalog.org/datasheet/atmel/doc0336.pdf
Un petit essai avec ce module:
Pour info, pour moi, les liens vers des vidéos Dailymotion ne fonctionnent plus, pour vous, je sais pas.
Le code du programme "poussoir" :
L'original .bas, (à ouvrir avec l'éditeur Picaxe) est plus présentable.
'########################################
'# Pour PICAXE-08M2 et MAXIM DS1307 RTC #
'# MM 29/12/2012 #
'########################################
' Plage de dates entre 2000 et 2099
' Affichage des données sur LCD série port C.0
Debut:
#picaxe 08m2
SetFreq m8
symbol baud=N4800_8 'liaison série à 4800 bauds 8 Mhz
'***** Nomination des ports *********
symbol increm = pinC.4 'poussoir incrémentation
symbol valid = pinC.3 'poussoir validation
'***** Nomination des variables type byte ***********
symbol ch =b1 'chiffre
symbol dch =b2 'chiffre diz
symbol col =b3 'n° colonne
symbol minch =b4 'chiffre mini
symbol maxch =b5 'chiffre maxi
symbol varb =b6 'temporaire byte
symbol jour =b7
symbol mois =b8
symbol heure =b9
symbol minut =b10
symbol second =b11
'***** Nomination des variables type word **********
symbol joursem =w11
symbol varw =w12 'temporaire word
symbol an =w13
'******************************************
pause 2000 'temps initialisation LCD
' Initialisation DS1307
'%11010000 est l'adresse i2c
i2cslave %11010000, i2cslow, i2cbyte
Do 'boucle principale
if valid=1 then gosub init
hi2cin 3,(varb) ' jour de semaine lu dans le registre 3
bcdtoascii varb,dch,ch ' DS1307 les données sont au format BCD
serout C.0,baud,(254,128)
if ch="1" then serout C.0,baud,(" Dim ") 'affichage du jour de la semaine
elseif ch="2" then serout C.0,baud,(" Lun ")
elseif ch="3" then serout C.0,baud,(" Mar ")
elseif ch="4" then serout C.0,baud,(" Mer ")
elseif ch="5" then serout C.0,baud,(" Jeu ")
elseif ch="6" then serout C.0,baud,(" Ven ")
elseif ch="7" then serout C.0,baud,(" Sam ")
endif
hi2cin 4,(jour) ' jour lu dans le registre 4
bcdtoascii jour,dch,ch
serout C.0,baud,(dch,ch,"/")
hi2cin 5,(mois) ' mois lu dans le registre 5
bcdtoascii mois,dch,ch
serout C.0,baud,(dch,ch,"/")
hi2cin 6,(an) ' année lu dans le registre 6.
bcdtoascii an,dch,ch
serout C.0,baud,("20",dch,ch," ")
serout C.0,baud,(254,192)
hi2cin 2,(heure) ' heure lu dans le registre 2
bcdtoascii heure,dch,ch
serout C.0,baud,(254,192," ",dch,ch)
hi2cin 1,(minut) ' Minute lu dans le registre 1
bcdtoascii minut,dch,ch
serout C.0,baud,(":",dch,ch)
hi2cin 0,(second) ' Seconde lu dans le registre 0
bcdtoascii second,dch,ch
serout C.0,baud,(":",dch,ch," ")
loop ' fin boucle principale
'******* Initialisation du DS1307 ************************
init:
Do: loop while valid=1 'attente relachement poussoir
serout C.0,baud,(254,1) 'Effacement écran
serout C.0,baud,(254,128,"20aa/MM/jj hh:mm ") 'Modèle du format
'********* an ***************
Do: loop while valid=1 'Attente relachement poussoir
col=194 'Position colonne 1er chiffre
minch=0:maxch=9 'plage possible chiffre dizaire
gosub chiffre 'routine affichage
dch=ch 'mémoire dizaine
col=195 'position 2ème chiffre
gosub chiffre
an=dch*10+ch 'nombre année
'******* mois ********
col=197
minch=0
maxch=1
gosub chiffre
dch=ch
col=198
if dch=0 then
minch=1:maxch=9
else
minch=0:maxch=2
endif
gosub chiffre
mois=dch*10+ch
'****** jour ********
col=200 'chiffre des dizaines
minch=0
if mois=2 then
maxch=2
else maxch=3
endif
gosub chiffre
dch=ch
col=201 'chiffre des unités
if dch=0 then 'si chiffre des dizaines = 0
minch=1 'pas de 00
else minch=0
endif
if mois =2 then 'traitement février
varb=an//4
if varb=0 then 'année bisextile
maxch=9 'max 29
else maxch=8 'sinon 28
endif
endif
if mois<>2 then 'traitement non février
maxch=9
if dch=3 then
if mois=4 or mois=6 or mois=9 or mois=11 then
maxch=0 'mois de 30j
else maxch=1 'sinon 31j
endif
endif
endif
gosub chiffre
jour=dch*10+ch
'******** heure **************
col=203
minch=0
maxch=2
gosub chiffre
dch= ch
col=204
minch=0
maxch=9
if dch=2 then
maxch=3
endif
gosub chiffre
heure=dch*10+ch
'******** minutes **********
col=206
minch=0
maxch=5
gosub chiffre
dch= ch
col=207
minch=0
maxch=9
gosub chiffre
minut=dch*10+ch
'***** calcul joursem ****************
'L'algorithme de Mike Keith numérote de 0 à 6
'Dim=0, Lun=1,...,Sam=6
an= 2000+an
if mois < 3 then
varw=an-1
else varw=an
end if
joursem= 23*mois/9 +jour+4+an
w10=varw/4
joursem=joursem+w10
w10=varw/100
joursem=joursem-w10
w10=varw/400
joursem=joursem+w10
if mois>= 3 then
joursem=joursem-2
endif
joursem=joursem//7+1 '+1 pour numérotation de 1 à 7 idem DS1307
varb=joursem 'mémorisation dans une variable type byte
'***********************************************
dch=minut//10 'Les données sont
minut=minut/10*16 'mises au format BCD
minut=minut+dch 'pour enregistrement
dch=heure//10
heure=heure/10*16
heure=heure+dch
dch=jour//10
jour=jour/10*16
jour=jour+dch
dch=mois//10
mois=mois/10*16
mois=mois+dch
an=an-2000
dch=an//10
an=an/10*16
an=an+dch
hi2cout 0, ($00,minut,heure,varb,jour,mois,an,%00010000)
return
'******* Sous programme affichage et incrémentation ***************
chiffre:
ch=minch
Do
serout C.0,baud,(254,col,#ch)
if increm=1 then
do:loop while increm=1
inc ch
if ch>maxch then
ch=minch
endif
endif
if valid=1 then exit
loop
Do: loop while valid=1
return
A suivre...