Le immagini dei prodotti sono solo a scopo informativo e potrebbero presentare piccole differenze, a seconda del lotto e del fornitore. Le specifiche e i prezzi dei prodotti potrebbero essere soggetti a modifiche senza preavviso. Facciamo del nostro meglio per aggiungere specifiche quanto più precise e corrette possibili alla pagina del prodotto, ma è possibile che non siano del tutto corrette. Se identifichi un caso del genere, ti preghiamo di segnalarcelo.
Il prodotto è destinato agli specialisti e richiede personale qualificato e autorizzato. Il prodotto non include istruzioni di montaggio/uso . La messa in funzione del prodotto da parte di persone non qualificate comporta la perdita della garanzia secondo i Termini e Condizioni presenti sul sito.
Le specifiche tecniche indicate (corrente, potenza, ecc.) rappresentano valori massimi consentiti in condizioni ideali di funzionamento. Per un utilizzo sicuro e una durata ottimale, si raccomanda di utilizzare il prodotto in regime continuo a non più del 50% dei valori massimi specificati.
Modulo orologio RTC PCF8563, interfaccia I2C, 1.0-5.5V, allarme e timer, supporto per batteria a bottone
Mantiene ora e data con basso consumo, ideale per progetti Arduino, Raspberry Pi e automazioni. Il PCF8563 offre una comunicazione I2C semplice, alimentazione a 3.3V o 5V con batteria di backup, buona stabilità rispetto ai moduli classici DS1307, dimensioni compatte per un'integrazione facile nei montaggi.
Acquistando questo prodotto guadagni 0,29 RON in punti fedeltà.
Spedizione veloce gratuita per ordini superiori a 100EUR nella maggior parte de paesi UE.
Spediamo dal nostro magazzino entro 24 ore
Ricevi punti a ogni ordine, per un valore del 5%.
Il modulo orologio RTC con circuito PCF8563 mantiene ora e data in tempo reale e li conserva anche quando manca l'alimentazione principale, purché nel supporto sia inserita una batteria a bottone. Fornisce secondi, minuti, ore, giorno, giorno della settimana, mese e anno, e i dati si leggono tramite interfaccia I2C. È adatto a registrazioni dati con marcatura temporale, allarmi, orologi digitali, automazioni programmate e qualsiasi progetto che deve conoscere l'ora esatta dopo un riavvio.
Il circuito PCF8563 è un orologio calendario CMOS a basso consumo, che utilizza un cristallo da 32.768 kHz e un divisore di frequenza per generare la base dei tempi di 1 Hz. Oltre a orologio e calendario, il circuito dispone di allarme, timer, rilevatore di bassa tensione con indicatore VL e un'uscita di clock programmabile, con frequenze di 32.768 kHz, 1.024 kHz, 32 Hz o 1 Hz. L'interfaccia I2C supporta una frequenza fino a 400 kHz, e l'indirizzo a 7 bit è 0x51.
Tra le caratteristiche principali si contano il circuito PCF8563 in package SO8 (U4), il cristallo da 32.768 kHz (Y1), il supporto per batteria a bottone, due diodi e condensatori di filtraggio montati sulla scheda, due fori di fissaggio e il connettore J1 con 6 pin contrassegnati INT, COT, SCL, SDA, GND e VCC. L'alimentazione avviene tramite il pin VCC con tensione da 1.0 a 5.5 V, e in caso di mancanza di alimentazione l'orologio continua a funzionare grazie alla batteria inserita nel supporto.
Tramite l'interfaccia I2C, il modulo è compatibile con Arduino, ESP32, ESP8266, STM32, Raspberry Pi e altre piattaforme dotate di bus I2C, utilizzando solo due fili dati, l'alimentazione e la massa.
Specifiche:
Tensione di alimentazione: 1.0 - 5.5 VDC
Corrente in modalità di riserva: 0.25 µA tipica (a 3.0 V e 25 °C)
Circuito orologio: PCF8563 (SO8)
Interfaccia: I2C
Indirizzo I2C: 0x51 (a 7 bit)
Frequenza massima I2C: 400 kHz (con alimentazione di almeno 1.8 V)
Cristallo: 32.768 kHz (Y1)
Dati forniti: Secondi, minuti, ore, giorno, giorno della settimana, mese, anno, indicatore di secolo
Funzioni aggiuntive: Allarme, timer, rilevatore di bassa tensione (indicatore VL)
Uscita clock programmabile (COT): 32.768 kHz, 1.024 kHz, 32 Hz o 1 Hz
Uscita di interruzione (INT): Open-drain, attiva a livello basso
Alimentazione di riserva: Supporto per batteria a bottone
Connettore: J1, 6 pin (INT, COT, SCL, SDA, GND, VCC)
Layout:
| Elemento | Funzione |
|---|---|
| Connettore J1 | Connettore a 6 pin, contrassegnati dall'alto verso il basso INT, COT, SCL, SDA, GND e VCC, per alimentazione, bus I2C e le due uscite del circuito. |
| Circuito U4 (PCF8563) | Orologio in tempo reale con calendario, allarme, timer e interfaccia I2C, in package SO8. |
| Cristallo Y1 | Cristallo da 32.768 kHz che fornisce la base dei tempi dell'orologio. |
| Supporto batteria a bottone | Alimenta l'orologio quando manca l'alimentazione del modulo, così ora e data vengono conservate. |
| Diodi D7 e D8 | Diodi montati vicino al supporto della batteria, nel circuito di alimentazione dell'orologio. |
| Condensatori | I condensatori C10, C16 e C22 e un condensatore elettrolitico filtrano l'alimentazione del circuito. |
| Fori di montaggio | Due fori all'estremità della scheda, dal lato del supporto della batteria, per il fissaggio del modulo. |
Pinout:
| Connettore | Pin | Funzione |
|---|---|---|
| J1 | INT | Uscita di interruzione open-drain, attiva a livello basso, per allarme e timer |
| J1 | COT | Uscita clock programmabile (CLKOUT), open-drain, predefinita a 32.768 kHz |
| J1 | SCL | Clock I2C |
| J1 | SDA | Dati I2C |
| J1 | GND | Massa |
| J1 | VCC | Alimentazione 1.0 - 5.5 VDC |
| Parametro I2C | Valore |
|---|---|
| Indirizzo a 7 bit | 0x51 |
| Indirizzo di scrittura a 8 bit | A2h |
| Indirizzo di lettura a 8 bit | A3h |
Utilizzo:
Il modulo non ha pulsanti, potenziometri, jumper o LED, quindi ora e data si impostano e si leggono solo tramite il bus I2C.
Inserite nel supporto una batteria a bottone con la polarità corretta, verificando il tipo indicato sul supporto, in modo che l'orologio funzioni anche quando l'alimentazione del modulo è disattivata.
Collegate il pin VCC all'alimentazione della scheda di sviluppo, il pin GND alla massa, il pin SDA alla linea dati I2C e il pin SCL alla linea clock I2C. Attenzione, sul connettore J1 il pin SCL si trova sopra il pin SDA, al contrario di molti altri moduli.
Alimentate il modulo con una tensione compresa tra 1.0 e 5.5 V, adeguata al livello logico della scheda di sviluppo. Non applicate più di 5.5 V e rispettate la polarità.
Lasciate scollegati i pin INT e COT se non utilizzate l'allarme, il timer o l'uscita di clock. Se li utilizzate, aggiungete su ciascuno una resistenza di pull-up, poiché entrambe le uscite sono di tipo open-drain.
Leggete l'indirizzo 0x51 sul bus I2C per verificare che il modulo risponda, quindi impostate ora e data scrivendo i registri dell'orologio. I valori si leggono e si scrivono in formato BCD.
Verificate l'indicatore VL nel registro dei secondi. Se è 1, l'ora non è più garantita e va impostata di nuovo, mentre la scrittura dei secondi con il bit 7 uguale a 0 cancella l'indicatore.
Per risultati stabili, usate fili corti per SDA e SCL e sostituite la batteria quando l'ora si perde dopo un'interruzione dell'alimentazione. La precisione dipende dal cristallo, quindi per applicazioni che richiedono esattezza è utile una sincronizzazione periodica dell'orologio.
- Tensione di alimentazione
- 1.0-5.5 V DC
- Numero di pin
- 6 (INT, COT, SCL, SDA, GND, VCC)
- Interfaccia
- I2C
- Frequenza di lavoro
- 400 kHz
- Circuito integrato
- PCF8563
- Consumo in standby
- 0.25 µA
- Indirizzo I2C
- 0x51
- Tipo di batteria
- Batteria a bottone
Produs destinat utilizarii in proiecte electronice, automatizari, prototipare, educatie si cercetare.
Produsul trebuie utilizat numai conform specificatiilor tehnice mentionate in descriere si/sau in documentatia produsului.
Avertismente generale de siguranta:
Nu utilizati produsul la tensiuni, curenti sau temperaturi peste valorile specificate.
Montajul si conectarea trebuie realizate de persoane cu cunostinte tehnice minime in domeniul electric/electronic.
Evitati scurtcircuitele, inversarea polaritatii si conectarea gresita a alimentarii.
Nu lasati produsul alimentat nesupravegheat in timpul testelor.
Produsul nu este jucarie si nu este destinat copiilor.
Pentru modulele electronice, se recomanda utilizarea in carcase, panouri sau montaje protejate, dupa caz.
Identificare produs:
Denumirea produsului, codul/SKU-ul si caracteristicile tehnice sunt mentionate in pagina produsului si/sau pe eticheta ambalajului.
Producator / Importator / Distribuitor:
Sigmanortec S.R.L.
Calea Bucuresti nr. 9, Targu Jiu, Gorj, Romania
E-mail: [email protected]
Website: www.sigmanortec.ro
Persoana responsabila in UE:
Sigmanortec S.R.L.
Calea Bucuresti nr. 9, Targu Jiu, Gorj, Romania
E-mail: [email protected]
Documentatie si siguranta:
Pentru informatii suplimentare, fise tehnice, declaratii de conformitate sau instructiuni, ne puteti contacta la [email protected].
/*
PCF8563 RTC module test
Board: Arduino Uno (Tools > Board > Arduino AVR Boards > Arduino Uno)
Board package: Arduino AVR Boards (comes with the Arduino IDE)
Libraries: none to install, the Wire library comes with the Arduino IDE
Wiring:
RTC VCC -> Arduino 5V
RTC GND -> Arduino GND
RTC SDA -> Arduino A4
RTC SCL -> Arduino A5
RTC INT and COT are not connected
The program sets the clock from the compile time when the time was never
set or the backup battery was lost, then prints the date and time every second.
*/
#include <Wire.h>
const uint8_t RTC_ADDRESS = 0x51; // 7-bit I2C address of the PCF8563
const uint8_t REG_CONTROL_1 = 0x00; // first register, control and status 1
const uint8_t REG_SECONDS = 0x02; // seconds register, bit 7 is the VL flag
const bool FORCE_SET_TIME = false; // set to true to rewrite the time at every start
const char *dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Convert a decimal number (0 - 99) to BCD
uint8_t decToBcd(uint8_t value) {
return ((value / 10) << 4) | (value % 10);
}
// Convert a BCD number to decimal
uint8_t bcdToDec(uint8_t value) {
return ((value >> 4) * 10) + (value & 0x0F);
}
// Day of the week from the date, 0 = Sunday
uint8_t dayOfWeek(uint16_t year, uint8_t month, uint8_t day) {
static const uint8_t offsets[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
if (month < 3) {
year -= 1;
}
return (year + year / 4 - year / 100 + year / 400 + offsets[month - 1] + day) % 7;
}
// Check if the module answers on the I2C bus
bool rtcPresent() {
Wire.beginTransmission(RTC_ADDRESS);
return Wire.endTransmission() == 0;
}
// Read several consecutive registers starting at startReg
bool readRegisters(uint8_t startReg, uint8_t *buffer, uint8_t length) {
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(startReg);
if (Wire.endTransmission() != 0) {
return false;
}
if (Wire.requestFrom(RTC_ADDRESS, length) != length) {
return false;
}
for (uint8_t i = 0; i < length; i++) {
buffer[i] = Wire.read();
}
return true;
}
// Write the compile date and time into the clock
void setTimeFromCompileTime() {
const char *dateText = __DATE__; // format: "Mmm dd yyyy"
const char *timeText = __TIME__; // format: "hh:mm:ss"
const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char monthName[4] = {dateText[0], dateText[1], dateText[2], 0};
uint8_t month = (strstr(months, monthName) - months) / 3 + 1;
uint8_t day = ((dateText[4] == ' ') ? 0 : (dateText[4] - '0')) * 10 + (dateText[5] - '0');
uint16_t year = atoi(dateText + 7);
uint8_t hour = (timeText[0] - '0') * 10 + (timeText[1] - '0');
uint8_t minute = (timeText[3] - '0') * 10 + (timeText[4] - '0');
uint8_t second = (timeText[6] - '0') * 10 + (timeText[7] - '0');
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(REG_CONTROL_1); // start at control register 1
Wire.write((uint8_t)0x00); // control 1: clock running
Wire.write((uint8_t)0x00); // control 2: no alarm or timer flags
Wire.write(decToBcd(second)); // seconds, bit 7 = 0 clears the VL flag
Wire.write(decToBcd(minute)); // minutes
Wire.write(decToBcd(hour)); // hours
Wire.write(decToBcd(day)); // day of the month
Wire.write(dayOfWeek(year, month, day)); // day of the week
Wire.write(decToBcd(month)); // month, century bit 0 means 20xx
Wire.write(decToBcd(year % 100)); // year (00 - 99)
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtcPresent()) {
Serial.println("PCF8563 not found, check the wiring");
while (true) {
delay(1000);
}
}
Serial.println("PCF8563 found at address 0x51");
uint8_t secondsRegister = 0;
readRegisters(REG_SECONDS, &secondsRegister, 1);
bool vlFlag = (secondsRegister & 0x80) != 0; // 1 = time is not guaranteed
if (vlFlag || FORCE_SET_TIME) {
Serial.println("Time lost or forced, setting it from compile time");
setTimeFromCompileTime();
}
}
void loop() {
uint8_t data[7];
if (!readRegisters(REG_SECONDS, data, 7)) {
Serial.println("Read error");
delay(1000);
return;
}
bool vlFlag = (data[0] & 0x80) != 0;
uint8_t second = bcdToDec(data[0] & 0x7F); // mask the VL bit
uint8_t minute = bcdToDec(data[1] & 0x7F);
uint8_t hour = bcdToDec(data[2] & 0x3F);
uint8_t day = bcdToDec(data[3] & 0x3F);
uint8_t weekday = data[4] & 0x07;
uint8_t month = bcdToDec(data[5] & 0x1F); // mask the century bit
uint16_t year = 2000 + bcdToDec(data[6]);
char buffer[40];
snprintf(buffer, sizeof(buffer), "%04u-%02u-%02u %02u:%02u:%02u ",
(unsigned int)year, (unsigned int)month, (unsigned int)day,
(unsigned int)hour, (unsigned int)minute, (unsigned int)second);
Serial.print(buffer);
Serial.print(dayNames[weekday]);
if (vlFlag) {
Serial.print(" WARNING: time is not guaranteed");
}
Serial.println();
delay(1000); // one reading per second
}
In questo tutorial utilizziamo la scheda Arduino Uno R3. Il modulo orologio PCF8563 è un orologio in tempo reale (RTC) con interfaccia I2C. Mantiene l'ora e la data anche quando la scheda di sviluppo è spenta, finché ha una batteria di riserva nel portabatteria. Lo si usa nei registri dati con marca temporale, negli allarmi, negli orologi digitali, nelle automazioni programmate e in qualsiasi progetto che deve sapere che ore sono dopo un riavvio.
Il modulo ha il circuito PCF8563 in package SO8, un cristallo da 32.768 kHz (Y1) e un portabatteria per batterie a bottone. Sul bordo della scheda c'è un connettore J1 a 6 pin, contrassegnati INT, COT, SCL, SDA, GND e VCC. La scheda non ha pulsanti, potenziometri, jumper o LED, quindi tutte le regolazioni si fanno da programma.

