Microcontrolerul atmega328 de pe placa de dezvoltare Arduino are un cronometru încorporat denumit millis(), care cu ajutorul unui soft aferen poate fi folosit pe post de ceas. În cazul acesta probabil vă puneţi următoarea întrebare, „Pentru ce mai avem nevoie de un ceas suplimentar?”. Răspunsul este foarte simplu. Folosind un program care să calculeze timpul bazat pe  timer-ul millis() ar însemna ca de fiecare dată când Arduino este resetat sau reprogramat să fim nevoiţi să reintroducem data şi ora curentă. Problema este dată de faptul ca millis() reţine numărul de milisecunde de la pornirea plăcii de dezvoltare, ceea ce înseamnă că la fiecare repornire/reprogramare timerul va fi resetat. Pentru proiecte simple, în care acest lucru nu este un inconvenient, se poate merge pe ideea de a crea un ceas software, dar în cazul în care realizăm un „dataloger”, un ceas cu alarma etc. avem nevoie de o metoda coerentă de a înregistra timpul. În acest caz kitul DS1307 ne vine în ajutor deoarece integratul DS1307 reţine secunda/minut/ora/ziua/luna/anul, ţine cont de anii bisecţi, nu îşi pierde informaţia în momentul în care Arduino rămâne fără alimentare sau este reprogramat.

Necesar
-plăcuţă de dezvoltare Arduino
-bread board
-fire pentru conexiuni
-shield DS1307
-(opţional)shield LCD

Schema electrică
Acest schemă poate fi realizată în două moduri. În cazul în care deţineţi un kit ROROID LCD ceasul şi data va fi afişata şi pe display. În caz contrar pentru a citi ora şi data curentă va trebui să folosiți monitorul serial. În ambele cazuri programarea va fi făcută cu ajutorul meniului din monitorul serial. Schema de mai jos explică modul de legare al modulelor de Arduino:

kit_DS1307
Programare

S sau s – setarea datei
Pentru a seta data în monitorul serial se scrie o comanda de forma S(ora)(minut)(secunda)(zi săptămâna)(zi lună)(luna)(anul) cu următoarea structură S(00-23)(00-59)(00-59)(1-7)(01-31)(01-12)(00-99). Astfel dacă vrem să setăm data de 18/08/2012 21:41:00 iar ziua acestei date este sâmbătă comanda va fi următoarea: S2141006180812
C sau c -citirea datei pe serial
Data este afișată pe LCD, dar în cazul în care dorim să citim data pe serial sau nu avem un LCD această comandă este foarte utilă

//Se incarca libraria Wire
#include "Wire.h"
//Se defineste adresa ceasului DS1307 pe bus I2C
#define ADRESA_RTC 0x68

//Se incarca libraria NewCrystalLCD
#include <LiquidCrystal_SR_LCD3.h>

//Se definesc pini de comunicare
const int PIN_LCD_STROBE = 9;//pinul 9 de pe placa Arduino
const int PIN_LCD_DATA = 8;//pinul 8 de pe placa Arduino
const int PIN_LCD_CLOCK = 7;//pinul 7 de pe placa Arduino

//Initializare librarie
LiquidCrystal_SR_LCD3 lcd(PIN_LCD_DATA, PIN_LCD_CLOCK, PIN_LCD_STROBE);

//variabila care retine mesajul afisat pe LCD
String mesaj;

//variabila care retine comanda primita pe serial
int comanda;

//variabila necesara pentru a sti cand afisam data pe serial
int ser=0;

byte secunda, minutul, ora, ziS, ziL, luna, anul;
byte zero;
char *zi[] = {"","Lun","Mar","Mie","Joi","Vin","Sam","Dum",};

byte bcdToDec(byte val) {
// Functia converteste un nr binar in zecimal
return ( (val/16*10) + (val%16) );
}

byte decToBcd(byte val)
{
// inversul functiei bcdToDec
return ( (val/10*16) + (val%10) );
}

