Ceasul în timp real DS1307 are o precizie destul de scăzută. Acesta pierde sau câștigă câteva secunde la zi în funcție de temperatura ambientală. Teoretic această pierdere ar putea fi compensată prin software cu ajutorul unui termometru, dar în general soluțiile cele mai simple sunt și cele mai fiabile. În consecință am ales fratele mai mare a cipului DS1307 și anume cipul DS3232.
Argumentele PRO pentru cipul DS3232 sunt:
– precizie ridicata
– nu are componente externe (cristalul de cuarț este integrat în cip)
– are senzor de temperatură intern foarte precis
– are 2 alarme setabile

Necesar
-plăcuță de dezvoltare Arduino
-bread board
-fire pentru conexiuni
-cipul DS3232
-(opțional)baterie 3.3V

Schema electrică
Schema de mai jos explică conexiunile între DS3232 și plăcuța de dezvoltare Arduino UNO. Pentru realizarea acestui montaj aveți nevoie de 5 conexiuni. Două pentru I2C(SCL si SDA), două pentru alimentare și una pentru a putea detecta întreruperile emise de cipul DS3232.

DS3232 (1)
Programare
Montajul are posibilitatea de a seta ora curentă, de a afișa ora curentă, arată temperatura ambientală, setează o alarmă la o anumită oră din zi sau setează o alarmă în funcție de o anumită temperatură critică.
Ca totul să funcționeze trebuie să instalați librăria RTC de la următoarea adresă de pe github. Dacă nu știţi încă cum se instalează o librărie, tutorialul acesta va poate fi de ajutor.

Comenzile acceptate de către montaj prin interfața serială sunt:
S sau s – setarea timpului curent
Pentru a seta data, în monitorul serial din Arduino IDE 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)(01-31)(01-12)(1960-2300). Astfel dacă vrem să setăm data de 26/12/2013 22:20:00 va fi următoarea: S22200026122013
O sau o -afișarea timpului curent pe serial
T sau t -afișarea temperaturii
C sau c -setarea temperaturii de alarma
Formatul acestei comenzi este C sau c pentru a afișa temperatura critică sau CXX unde XX reprezintă noua temperatură critică.
A sau a -setarea alarmei
Formatul acestei comenzi este A sau a pentru afișarea stării alarmelor sau pentru setarea unei noi alarme, comanda are forma AXHHMMS, unde X-alarma, și poate fi 1 sau 2; HHMM-ora și minutul; S-starea alarmei,1 pentru ON și 0 pentru OFF. Exemplu: A112001-seteaza alarma 1 pentru ora 12:00 cu starea ON

#include <DS3232RTC.h>
#include <Wire.h>
#include <Time.h>

//variabila care retine comanda primita pe serial
int comanda;
bool int_0 = false;
byte temp_c = 35;

void setup() {
Serial.begin(9600);
int_0 = false;
attachInterrupt(0, alarmTrigger, CHANGE);
}

void loop() {
if (int_0) showTrigger();
verificaTemperatura();
if (Serial.available()) { // daca se detecteaza
comanda = Serial.read();
if (comanda == 79 || comanda == 111) { //caracterul O sau o
citesteTimp();
}
if (comanda == 84 || comanda == 116) { //caracterul T sau t
citesteTemperatura();
}
if (comanda == 83 || comanda == 115) { //caracterul S sau s
setareTimp();
}
if (comanda == 65 || comanda == 97) { //caracterul A sau a
setareAlarma();
}
if (comanda == 67 || comanda == 99) { //caracterul A sau a
setareTemperatura();
}
}
delay(200);
}

//"S" sau "s" - setarea timpului curent
void setareTimp()
{
byte secunda, minutul, ora, ziS, ziL, luna;
int anul;
tmElements_t timp;
//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= (int) ((Serial.read() - 48) *1000+(Serial.read() - 48) *100+(Serial.read() - 48) *10 + (Serial.read() - 48));
if (ora!=218)
{
timp.Hour =ora;
timp.Minute =minutul;
timp.Second =secunda;
RTC.writeTime(timp);
timp.Day = ziL;
timp.Month = luna;
timp.Year = CalendarYrToTm(anul);
RTC.writeDate(timp);
Serial.print("Timpul a fost setat la:");
citesteTimp();
}
}
//"O" sau "o" -afişarea timpului curent pe serial
void citesteTimp() // Citeste timpul curent.
{
tmElements_t timp;
RTC.read(timp);
printDec2(timp.Hour);
Serial.print(':');
printDec2(timp.Minute);
Serial.print(':');
printDec2(timp.Second);
Serial.print(" ");
Serial.print(timp.Day, DEC);
Serial.print("/");
Serial.print(timp.Month);
Serial.print("/");
Serial.println(tmYearToCalendar(timp.Year), DEC);
Serial.println();
}