Come funziona:
Il cristallo da 32.768 kHz oscilla 32768 volte al secondo, ovvero 2 alla 15. Il circuito divide questa frequenza fino a 1 Hz e a ogni impulso di questo incrementa il contatore dei secondi. Dal contatore dei secondi si ottengono minuti, ore, giorno, giorno della settimana, mese e anno, tutti conservati in registri interni.
I valori nei registri sono in formato BCD. Ogni cifra decimale occupa 4 bit, quindi il secondo 45 si legge come 0x45 e non come 0x2D. Il programma converte dal BCD al decimale con la formula (v >> 4) * 10 + (v AND 0x0F) e viceversa con ((v / 10) << 4) OR (v MOD 10).
Il registro 0x02 (secondi) ha nel bit 7 l'indicatore VL (voltage low). Se è 1, la tensione di alimentazione è scesa troppo oppure l'oscillatore si è fermato, e l'ora non è più garantita. Scrivendo i secondi con il bit 7 uguale a 0 l'indicatore viene cancellato. Il registro 0x07 (mese) ha nel bit 7 il bit di secolo, che il circuito commuta al passaggio dell'anno da 99 a 00. Nel programma consideriamo che il valore 0 significhi gli anni 20xx.
Il circuito ha anche l'allarme, il timer e un'uscita di clock programmabile sul pin COT (CLKOUT), con frequenze 32.768 kHz, 1.024 kHz, 32 Hz o 1 Hz, impostata dal registro all'indirizzo 0x0D. Il pin INT è un'uscita di interruzione, open-drain, attiva a livello basso. In questo tutorial leggiamo solo ora e data, quindi COT e INT restano non collegati.
La precisione dipende solo dal cristallo, perché il circuito non fa compensazione di temperatura. Un cristallo con scostamento di 20 ppm (valore dato come esempio) significa circa 20 x 86400 / 1000000 = 1.7 secondi al giorno, cioè circa 50 secondi al mese. Per un registro dati è più che sufficiente, per un orologio di precisione servirebbe una sincronizzazione periodica.
L'indirizzo I2C a 7 bit è 0x51. Nella documentazione del circuito compaiono gli indirizzi a 8 bit A2h per la scrittura e A3h per la lettura, mentre la libreria Wire di Arduino lavora con l'indirizzo a 7 bit, cioè 0x51.
Collegamento:
Alimentate il modulo dal pin 5V della scheda Arduino Uno. Il circuito PCF8563 funziona tra 1.0 e 5.5 V, quindi 5 V è adatto, e i livelli logici del bus I2C sono compatibili con quelli della scheda Uno, quindi non serve un convertitore di livello. Se usate una scheda a 3.3 V, alimentate il modulo da 3.3 V. La scheda Arduino si alimenta dal computer tramite il cavo USB A-B. Montate la batteria a bottone nel portabatteria con la polarità corretta, verificando il tipo stampigliato sul portabatteria.
| Pin prodotto | Si collega a | Ruolo |
|---|---|---|
| VCC | 5V | Alimentazione modulo |
| GND | GND | Massa comune |
| SDA | A4 | Dati I2C |
| SCL | A5 | Clock I2C |
| INT | Non collegato | Uscita di interruzione per allarme e timer, non usata qui |
| COT | Non collegato | Uscita di clock programmabile CLKOUT, non usata qui |
Sulla scheda Arduino Uno R3 i pin SDA e SCL vicino ad AREF sono gli stessi segnali di A4 e A5, quindi potete usarli al loro posto. Quando collegate i pin del connettore, tenete presente che l'ordine dall'alto in basso sulla scheda è INT, COT, SCL, SDA, GND, VCC. Attenzione a SDA e SCL, sono in ordine inverso rispetto a molti moduli. Per un bus I2C stabile usate cavi corti.
Scheda e librerie:
In Arduino IDE selezionate Tools > Board > Arduino AVR Boards > Arduino Uno. Il pacchetto Arduino AVR Boards è incluso in Arduino IDE, quindi non va aggiunto nessun indirizzo in File > Preferences. Selezionate poi la porta della scheda da Tools > Port.
Il programma usa solo la libreria Wire, che è inclusa in Arduino IDE, quindi non serve installare alcuna libreria. Parliamo direttamente con i registri del circuito, così capite esattamente cosa si legge e cosa si scrive.
Codice:
Il programma imposta l'orologio dall'ora di compilazione se l'ora non è mai stata impostata o se la batteria è stata rimossa, poi visualizza data e ora ogni secondo.
/*
PCF8563 RTC module test
Board: Arduino Uno (Tools > Board > Arduino AVR Boards > Arduino Uno)
Board package: Arduino AVR Boards (comes with the Arduino IDE)
Libraries: none to install, the Wire library comes with the Arduino IDE
Wiring:
RTC VCC -> Arduino 5V
RTC GND -> Arduino GND
RTC SDA -> Arduino A4
RTC SCL -> Arduino A5
RTC INT and COT are not connected
The program sets the clock from the compile time when the time was never
set or the backup battery was lost, then prints the date and time every second.
*/
#include <Wire.h>
const uint8_t RTC_ADDRESS = 0x51; // 7-bit I2C address of the PCF8563
const uint8_t REG_CONTROL_1 = 0x00; // first register, control and status 1
const uint8_t REG_SECONDS = 0x02; // seconds register, bit 7 is the VL flag
const bool FORCE_SET_TIME = false; // set to true to rewrite the time at every start
const char *dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Convert a decimal number (0 - 99) to BCD
uint8_t decToBcd(uint8_t value) {
return ((value / 10) << 4) | (value % 10);
}
// Convert a BCD number to decimal
uint8_t bcdToDec(uint8_t value) {
return ((value >> 4) * 10) + (value & 0x0F);
}
// Day of the week from the date, 0 = Sunday
uint8_t dayOfWeek(uint16_t year, uint8_t month, uint8_t day) {
static const uint8_t offsets[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
if (month < 3) {
year -= 1;
}
return (year + year / 4 - year / 100 + year / 400 + offsets[month - 1] + day) % 7;
}
// Check if the module answers on the I2C bus
bool rtcPresent() {
Wire.beginTransmission(RTC_ADDRESS);
return Wire.endTransmission() == 0;
}
// Read several consecutive registers starting at startReg
bool readRegisters(uint8_t startReg, uint8_t *buffer, uint8_t length) {
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(startReg);
if (Wire.endTransmission() != 0) {
return false;
}
if (Wire.requestFrom(RTC_ADDRESS, length) != length) {
return false;
}
for (uint8_t i = 0; i < length; i++) {
buffer[i] = Wire.read();
}
return true;
}
// Write the compile date and time into the clock
void setTimeFromCompileTime() {
const char *dateText = __DATE__; // format: "Mmm dd yyyy"
const char *timeText = __TIME__; // format: "hh:mm:ss"
const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char monthName[4] = {dateText[0], dateText[1], dateText[2], 0};
uint8_t month = (strstr(months, monthName) - months) / 3 + 1;
uint8_t day = ((dateText[4] == ' ') ? 0 : (dateText[4] - '0')) * 10 + (dateText[5] - '0');
uint16_t year = atoi(dateText + 7);
uint8_t hour = (timeText[0] - '0') * 10 + (timeText[1] - '0');
uint8_t minute = (timeText[3] - '0') * 10 + (timeText[4] - '0');
uint8_t second = (timeText[6] - '0') * 10 + (timeText[7] - '0');
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(REG_CONTROL_1); // start at control register 1
Wire.write((uint8_t)0x00); // control 1: clock running
Wire.write((uint8_t)0x00); // control 2: no alarm or timer flags
Wire.write(decToBcd(second)); // seconds, bit 7 = 0 clears the VL flag
Wire.write(decToBcd(minute)); // minutes
Wire.write(decToBcd(hour)); // hours
Wire.write(decToBcd(day)); // day of the month
Wire.write(dayOfWeek(year, month, day)); // day of the week
Wire.write(decToBcd(month)); // month, century bit 0 means 20xx
Wire.write(decToBcd(year % 100)); // year (00 - 99)
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtcPresent()) {
Serial.println("PCF8563 not found, check the wiring");
while (true) {
delay(1000);
}
}
Serial.println("PCF8563 found at address 0x51");
uint8_t secondsRegister = 0;
readRegisters(REG_SECONDS, &secondsRegister, 1);
bool vlFlag = (secondsRegister & 0x80) != 0; // 1 = time is not guaranteed
if (vlFlag || FORCE_SET_TIME) {
Serial.println("Time lost or forced, setting it from compile time");
setTimeFromCompileTime();
}
}
void loop() {
uint8_t data[7];
if (!readRegisters(REG_SECONDS, data, 7)) {
Serial.println("Read error");
delay(1000);
return;
}
bool vlFlag = (data[0] & 0x80) != 0;
uint8_t second = bcdToDec(data[0] & 0x7F); // mask the VL bit
uint8_t minute = bcdToDec(data[1] & 0x7F);
uint8_t hour = bcdToDec(data[2] & 0x3F);
uint8_t day = bcdToDec(data[3] & 0x3F);
uint8_t weekday = data[4] & 0x07;
uint8_t month = bcdToDec(data[5] & 0x1F); // mask the century bit
uint16_t year = 2000 + bcdToDec(data[6]);
char buffer[40];
snprintf(buffer, sizeof(buffer), "%04u-%02u-%02u %02u:%02u:%02u ",
(unsigned int)year, (unsigned int)month, (unsigned int)day,
(unsigned int)hour, (unsigned int)minute, (unsigned int)second);
Serial.print(buffer);
Serial.print(dayNames[weekday]);
if (vlFlag) {
Serial.print(" WARNING: time is not guaranteed");
}
Serial.println();
delay(1000); // one reading per second
}
Come funziona il codice:
All'inizio ci sono le definizioni. RTC_ADDRESS è l'indirizzo I2C a 7 bit del circuito, cioè 0x51. REG_CONTROL_1 è il primo registro (0x00), mentre REG_SECONDS è il registro dei secondi (0x02), il cui bit 7 è l'indicatore VL. La costante FORCE_SET_TIME, se la impostate su true, riscrive l'ora a ogni avvio. L'array dayNames contiene i nomi dei giorni, nell'ordine in cui li numera il programma, da 0 per domenica.
Le funzioni decToBcd e bcdToDec convertono tra il numero decimale e il formato BCD usato dai registri. La funzione dayOfWeek calcola il giorno della settimana dalla data, perché l'orologio non lo deduce da solo e dobbiamo calcolarlo noi. La funzione rtcPresent invia una trasmissione vuota all'indirizzo 0x51 e restituisce true se il modulo risponde.
La funzione readRegisters invia l'indirizzo del registro iniziale, poi richiede length byte con Wire.requestFrom e li mette nel buffer. Il circuito incrementa da solo l'indirizzo del registro, quindi una sola richiesta legge tutti i valori dai secondi all'anno.
La funzione setTimeFromCompileTime estrae data e ora dalle macro __DATE__ e __TIME__, calcola il mese in base alla posizione del nome nella stringa months e scrive in ordine i registri da 0x00 a 0x08. I secondi si scrivono con il bit 7 uguale a 0, il che cancella l'indicatore VL, e il bit di secolo nel mese resta 0.
Nel setup avviamo la porta seriale a 9600 baud e il bus I2C con Wire.begin. Se rtcPresent restituisce false, il programma mostra un messaggio di errore e si ferma. Altrimenti leggiamo il registro dei secondi, e se vlFlag è 1 oppure FORCE_SET_TIME è true, chiamiamo setTimeFromCompileTime.
Nel loop leggiamo 7 registri da 0x02 nell'array data. Da ogni valore mascheriamo i bit che non fanno parte del numero (0x7F per secondi e minuti, 0x3F per ore e giorno, 0x1F per il mese) e convertiamo dal BCD. L'anno si ottiene come 2000 più il valore del registro degli anni. La riga viene formattata con snprintf, visualizzata insieme al nome del giorno e, se vlFlag è 1, con un avviso. Alla fine, delay(1000) fa una lettura al secondo.
Risultato:
Aprite il Serial Monitor da Tools e impostate la velocità a 9600 baud. Alla prima accensione compaiono i messaggi sul modulo trovato e sull'impostazione dell'ora, poi una riga al secondo con data, ora e giorno della settimana. Alle accensioni successive l'ora non viene più impostata, finché la batteria è nel portabatteria.
PCF8563 found at address 0x51
Time lost or forced, setting it from compile time
2025-03-14 10:22:31 Friday
2025-03-14 10:22:32 Friday
2025-03-14 10:22:33 Friday
2025-03-14 10:22:34 Friday
2025-03-14 10:22:35 Friday
2025-03-14 10:22:36 Friday
Problemi frequenti:
Sul monitor seriale compare il messaggio PCF8563 not found. La causa è di solito un collegamento sbagliato o un'alimentazione mancante. Verificate che SDA vada ad A4 e SCL ad A5, tenendo presente che sul connettore SCL è sopra SDA, e che VCC sia a 5V e GND a GND.
Non compare nulla sul monitor seriale oppure compaiono caratteri strani. La causa è una velocità sbagliata. Impostate nel Serial Monitor la velocità di 9600 baud e verificate che la porta selezionata sia quella della scheda Arduino Uno.
L'ora è sbagliata dopo ogni spegnimento. La causa è una batteria assente o scarica nel portabatteria, oppure montata con la polarità invertita. Montate una batteria corretta, poi impostate FORCE_SET_TIME su true, caricate il programma una volta e riportatelo su false.
Compare l'avviso time is not guaranteed. L'indicatore VL è 1, quindi la tensione di alimentazione è scesa troppo oppure l'oscillatore si è fermato. Impostate di nuovo l'ora, e se l'avviso ritorna, sostituite la batteria.
L'orologio imposta l'ora di compilazione, ma con qualche secondo di ritardo. La causa è il tempo che passa tra la compilazione e il caricamento del programma sulla scheda. Per un'ora esatta, impostate l'orologio da una fonte esterna, ad esempio dal computer o da un server orario.
L'orologio si discosta di qualche secondo al mese. È normale, perché la precisione dipende dal cristallo e il circuito non fa compensazione di temperatura. Sincronizzate periodicamente l'orologio se vi serve una precisione migliore.
Limiti e consigli:
L'orologio funziona tra 1.0 e 5.5 V, ma per la comunicazione I2C a 400 kHz l'alimentazione deve essere di almeno 1.8 V. La precisione è data dal cristallo da 32.768 kHz e varia con la temperatura, quindi non sostituisce un orologio con compensazione di temperatura dove contano le frazioni di secondo al mese.
Il modulo mantiene l'ora solo finché nel portabatteria c'è una batteria in buono stato, e il consumo in modalità di riserva è molto basso, tipicamente 0.25 µA a 3.0 V e 25 °C. Quando usate le uscite INT e COT, aggiungete resistenze di pull-up, perché entrambe sono open-drain.
In seguito potete usare l'allarme e il timer del circuito, con l'uscita INT collegata a un ingresso di interruzione, per risvegliare la scheda da una modalità a basso consumo. Potete anche usare l'uscita COT a 1 Hz come base dei tempi per altri circuiti, oppure costruire un registro dati con marca temporale su scheda SD.