void setup(){
//Initializeaza libraria Wire
Wire.begin();
//Initializeaza portul serial
Serial.begin(9600);

lcd.begin(16, 2);//Definim tipul de display folosit
//in cazul nostru 16X2

lcd.print(F("Bine ati venit")); //Tiparim textul

lcd.setCursor (0, 1);//sarim pe linia urmatoare
lcd.print(F("pe www.roroid.ro"));//tiparim textul
zero = 0x00;
}

void loop(){

if (Serial.available()) { // daca se detecteaza
comanda = Serial.read();
if (comanda == 83 || comanda == 115) { //Ex. de comanda folosita pentru setare este
setare_data(); //S1742306180812 - unde 17 este ora;42 este minutul;30 sunt secundele
//6 este ziua din saptamana;18 este ziua din luna;08 este luna;12 este anul
//Daca va grabiti eliminati randurile de mai jos
lcd.clear();
lcd.print("Initializare...");
Serial.println("Initializare...");
delay(1000);
lcd.setCursor(0,0);
lcd.print("Noua data a fost");
lcd.setCursor(0,1);
lcd.print("inregistrata!");
Serial.println("Noua data a fost");
Serial.print("inregistrata!");
delay(2000);
Serial.println(" ");

}
else if (comanda == 67 || comanda == 99) { //cu C sau c se afiseaza data pe portul serial
ser=1;
citeste_data();
Serial.println(" ");
ser=0;
}
}

citeste_data();
delay(1000);
}

//Functia realizeaza citirea datei din DS1307
void citeste_data(){

// Reset the register pointer
Wire.beginTransmission(ADRESA_RTC);

Wire.write(zero);
Wire.endTransmission();

Wire.requestFrom(ADRESA_RTC, 7);

secunda = bcdToDec(Wire.read()&0x7f);
minutul = bcdToDec(Wire.read());
ora = bcdToDec(Wire.read() & 0x3f); //mod 24 ore
ziS = bcdToDec(Wire.read()); //1-7 -> luni - duminica
ziL = bcdToDec(Wire.read());
luna = bcdToDec(Wire.read());
anul = bcdToDec(Wire.read());

mesaj="";
if (ora<10)
{
mesaj=mesaj+"0";
}
mesaj=mesaj+ora;
mesaj=mesaj+":";
if (minutul<10)
{
mesaj=mesaj+"0";
}
mesaj=mesaj+minutul;
mesaj=mesaj+":";
if (secunda<10)
{
mesaj=mesaj+"0";
}
mesaj=mesaj+secunda;
lcd.clear();
lcd.print(mesaj);
if (ser==1){
Serial.println(mesaj);
}
lcd.setCursor (0, 1);//sarim pe linia urmatoare
mesaj="";
mesaj=zi[ziS];
mesaj=mesaj+" ";
if (ziL<10)
{
mesaj=mesaj+"0";
}
mesaj=mesaj+ziL;
mesaj=mesaj+"/";
if (luna<10)
{
mesaj=mesaj+"0";
}
mesaj=mesaj+luna;
mesaj=mesaj+"/20";
mesaj=mesaj+anul;
lcd.print(mesaj);
if (ser==1){
Serial.println(mesaj);
}
}

void setare_data()
{
//se calculeaza valoarile receptionate pe portul serial
ora = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
minutul = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
secunda = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48));
ziS = (byte) (Serial.read() - 48);
ziL = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
luna = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
anul= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));

//se trimit noile valori pe I2C
Wire.beginTransmission(ADRESA_RTC);
Wire.write(zero);
Wire.write(decToBcd(secunda) & 0x7f);
Wire.write(decToBcd(minutul));
Wire.write(decToBcd(ora));

Wire.write(decToBcd(ziS));
Wire.write(decToBcd(ziL));
Wire.write(decToBcd(luna));
Wire.write(decToBcd(anul));
Wire.endTransmission();
}

Iar la final, rezultatul aplicaţiei:

DS1307_tut

Programul de mai jos este un exemplu de realizare a unei alarme cu ajutorul modulului DS1307.