// "T" sau "t" -afisarea temperaturii
void citesteTemperatura()
{
tpElements_t temperatura;
RTC.readTemperature(temperatura);
if (temperatura.Temp != NO_TEMPERATURE) {
Serial.print(temperatura.Temp);
Serial.print(".");
Serial.print(temperatura.Decimal);
Serial.print("'C");
} else {
Serial.println("Nu pot citi temperatura!");
}
Serial.println();
}

void printDec2(int value)
{
Serial.print((char)('0' + (value / 10)));
Serial.print((char)('0' + (value % 10)));
}
//A sau a -afisarea sau setarea alarmei. Pentru setarea unei alarme comanda are forma AXHHMMS, unde X-alarma, si poate fi 1 sau 2;HHMM-ora si minutul;S-starea alarmei,1 pentru ON si 0 pentru OFF
//Ex.A112001-seteaza alarma 1 pentru ora 12:00 cu starea ON
void setareAlarma()
{
byte minutul, ora, stare, alarma;
tmElements_t timp;
alarmMode_t mod;
alarma=0;
//se calculeaza valoarile receptionate pe portul serial
alarma = (byte)(Serial.read() - 48);
ora = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
minutul = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
stare = (byte)(Serial.read() - 48);
if (alarma==218){//daca se trimite doar A sau a se va afisa starea alarmelor
//afiseaza starea pentru alarma 1
RTC.readAlarm(1, mod, timp);
arataAlarma(1, mod, timp);
//afiseaza starea pentru alarma 2
RTC.readAlarm(2, mod, timp);
arataAlarma(2, mod, timp);
showTrigger();
}
else
{
timp.Hour = ora;
timp.Minute = minutul;
timp.Second=0;
if (stare==0)
{mod=alarmModeOff;}
else
{
mod = alarmModeHoursMatch;
bool a1 = RTC.isAlarmInterupt(1);
bool a2 = RTC.isAlarmInterupt(2);
if (alarma == 1) {
a1 = true;
} else {
a2 = true;
}
if (a1 && a2) {
RTC.setSQIMode(sqiModeAlarmBoth);
} else if (a1) {
RTC.setSQIMode(sqiModeAlarm1);
} else if (a2) {
RTC.setSQIMode(sqiModeAlarm2);
}
}
RTC.writeAlarm(alarma, mod, timp);
RTC.readAlarm(alarma, mod, timp);
arataAlarma(alarma, mod, timp);
}
}

void arataAlarma(byte alarmNum, const alarmMode_t mode, const tmElements_t time)
{
Serial.print("Alarma ");
Serial.print(alarmNum, DEC);
Serial.print(" este ");
if (mode == alarmModeOff) {
Serial.println("OFF");
}
else
{
Serial.print("ON");
Serial.print(" si este setata la:");
printDec2(time.Hour);
Serial.print(":");
printDec2(time.Minute);
Serial.print(":");
printDec2(time.Second);
}

Serial.println();
}

void showTrigger()
{
if (RTC.isAlarmFlag(1)) {
//inlocuiti linia de mai jos cu comanda ce doriti sa se execute la declansarea alarmei
Serial.println("Alarma 1 a fost declansata");
RTC.clearAlarmFlag(1);
}
if (RTC.isAlarmFlag(2)) {
//inlocuiti linia de mai jos cu comanda ce doriti sa se execute la declansarea alarmei
Serial.println("Alarma 2 a fost declansata");
RTC.clearAlarmFlag(2);
}
int_0 = false;
}

void alarmTrigger() // Triggered when alarm interupt fired
{
int_0 = true;
}

//C sau c pentru setarea temperaturii critice
void setareTemperatura()
{byte temp;
temp = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
if (temp==83){//daca se trimite doar C sau c se va afisa temperatura critica prestabilita
Serial.print("Temperatura critica este setata la:");
Serial.print(temp_c);
Serial.println("C");
}
else
{
temp_c=temp;
Serial.print("Temperatura critica a fost setata la:");
Serial.print(temp_c);
Serial.println("C");
}
}

void verificaTemperatura()
{
tpElements_t temperatura;
RTC.readTemperature(temperatura);
if (temperatura.Temp>=temp_c){
Serial.println("Alarma de temperatura!");
Serial.print("Tmax=");Serial.println(temp_c);
Serial.print("Tact=");Serial.println(temperatura.Temp);
}
}

 

Iar la final, rezultatul aplicaţiei:

DS3232_on

Spor la treaba!

Ceas în timp real DS3232
Etichetat pe:            

Un comentariu la „Ceas în timp real DS3232

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.