Dove dice :On-board 32 kHz Clock Oscillator for Easy RTC Implemetations
Quindi anche con il 328 facendo oscillare un quarzo a 32KHZ si possono implementare le funzionalità di un RTC che di solito ho visto che si preferisce comprare.
Quali vantaggi ci sono ad avere un RTC esterno anzichè interno?
No perchè c'è anche il codice sorgente dell'RTC.
Però non ho idea di come collegare il quarzo, forse bisogna fare un osclillatore esterno ed il segnale iniettarlo in qualche pin.
l'rtc intrno ha una risoluzione bassissima e si mangia vari secondi al giorno, un vero rtc è molto più preciso di solito ed in più ha anche un sistema di compensazione dell'errore introdotto dalla variazione di temperatura.
No, aspetta Brain. Secondo me non è come dici.
Riporto dal datasheet dell'Atmega328. pag. 156:
The clock source for Timer/Counter2 is named clkT2S. clkT2S is by default connected to the main
system I/O clock clk IO. By setting the AS2 bit in ASSR, Timer/Counter2 is asynchronously
clocked from the TOSC1 pin. This enables use of Timer/Counter2 as a Real Time Counter
(RTC). When AS2 is set, pins TOSC1 and TOSC2 are disconnected from Port C. A crystal can
then be connected between the TOSC1 and TOSC2 pins to serve as an independent clock
source for Timer/Counter2. The Oscillator is optimized for use with a 32.768 kHz crystal.
Quindi essendo la sorgente un quarzo esterno, non usi il clock di sistema per cui tutto dipende dalla qualità del quarzo e dall'ottimizzazione del circuito. Puoi così farti effettivamente un RTC, però devi gestirti tu tutta la parte di conteggio ora/data, perché il datasheet non mi pare che specifichi che lo fa il chip. Ti dice solo che ti mette a disposizione il timer2.
Puoi così farti effettivamente un RTC, però devi gestirti tu tutta la parte di conteggio ora/data, perché il datasheet non mi pare che specifichi che lo fa il chip. Ti dice solo che ti mette a disposizione il timer2.
Si il codice sarebbe questo preso da Atmel, ma perchè un RTC esterno oltre all'orologio fornisce informazioni sul calendario?
// Include files
#include "Main.h"
#include "RTC.h"
// Lookup table used to determine the highest date in a specific month
unsigned char MaxDate[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*! \brief Start Timer/Counter2 in asynchronous operation using a
* 32.768kHz crystal.
*/
void RTC_init(void)
{
Delay(1000); // wait for 1 sec to let the Xtal stabilize after a power-on,
__disable_interrupt(); // disabel global interrupt
TIMSK2 = 0; // disable OCIE2A and TOIE2
ASSR = (1<<AS2); // select asynchronous operation of Timer2
TCNT2 = 0; // clear TCNT2A
TCCR2A = (1<<CS22) | (1<<CS20); // select precaler: 32.768 kHz / 128 = 1 sec between each overflow
while(ASSR & (0x01 | 0x04)); // wait for TCN2UB and TCR2UB to be cleared
TIFR2 = 0xFF; // clear interrupt-flags
TIMSK2 = (1<<TOIE2); // enable Timer2 overflow interrupt
__enable_interrupt(); // enable global interrupt
// initial time and date setting
HOUR = 8;
MINUTE = 0;
SECOND = 0;
DAY = 4;
MONTH = 11;
YEAR_LO = 2;
YEAR_HI = 20;
}
/*! \brief Updates the time and date variables
*/
void Time_update(void)
{
unsigned char LeapYear = FALSE;
//the variable SECOND gets updated in the Timer0 Overflow Interrupt Routine every second
if(SECOND > 59) // if one minute
{
SECOND = 0; // clear SECOND
MINUTE++; // increment MINUTE
if(MINUTE > 59) // if one hour
{
MINUTE = 0; // clear MINUTE
HOUR++; // increment HOUR
if(HOUR > 23) // if one hour
{
HOUR = 0; // clear HOUR
DAY++; // increment DAY
if(MONTH == 2) // if it's February
{
// check for leap year
if(!YEAR_LO) // if YEAR_LO = 0, (a century has passed)
{
if(!(YEAR_HI%4)) // check if YEAR_HI is divisible by 4
LeapYear = TRUE; // then it is a leap year
}
else if(!(YEAR_LO%4) & (YEAR_LO != 0)) // else if YEAR_LO is divisible by 4 and not zero
LeapYear = TRUE; // then it's a leap year
}
if(DAY > (MaxDate[MONTH] + LeapYear)) // if a whole month has passed
{
DAY = 1; // clear DAY
MONTH++; // increment MONTH
if(MONTH > 12) // if one year
{
MONTH = 1; // clear MONTH
YEAR_LO++; // increment YEAR_LO
if(YEAR_LO > 99) // if one century
{
YEAR_LO = 0; // clear YEAR_LO
YEAR_HI++; // increment YEAR_HI
if(YEAR_HI > 99) // if 100 centuries
YEAR_HI = 0; // the AVR is still going strong :)
}
}
}
}
}
}
}
/*! \brief Increment the varible SECOND by one - interrupt function.
*/
#pragma vector = TIMER2_OVF_vect
__interrupt void TIMER2_OVF_interrupt(void)
{
SECOND++; // increment second
}
Ma sai che un quarzo da un vecchio orologio guasto lo smonto volentieri, se ha questa frequenza 32.768kHz
provo ad impementare delle funzioni di alto livello più digeribili.
Un RTC ha dei registri interni che vengono aggiornati man mano che scorre il tempo e che contengono i secondi, minuti, ore, giorno della settimana, giorno del mese, mese ed anno nonché effettuano anche la compensazione per l'anno bisestile e come passare da un mese all'altro. Tutte queste funzioni non credo che il timer dell'Atmega te le faccia, dovresti farlo tu a livello di codice.
In genere i quarzi per orologio lavorano a 32768 Hz, è quasi uno standard.
Facevo caso ad una cosa. Rileggendo quell'estratto sono andato a ricercare quei pin, TOSC1 e TOSC2.... Ebbene, sono i pin normalmente deputati all'utilizzo del quarzo esterno, non sono altri 2 pin (come pensavo). Quindi l'uso di un quarzo da 32768 Hz per usare l'Atmega328 ti obbliga ad usare l'oscillatore interno come fonte di clock per il sistema, perciò ottieni sì un RTC ma anche un micro che va minimo a metà velocità (l'oscillatore va a 8 MHz).
Ho letto velocemente quel documento. Esso dice che quanto descritto si applica a tutti gli Atmega con modulo RTC integrato, come l'Atmega103 a cui quel documento fa riferimento. Difatti nella descrizione del micro si legge:
Real-time Counter (RTC) with Separate Oscillator
Ho aperto poi per scrupolo il datasheet dell'Atmega328 ed ho letto tra le sue caratteristiche:
Real-time Counter with Separate Oscillator
Quindi in teoria anche questo micro ha un modulo RTC integrato. Ciò significa che esso opera in modo asincrono dal clock di sistema. Anche il datasheet lo specifica: anche in condizioni di grossi carichi di lavoro sulla CPU, il modulo RTC, operando con il suo clock separato, mantiene la sua precisione. Interessante.
Tratto dal d.s. ristretto del 328: Unstable 32kHz Oscillator
The 32kHz oscillator does not work as system clock. The 32kHz oscillator used as asynchronous
timer is inaccurate.
Problem Fix/ Workaround
None.
Penso che si capisca anche se è in inglese
Con un clock di 8MHZ e calibrando l'oscillatore rc grazie al quarzo da 32KHZ l'errore dovrebbe essere ancora minore e sopratutto non è cumulativo.
Dico questo perchè non è detto che ci serve un orologio di precisione in tutti i progetti, se perde un secondo all'anno mi sta pure bene, ma evito di acquistare un RTC esterno interfacciarlo ecc.
un secondo all'anno sarebbe oro
mediamente un rtc come il ds1307 ha un errore di +o- mezzo secondo al giorno e non credo che l'atmega riesca a fare di meglio.
mediamente un rtc come il ds1307 ha un errore di +o- mezzo secondo al giorno e non credo che l'atmega riesca a fare di meglio.
ahaha, si allora sogna, niente da fare, io credevo fossero più precisi cio circa 3 minuti all'anno.
Comunque anche se un atmega sballasse di 10 all'anno per certi progetti potrebbe essere tollerato.
Comunque sarebbe da provare e verificare, quel The 32kHz oscillator used as asynchronous
timer is inaccurate, non dice quanto non è accurato ed in riferimento a cosa, se si riferisce a quello che dice il doc1259 allora è da provare, solo che con il 328 non si può usare un quarzo di sistema separato ma bisogna usare l'oscillatore rc interno, mentre con ATmega103 si possono usare entrambe i quarzi perchè i pin sono separati.
L'oscillatore interno rc è mooolto inpreciso e nella migliore delle ipotesi l'errore sarebbe di vari secondi al giorno.
Anche i quarzi non sono di per sè garanzia di precisione, nei datasheet questo parametro è specificato come errore in PPM (parti per milione).
quindi anche usando un buon rtc con un quarzo scarso si otterrebbero risultati pessimi, poi c'è anche l'effetto della temperatura... provate a calcolarvi la deviazione da qui: Mixed-signal and digital signal processing ICs | Analog Devices
Per il momento la soluzione migliore per gli rtc è quella di inglobare in quarzo interno e autocalibrarsi in base alla temperatura del die, questa è la tecnologia tcxo, compensated crystal oscillator (TCXO)
che incorporano rtc moderni come il ds3231.
MauroTec:
allora è da provare, solo che con il 328 non si può usare un quarzo di sistema separato ma bisogna usare l'oscillatore rc interno, mentre con ATmega103 si possono usare entrambe i quarzi perchè i pin sono separati.
Sul 328 è possibile usare il Timer2 come rtc prendendo come sorgente il clock principale tramite il prescaler del timer2.
Attenzione che il Timer2 serve per il PWM, se viene utilizzato come RTC si perdono alcuni pin PWM di Arduino, da verificare quali.
Non avete pensato che per realizzare un RTC basta prendere una qualunque mcu 8 pin low cost, collegargli un quarzo preciso, scrivere un programmino che conta i cicli del timer e li converte in data ora, interfaccia I2C/SPI e con meno di 3 Euro avete risolto.
è vero astrobeed, si può fare anche così, tutto però dipende dalla precisione richiesta.
usando un mcu per migliorare la resa e compensare la risposta in temperatura dovresti misurare anche quella e ricalibrare al volo l'oscillatore in base a quella, e poi si introdurrebbe anche l'errore del sensore di temperatura usato ecc...
un sistema come quello che dici non è paragonabile ad un buon rtc come precisione alla lunga , ma se non è richiesta tutta questa precisione và più che bene
è vero astrobeed, si può fare anche così, tutto però dipende dalla precisione richiesta.
Appunto era quello che dicevo, però ci sarebbe da vedere qual'è l'errore in un'anno o giorno, considerando le variazioni di temperature da 7 a 32 gradi del nostro clima.
Se dopo un'anno anzichè segnare 00:00 segna 00:10 e non oltre io penso che può andare, e se il micro non fà grandi lavori si potrebbe anche pensare di usare un solo micro, tanto il timer funziona in backgroung.
Rimane da stabilire se usare il Timer2 e il prescaler e ricavare il clock dal quarzo da 16MHZ esterno, oppure montare come quarzo esterno uno da 32768 HZ ed usare l'oscillatore rc interno.
Per questa ultima soluzione sembra che si possa calibrare l'oscillatore rc interno grazie al quarzo da 32768HZ.