#include "Wire.h"
//in codul nostru vom folosi timer
#include <Metro.h>

//Se defineste adresa ceasului DS1307 pe bus I2C
#define ADRESA_RTC 0x68
Metro background0 = Metro(5000);

byte secunda, minutul, ora, ziS, ziL, luna, anul;
byte zero;

byte bcdToDec(byte val_n) {
// Functia converteste un nr binar in zecimal
return ( (val_n/16*10) + (val_n%16) );
}

byte decToBcd(byte val_n)
{
// inversul functiei bcdToDec
return ( (val_n/10*16) + (val_n%10) );
}
//Functia realizeaza citirea datei din DS1307
void verifica_ora(){

// Reset the register pointer
Wire.beginTransmission(ADRESA_RTC);

Wire.write(zero);
Wire.endTransmission();

Wire.requestFrom(ADRESA_RTC, 7);

//citeste ceasul
secunda = bcdToDec(Wire.read()&0x7f);
minutul = bcdToDec(Wire.read());
ora = bcdToDec(Wire.read() & 0x3f); //mod 24 ore
ziS = bcdToDec(Wire.read()); //1-7 -> luni - duminica
ziL = bcdToDec(Wire.read());
luna = bcdToDec(Wire.read());
anul = bcdToDec(Wire.read());
//Serial.print(ora); Serial.print(minutul); Serial.println(secunda);
if(ora==21 && minutul==0 && secunda>=0)
{
//alarma de la ora 21
}

else if(ora==7 && minutul==0 && secunda>=0)
{
//alarma de la ora 7
}
//reseteaza timer-ul
background0.reset();
}

void setup()
{
//Initializeaza libraria Wire
Wire.begin();
Serial.begin(9600);
zero = 0x00;
}
void loop()
{
if (background0.check() == 1)
{ // se verifica ora din 5 in 5 secunde. Timpul de verificare poate fi setat si mai mic
verifica_ora();
}

}

Spor la treaba!

Ceas în timp real DS1307
Etichetat pe:            

20 de gânduri despre „Ceas în timp real DS1307

  • 05/01/2014 la 10:39
    Legătură permanentă

    Salut.
    Intrebarea e foarte buna. In momentul cand are cei 5V la Vcc dispozitivul poate fi citit si scris. Cand aceasta tensiune nu exista dispozitivul intra in modul „sleep”. Vezi mai jos textul preluat din data sheet.

    „VCC, GND – DC power is provided to the device on these pins. VCC is the +5V input. When 5V is applied within normal limits, the device is fully accessible and data can be written and read. When a 3V battery is connected to the device and VCC is below 1.25 x VBAT, reads and writes are inhibited. However, the timekeeping function continues unaffected by the lower input voltage. As VCC falls below VBAT the RAM and timekeeper are switched over to the external power supply (nominal 3.0V DC) at VBAT.”

    Răspunde
  • 05/01/2014 la 10:40
    Legătură permanentă

    Am un chip TINY RTC cu memrie cu tot pe el. Nu reusesc sa-l initializez deloc. Afiseaza ore, ani, data aberante. Ce e de facut, va rog?

    Răspunde
  • 05/01/2014 la 10:41
    Legătură permanentă

    PS. Scuze pentru revenire. Am o placa ARDUINO MEGA 2560. M-am conecat cu SCL si SDA unde trebuie. RTC nu merge. Doar afiseaza abeatiil de care am pomenit (anul 2165, luna 65 etc.). Chiar asa aberante, nu o ia din loc (valorile la secunda nu cresc la fiecare secunda si nu transmite cresterea timpului cu o secunda catre serial, pt afi afisata). Multumesc anticipat pt. orice solutie

    Răspunde
  • 05/01/2014 la 10:41
    Legătură permanentă

    Salut,

    Am patit acelasi lucru cand:
    -libraria folosita nu era ok
    -conexiunile nu erau ok
    -alimentarea era 3v in loc de 5
    -erau erori in program

    Sper sa te ajute.

    Răspunde
  • 05/01/2014 la 10:41
    Legătură permanentă

    @lucian Am adaugat un nou cod care seteaza doua alarme
    @adrian Mai adauga la lista de mai sus si initializarea din setup pentru libraria wire Wire.begin();

    Răspunde
  • 12/01/2014 la 22:52
    Legătură permanentă

    Va multumim pentru munca depusa. E minunat suportul tehnic pentru programarea acestor device-uri dar am totusi si o bila neagra pentru d-voastra. Pentru ca aceste tutoriale sunt citite de foarte multi oameni ei au tendinta sa ia de bun si scrisul prezent aici. Va rog sa corectati „v-a” cu „va” pentru simplu motiv ca nu se aplica. fara sa fie o jignire, vrem doar sa fie folosita limba romana corect ( atat ne-a mai ramas ). un link ajutatator http://scri.ro/va-sau-v-a-187.html

    Răspunde
  • 13/01/2014 la 15:17
    Legătură permanentă

    Multumesc pentru atentionare. Nu este nici o jgnire.

    P.S. Recunosc ca am cam chiulit de la orele de LIMBA SI LITERATURA ROMANA!

    Răspunde
  • 23/01/2014 la 21:40
    Legătură permanentă

    Salut asi avea si eu o intrebare legata de placa de dezvoltare Arduino se poate sa fac ca pe un afisaj lcd in coltul din stanga sa fie afisat timpul si data si in cel din dreapta 2 temperaturi (interior si exterior)???Multumesc anticipat

    Răspunde
  • 18/03/2014 la 20:42
    Legătură permanentă

    Va salut. Am o plac Arduino Mega 2560 cu acel ceas în timp real DS1307 dar nu stiu care librarie este buna pentru el. pentru ca setez ceasul si nu il memoreaza dupa ce i scot alimentarea

    Răspunde
    • 18/03/2014 la 23:15
      Legătură permanentă

      Atata timp cat in momentul cand cititi ceasul datele sunt ok libraria functioneaza.
      Totusi as dorii sa stiu daca:
      1.E montajul legat la o baterie externa?
      2.E functionala acea baterie?

      Răspunde
  • 10/04/2015 la 23:27
    Legătură permanentă

    Salutare. Cum as putea face si eu montajul dar fara arduino, as vrea sa folosesc doar atmega328, pentru a iesii montajul cat mai mic, trebuie modificat in program intrarile si iesirile?

    Răspunde
    • 11/04/2015 la 07:24
      Legătură permanentă

      Nu trebuie sa schimbi nimic. Pe atmega trebuie sa încarci bootloaderul de arduino(găsești pe site un articol despre cum se face acest lucru) si trebuie sa știi corespondenta intre pinii atmega si arduino(găsești cu un search pe Google).

      Răspunde
  • 13/04/2015 la 21:27
    Legătură permanentă

    Buna seara ,
    Interesant programul si multumim pentru rabdarea de a ne asculta.
    Cum se implementeaza cele 2 alarme in codul initial?
    Multumesc!

    Răspunde
  • 11/02/2017 la 10:13
    Legătură permanentă

    Am facut montajul cu arduino uno si merge perfect, dar cand arduino nu este alimentat pierd data si ora. La realimentare afiseaza data si ora la care am incarcat programul in arduino. DS1307 are baterie conectata. Ce se poate face sa functioneze ceasul cand arduino nu este alimentat?
    Multumesc.

    Răspunde
  • 18/02/2017 la 14:57
    Legătură permanentă

    Buna ziua,
    Mulțumesc pentru răspuns.
    Montajul folosit este unul cumpărat de pe DX.com cu memorie 24C32N si DS1307 deci cred ca este ok, bateria am schimbat-o cu altele 3, și după ce am scos din program // RTC.adjust(DateTime(__DATE__, __TIME__));, pornește de fiecare data cu data 1/1/2000 00:00:00. Ce as putea sa mai încerc?
    Mulțumesc.

    Răspunde

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *

Acest sit folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.