Módulo RTC Arduino: DS3231, DS1307 y DS1302, hora y alarmas
Módulo RTC Arduino: DS3231, DS1307 y DS1302, ajustar la hora con RTClib, reloj en LCD, riego programado, la trampa de carga de la CR2032 y NTP en ESP32.
Un módulo RTC para Arduino es una pequeña placa de reloj que sigue contando la fecha y la hora aunque tu placa se quede sin alimentación. RTC significa "Real Time Clock", es decir, reloj de tiempo real. El contador millis() de Arduino empieza desde cero en cada arranque y puede desviarse varios minutos en pocos días; en cambio, un módulo RTC funciona al segundo durante años gracias a su pila de botón (CR2032). Lo encontrarás en relojes de escritorio, sistemas de riego automático, comederos para mascotas, registradores de datos con marca de tiempo e iluminación temporizada.
En esta guía compararás los tres chips más comunes, el DS1307, el DS3231 y el DS1302, y verás cuál elegir y por qué. Después, paso a paso, ajustaremos y leeremos la hora con la biblioteca RTClib, mostraremos la hora y la fecha en un LCD I2C, montaremos un temporizador que activa una bomba a horas fijas cada día y usaremos la alarma por hardware del DS3231. Las últimas secciones explican la trampa del circuito de carga de la CR2032 que estropea muchos módulos, cómo obtener la hora de internet con NTP en el ESP32 y el RTC interno de la Raspberry Pi Pico.

¿Qué es un módulo RTC y cómo funciona?
En el corazón de un chip RTC hay un cristal de reloj de 32,768 kHz. Ese número no es casual: 32 768 es 2 elevado a 15, así que el chip divide esa frecuencia entre dos 15 veces para obtener un pulso exacto de 1 segundo. En cada pulso se actualizan los registros de segundos, minutos, horas, día, mes y año; la duración de los meses y los años bisiestos se calculan automáticamente hasta el año 2100. Arduino lee estos registros por I2C o escribe en ellos una hora nueva. Los valores se guardan en formato BCD (por ejemplo, 59 segundos se almacena como 0x59); las bibliotecas hacen esa conversión por ti.
El verdadero truco de un RTC son sus dos entradas de alimentación. Cuando falta VCC, el chip pasa automáticamente a la entrada de la pila (VBAT) y consume solo la corriente necesaria para seguir contando: menos de un microamperio o unos pocos microamperios. En ese estado el DS1307 desactiva la comunicación I2C, mientras que el DS3231 sigue respondiendo con la pila; en ambos casos el reloj no se detiene. Cuando vuelve la alimentación, Arduino arranca, lee la hora correcta del RTC y continúa donde lo dejó. Por la tolerancia del resonador cerámico del Arduino Uno, un reloj llevado con millis() puede desviarse varios minutos al día y se pierde con cada reinicio; por eso cualquier proyecto que dependa de la hora necesita un RTC aparte.
Diferencias entre DS1307, DS3231 y DS1302
| Característica | DS1307 | DS3231 | DS1302 |
|---|---|---|---|
| Interfaz | I2C (100 kHz), dirección 0x68 | I2C (hasta 400 kHz), dirección 0x68 | Serie de 3 hilos: CE (RST), I/O (DAT), SCLK (CLK) |
| Tensión de alimentación | 4,5–5,5 V | 2,3–5,5 V | 2,0–5,5 V |
| Cristal | Externo de 32,768 kHz (12,5 pF) | Integrado en el chip, compensado en temperatura (TCXO) | Externo de 32,768 kHz (6 pF) |
| Precisión | Depende del cristal; con ±20 ppm unos 1,7 s/día, aprox. 1 min/mes | ±2 ppm (0–40 °C): unos 5 s/mes, aprox. 1 min/año | Depende del cristal; similar al DS1307 o peor |
| Extras | 56 bytes de RAM respaldada por pila, salida de onda cuadrada (SQW) | 2 alarmas, salida INT/SQW, sensor de temperatura (±3 °C), ajuste de envejecimiento | 31 bytes de RAM, cargador lento integrado (trickle charger) |
| Consumo de la pila | Unos 300–500 nA | Unos 1–3 µA | Menos de 300 nA a 2 V |
| Biblioteca para Arduino | RTClib (Adafruit) | RTClib (Adafruit) | Rtc by Makuna |
| Ideal para | Relojes sencillos a 5 V | Casi cualquier proyecto; también ideal para ESP32 y Pico | Kits antiguos y proyectos de aprendizaje |
Pongamos la diferencia de precisión en números: 1 ppm significa una parte por millón, y un día tiene 86 400 segundos. Un cristal corriente de ±20 ppm puede desviarse hasta 1,7 segundos al día, unos 52 segundos al mes, y cuanto más te alejas de la temperatura ambiente, más cambia la frecuencia del cristal y mayor es el error. El DS3231, en cambio, lleva el cristal dentro del chip, mide la temperatura cada 64 segundos y corrige la frecuencia en consecuencia. Así logra ±2 ppm entre 0 y 40 °C, más o menos un minuto al año, y se mantiene dentro de ±3,5 ppm incluso de -40 a +85 °C.
¿Qué módulo RTC debo elegir?
- Proyecto nuevo, ESP32 o Pico: elige un DS3231. Funciona a 3,3 V y a 5 V, tiene alarmas y es el que da la hora más precisa. La diferencia de precio es mínima.
- Ya tienes un DS1307 y usas un Arduino Uno: úsalo sin problema; solo ten en cuenta un desfase de aproximadamente un minuto al mes y corrige la hora de vez en cuando.
- Tu kit de inicio traía un DS1302: sirve para aprender cómo funciona un RTC, pero no esperes un reloj que se mantenga exacto durante meses.
- ESP32 con conexión permanente a internet: empieza con NTP sin módulo; añade un DS3231 si necesitas saber la hora tras un corte de luz antes de que vuelva internet.
Lo más habitual es encontrar dos placas listas para usar: la ZS-042 con chip DS3231 y la Tiny RTC con DS1307. Ambas llevan además una EEPROM AT24C32 de 4 KB para guardar datos. Por eso es normal que, al ejecutar un escáner I2C, aparezca una segunda dirección junto a 0x68 (normalmente 0x57 en la ZS-042 y 0x50 en la Tiny RTC); esa dirección pertenece a la EEPROM, no al reloj. El DS1302, en cambio, no usa I2C: se comunica con su propio protocolo de 3 hilos y ocupa tres pines digitales.
Conexión del módulo RTC: Arduino Uno, ESP32 y Pico
| Pin del RTC | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 (DS3231) | 3V3(OUT), pin físico 36 (DS3231) |
| GND | GND | GND | GND |
| SDA | A4 | GPIO 21 | GP4 (I2C0) |
| SCL | A5 | GPIO 22 | GP5 (I2C0) |
| SQW / INT (opcional) | D2 (pin de interrupción) | Cualquier GPIO (p. ej. GPIO 4) | Cualquier pin GP (p. ej. GP15) |
En el Uno R3, los conectores SDA y SCL que hay junto al pin AREF también están unidos a A4 y A5, así que da igual cuáles uses. El RTC puede compartir los mismos dos cables con un LCD I2C o una pantalla OLED; cada dispositivo tiene su propia dirección y no hay conflicto. Mantener los cables por debajo de 20–30 cm evita errores de lectura aleatorios, sobre todo en la protoboard. Solo necesitas conectar el pin SQW/INT si vas a usar la alarma por hardware.
Instalar RTClib y ajustar la hora
- Abre el Gestor de bibliotecas del IDE de Arduino, escribe RTClib e instala la biblioteca de Adafruit. Cuando te pregunte por las dependencias, elige Install all para instalar también Adafruit BusIO. Si nunca has añadido una biblioteca, Cómo añadir una biblioteca en Arduino te lo explica paso a paso.
- Conecta el módulo como en la tabla anterior y coloca la pila en el portapilas.
- Sube el código de abajo. En la primera ejecución el módulo no conoce la hora, así que el código escribe en el RTC la hora de compilación de tu ordenador.
- Abre el Monitor Serie a 9600 baudios con el fin de línea "Nueva línea". Para ajustar la hora al segundo, escríbela con el formato 2026-11-03 14:30:00 y pulsa Enter.
- Desconecta el cable USB, espera unos minutos y vuelve a conectarlo. Si el reloj sigue correctamente desde donde estaba, el respaldo de la pila funciona.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc; // DS1307 kullanıyorsan: RTC_DS1307 rtc; / for a DS1307: RTC_DS1307 rtc;
5
6void setup() {
7 Serial.begin(9600);
8 if (!rtc.begin()) { // modül I2C hattında yok / module not found on the I2C bus
9 Serial.println(F("RTC bulunamadi / RTC not found"));
10 while (true);
11 }
12 if (rtc.lostPower()) { // ilk çalıştırma ya da pil bitmiş / first run or dead battery
13 rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // derleme saatini yaz / write the compile time
14 Serial.println(F("Saat derleme zamanina ayarlandi / Clock set to compile time"));
15 }
16 Serial.println(F("Ayar icin yaz / To set, type: 2026-11-03 14:30:00"));
17}
18
19void loop() {
20 // Seri monitörden saat geldiyse ayarla / set the time sent from the Serial Monitor
21 if (Serial.available()) {
22 String line = Serial.readStringUntil('\n');
23 int y, mo, d, h, mi, s;
24 if (sscanf(line.c_str(), "%d-%d-%d %d:%d:%d", &y, &mo, &d, &h, &mi, &s) == 6) {
25 rtc.adjust(DateTime(y, mo, d, h, mi, s));
26 Serial.println(F("Saat ayarlandi / Time set"));
27 }
28 }
29
30 DateTime now = rtc.now();
31 char buf[] = "DD.MM.YYYY hh:mm:ss"; // biçim şablonu / format template
32 Serial.print(now.toString(buf));
33 Serial.print(F(" "));
34 Serial.print(rtc.getTemperature()); // yalnız DS3231 / DS3231 only
35 Serial.println(F(" C"));
36 delay(1000);
37}rtc.begin() devuelve false si no encuentra el módulo en el bus I2C; en ese caso revisa primero el cableado. rtc.lostPower() lee el indicador de oscilador detenido (OSF) del DS3231: devuelve true si el módulo funciona por primera vez o si el reloj se paró porque se agotó la pila, y entonces el código ajusta el reloj a la hora de compilación. DateTime(F(__DATE__), F(__TIME__)) usa el momento en que el compilador generó tu código; como la carga tarda unos segundos, el reloj queda ligeramente atrasado, así que viene bien afinarlo desde el Monitor Serie. toString() sustituye las letras de la plantilla "DD.MM.YYYY hh:mm:ss" por los valores reales.
| Función | Qué hace |
|---|---|
| rtc.begin() | Inicia el módulo; devuelve false si no lo encuentra |
| rtc.adjust(DateTime(...)) | Escribe la hora y la fecha |
| rtc.now() | Lee la hora actual como un objeto DateTime |
| now.year(), now.month(), now.day() | Año, mes, día |
| now.hour(), now.minute(), now.second() | Hora (0–23), minuto, segundo |
| now.dayOfTheWeek() | Día de la semana: 0 = domingo, 6 = sábado |
| now.unixtime() | Segundos desde el 1 de enero de 1970; ideal para comparar dos momentos |
| now + TimeSpan(0, 1, 30, 0) | Suma 1 hora y 30 minutos (días, horas, minutos, segundos) |
| rtc.lostPower() / rtc.isrunning() | Indica si la hora es válida (DS3231 / DS1307) |
| rtc.getTemperature() | Temperatura del chip en °C (solo DS3231) |
Si usas un DS1307, la única diferencia es el nombre del objeto: escribe RTC_DS1307 rtc;, comprueba !rtc.isrunning() en lugar de lostPower() y borra la línea de getTemperature(). La primera vez que se alimenta, el DS1307 arranca con el oscilador detenido (bit CH a 1); adjust() borra ese bit y pone el reloj en marcha. En los 56 bytes de RAM respaldada por pila del DS1307 puedes guardar pequeños ajustes, como la hora de una alarma, con rtc.writenvram() y rtc.readnvram(); gracias a la pila, esos datos también sobreviven a los cortes de luz.
Mostrar la hora y la fecha en un LCD
Ver la hora en una pantalla en lugar del Monitor Serie convierte el proyecto en un reloj de escritorio de verdad. Un LCD I2C de 16x2 y el RTC se conectan al mismo bus SDA-SCL: el LCD suele estar en la dirección 0x27 o 0x3F y el RTC en la 0x68. El código siguiente escribe en la línea superior la fecha y la abreviatura del día, y en la inferior la hora y la temperatura que mide el DS3231. Para la conexión del LCD y la instalación de su biblioteca, echa un vistazo a Cómo usar una pantalla LCD I2C.
1#include <Wire.h>
2#include <RTClib.h>
3#include <LiquidCrystal_I2C.h>
4
5RTC_DS3231 rtc;
6LiquidCrystal_I2C lcd(0x27, 16, 2); // adres 0x27 ya da 0x3F / address 0x27 or 0x3F
7
8// dayOfTheWeek(): 0 = Pazar / 0 = Sunday
9const char* const days[7] = {"Paz", "Pzt", "Sal", "Car", "Per", "Cum", "Cmt"};
10int lastSecond = -1;
11
12void setup() {
13 lcd.init();
14 lcd.backlight();
15 if (!rtc.begin()) {
16 lcd.print("RTC yok!"); // modül bulunamadı / module not found
17 while (true);
18 }
19 if (rtc.lostPower()) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
20}
21
22void loop() {
23 DateTime now = rtc.now();
24 if (now.second() == lastSecond) return; // saniye değişmediyse yazma / skip until the second changes
25 lastSecond = now.second();
26
27 char line1[17], line2[17];
28 snprintf(line1, sizeof(line1), "%02d.%02d.%04d %s",
29 now.day(), now.month(), now.year(), days[now.dayOfTheWeek()]);
30 snprintf(line2, sizeof(line2), "%02d:%02d:%02d %2dC",
31 now.hour(), now.minute(), now.second(), (int)rtc.getTemperature());
32 lcd.setCursor(0, 0);
33 lcd.print(line1); // ör. / e.g. 03.11.2026 Sal
34 lcd.setCursor(0, 1);
35 lcd.print(line2); // ör. / e.g. 14:05:09 23C
36}El %02d de snprintf añade un cero delante de los números de una cifra, así la hora aparece como 09:05:03 en lugar de 9:5:3 y la longitud de la línea nunca cambia. Gracias a esa longitud fija no hace falta lcd.clear(); borrar la pantalla en cada vuelta provoca parpadeo. El código solo escribe en la pantalla cuando cambia el segundo, con lo que no ocupa el bus I2C sin necesidad. El array days contiene abreviaturas en turco; cámbialas por Dom, Lun, Mar, etc., manteniendo el domingo como primer elemento.
Alarmas y tareas programadas: riego automático y comedero para mascotas
Lo más útil de un RTC es hacer tareas según la hora: regar las plantas cada mañana a las 08:00, servir la comida del gato a las 19:30 o apagar la luz del acuario por la noche. Hay dos formas de hacerlo. La primera es comparar por software: lees la hora en loop() y compruebas si ha llegado el momento de una tarea. Es sencillo y puedes añadir tantas tareas como quieras. La segunda es la alarma por hardware del DS3231: en el momento fijado, el chip pone su pin INT en LOW y avisa a Arduino mediante una interrupción; incluso puede despertar a un microcontrolador dormido.
Un error habitual al comparar por software es buscar un segundo exacto, como now.second() == 0. Si hay un delay() largo en loop(), ese segundo puede pasar de largo y la tarea nunca se ejecuta. El código siguiente compara la hora y el minuto, guarda una clave formada por el día y el minuto para que la tarea no se repita en el mismo minuto y controla el tiempo de la bomba con millis(). La bomba se acciona mediante un módulo de relé; encontrarás la conexión de la bomba en el artículo sobre la mini bomba de agua.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc;
5
6const byte RELAY_PIN = 7;
7const byte RELAY_ON = LOW; // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
8const byte RELAY_OFF = HIGH;
9const unsigned long RUN_MS = 10000; // pompa 10 saniye çalışır / the pump runs for 10 seconds
10
11struct Task { byte hour; byte minute; };
12Task tasks[] = { {8, 0}, {19, 30} }; // her gün 08:00 ve 19:30 / every day at 08:00 and 19:30
13const byte TASK_COUNT = sizeof(tasks) / sizeof(tasks[0]);
14
15long lastRunKey = -1; // aynı dakikada ikinci kez çalışmasın / never run twice in one minute
16bool running = false;
17unsigned long startMs = 0;
18
19void setup() {
20 pinMode(RELAY_PIN, OUTPUT);
21 digitalWrite(RELAY_PIN, RELAY_OFF); // açılışta kapalı / off at start-up
22 rtc.begin();
23}
24
25void loop() {
26 DateTime now = rtc.now();
27 long key = (long)now.day() * 1440 + now.hour() * 60 + now.minute(); // gün + dakika / day + minute
28
29 for (byte i = 0; i < TASK_COUNT; i++) {
30 if (now.hour() == tasks[i].hour && now.minute() == tasks[i].minute && key != lastRunKey) {
31 lastRunKey = key;
32 running = true;
33 startMs = millis();
34 digitalWrite(RELAY_PIN, RELAY_ON); // pompayı aç / pump on
35 }
36 }
37
38 if (running && millis() - startMs >= RUN_MS) {
39 running = false;
40 digitalWrite(RELAY_PIN, RELAY_OFF); // pompayı kapat / pump off
41 }
42 delay(200);
43}Que la clave incluya el día es importante: si solo guardaras el minuto y tuvieras una única tarea, al día siguiente la clave seguiría siendo la misma en ese minuto y la tarea no volvería a ejecutarse. Para hacer un comedero, usa un servomotor en lugar del relé: girarlo a 90 grados en el momento de la tarea y devolverlo un segundo después abre la compuerta del depósito y deja caer una ración de comida. Para un riego más inteligente, lee un sensor de humedad del suelo en ese momento y no actives la bomba si la tierra ya está húmeda. El segundo ejemplo de abajo hace lo mismo con la alarma por hardware del DS3231.
1#include <Wire.h>
2#include <RTClib.h>
3
4RTC_DS3231 rtc;
5const byte ALARM_PIN = 2; // DS3231 SQW/INT -> D2 (kesme pini / interrupt pin)
6volatile bool alarmFlag = false;
7
8void onAlarm() { // kesme fonksiyonu kısa olmalı / keep the ISR short
9 alarmFlag = true;
10}
11
12void setup() {
13 Serial.begin(9600);
14 rtc.begin();
15 rtc.disable32K(); // 32K çıkışını kapat / turn off the 32K output
16 rtc.writeSqwPinMode(DS3231_OFF); // SQW pini alarm çıkışı olur / SQW becomes the alarm output
17 rtc.clearAlarm(1);
18 rtc.clearAlarm(2);
19 rtc.disableAlarm(2);
20
21 // Her gün 07:30:00; tarih kısmı yok sayılır / every day at 07:30:00; the date part is ignored
22 rtc.setAlarm1(DateTime(2026, 1, 1, 7, 30, 0), DS3231_A1_Hour);
23
24 pinMode(ALARM_PIN, INPUT_PULLUP); // INT çıkışı open-drain / INT is an open-drain output
25 attachInterrupt(digitalPinToInterrupt(ALARM_PIN), onAlarm, FALLING);
26}
27
28void loop() {
29 if (alarmFlag) {
30 alarmFlag = false;
31 rtc.clearAlarm(1); // temizlenmezse pin LOW kalır / the pin stays LOW until cleared
32 Serial.println(F("Alarm: mama vakti / Feeding time"));
33 // Servo, röle ya da buzzer kodunu buraya yaz / put your servo, relay or buzzer code here
34 }
35}El DS3231 tiene dos alarmas. La alarma 1 tiene resolución de un segundo; el modo DS3231_A1_Hour se dispara cuando coinciden la hora, los minutos y los segundos, es decir, todos los días a la misma hora. Con los demás modos puedes programar una alarma cada segundo (PerSecond), cada minuto (Second), cada hora (Minute), un día concreto del mes (Date) o un día concreto de la semana (Day). La alarma 2 tiene resolución de un minuto. El pin SQW/INT es una salida de drenador abierto (open-drain) activa en LOW: pasa a LOW cuando salta la alarma y se queda así hasta que se llama a clearAlarm(). Por eso lo mejor es activar solo un indicador en la función de interrupción y hacer el trabajo real en loop(). Para entender las interrupciones, consulta Interrupciones en Arduino.
¿Cuánto dura la pila de un RTC?
Calcular la duración de la pila es fácil: duración (horas) = capacidad de la pila (mAh) ÷ corriente consumida (mA). Una CR2032 tiene unos 220 mAh. En modo pila, el DS3231 consume en el peor caso unos 3 µA, es decir, 0,003 mA: 220 ÷ 0,003 ≈ 73 000 horas, unos 8 años. La pila solo se usa mientras falta VCC; si el módulo está en un aparato siempre enchufado, apenas se gasta y dura mucho más. En la práctica, el límite lo marcan casi siempre la vida útil en almacenamiento de la propia pila y el circuito de carga del módulo.
| Chip | Consumo de la pila | Duración calculada con una CR2032 (220 mAh) |
|---|---|---|
| DS1307 | ~0,5 µA | ~50 años; en la práctica limitada por la vida útil de la pila (unos 10 años) |
| DS3231 | ~3 µA (peor caso) | ~8 años |
| DS1302 | ~0,3 µA | Limitada por la vida útil de la pila |
| Módulo con cargador activo + CR2032 | Se fuerza corriente hacia la pila | Impredecible; la pila puede hincharse y agotarse pronto |
La trampa de la pila CR2032 y el circuito de carga
La mayoría de los módulos baratos con DS3231 (ZS-042) y DS1307 (Tiny RTC) incluyen un circuito de carga sencillo pensado en realidad para una pila recargable LIR2032. En la ZS-042 la corriente va de VCC a la pila a través de un diodo 1N4148 y una resistencia de 200 Ω; la Tiny RTC tiene un circuito parecido. El problema es que estos módulos se venden a menudo con una CR2032 no recargable. Cuando el módulo funciona a 5 V, los aproximadamente 4,3 V que quedan tras el diodo empujan corriente sin parar hacia la pila de litio de 3 V. Una pila que nunca debió cargarse puede hincharse, tener fugas y agotarse antes de tiempo, y acabas con el problema de "tiene pila pero el reloj se reinicia siempre".
- Si usas una CR2032, corta el camino de carga: en la ZS-042, desuelda la resistencia SMD de 200 Ω marcada con "201" cerca del conector de pines, o el diodo que hay a su lado. Para resistencias cuyo código no sepas leer, usa el decodificador de códigos SMD. Es la solución más habitual y segura.
- Si dejas el circuito como está, pon una LIR2032: la capacidad de la pila recargable (unos 40 mAh) es aproximadamente la quinta parte de la de una CR2032 (unos 220 mAh), pero se mantiene cargada mientras el módulo tenga alimentación.
- Si alimentas el módulo a 3,3 V: tras el diodo solo llegan unos 2,6 V a la pila; una LIR2032 nunca se carga del todo y a una CR2032 apenas le llega corriente. Aun así, quitar la resistencia es la solución más limpia.
- El cargador integrado del DS1302 viene desactivado al arrancar; si usas una CR2032, no lo actives por código.
- Mide la pila: una CR2032 nueva marca 3,0–3,2 V; cámbiala si baja de 2,5 V.
Uso del DS1302 (conexión de 3 hilos)

El módulo DS1302 tiene cinco pines: VCC, GND, CLK, DAT y RST. Como no usa I2C, no se conecta a A4-A5 sino a tres pines digitales cualesquiera; en el ejemplo de abajo DAT va a D4, CLK a D5 y RST a D2, y el módulo se alimenta con 5V. La RTClib de Adafruit no es compatible con el DS1302, así que instala la biblioteca Rtc by Makuna desde el Gestor de bibliotecas. El DS1302 tiene dos bits de protección: con la protección contra escritura activada no se puede ajustar la hora, y con el bit de parada del reloj activado el reloj no avanza. El código comprueba ambos y ajusta el reloj a la hora de compilación si la hora guardada no es válida.
1#include <RtcDS1302.h>
2
3ThreeWire myWire(4, 5, 2); // DAT, CLK, RST pinleri / DAT, CLK, RST pins
4RtcDS1302<ThreeWire> rtc(myWire);
5
6void setup() {
7 Serial.begin(9600);
8 rtc.Begin();
9 if (rtc.GetIsWriteProtected()) rtc.SetIsWriteProtected(false); // yazma korumasını kaldır / remove write protection
10 if (!rtc.GetIsRunning()) rtc.SetIsRunning(true); // saati başlat / start the clock
11
12 RtcDateTime compiled(__DATE__, __TIME__);
13 if (!rtc.IsDateTimeValid() || rtc.GetDateTime() < compiled) {
14 rtc.SetDateTime(compiled); // derleme saatine ayarla / set to compile time
15 }
16}
17
18void loop() {
19 RtcDateTime now = rtc.GetDateTime();
20 char buf[20];
21 snprintf(buf, sizeof(buf), "%02u.%02u.%04u %02u:%02u:%02u",
22 now.Day(), now.Month(), now.Year(), now.Hour(), now.Minute(), now.Second());
23 Serial.println(buf);
24 delay(1000);
25}La queja más frecuente sobre los módulos DS1302 es que el reloj se desvía varios minutos por semana. Una razón es que el chip necesita un cristal ajustado para una capacidad de carga de 6 pF, mientras que los módulos baratos pueden usar cristales de otro valor. Los cables largos y flojos también provocan errores de lectura en la línea serie del DS1302. Si tienes un DS1302, es un gran punto de partida para entender cómo funciona un RTC; pero si vas a construir un reloj que deba ser exacto durante meses, pásate al DS3231.
NTP en lugar de RTC en el ESP32: obtener la hora de internet
Como el ESP32 puede conectarse al Wi-Fi, muchas veces no necesita ningún módulo RTC: con NTP (Network Time Protocol) obtiene en pocos segundos la hora exacta de servidores de hora como pool.ntp.org. El núcleo de Arduino para ESP32 incluye las funciones configTzTime() y getLocalTime() para ello, y la zona horaria se indica con una cadena de reglas. Turquía se mantiene en UTC+3 sin horario de verano desde 2016, por eso la regla del código es un desfase fijo de +3 horas. En la España peninsular y en otras zonas con horario de verano usa la regla de Europa Central que aparece en el comentario del código; calcula por sí sola los días de cambio de hora.
El punto débil de NTP es que depende de internet: tras un corte de luz, hasta que arranca el router, o si cambia la contraseña del Wi-Fi, el ESP32 no puede saber la hora. El temporizador RTC interno del ESP32 conserva la hora durante el deep sleep, pero se pone a cero cuando se pierde por completo la alimentación. La solución más robusta combina ambos: al arrancar, si el ESP32 llega al servidor NTP sincroniza el DS3231 con la hora de internet; si no, lee la hora del DS3231, y vuelve a sincronizar una vez al día. Para más detalles sobre NTP, consulta Hora con NTP en el ESP32.
1#include <WiFi.h>
2#include <Wire.h>
3#include <RTClib.h>
4#include <time.h>
5
6const char* WIFI_SSID = "AgAdin"; // Wi-Fi ağ adı / Wi-Fi network name
7const char* WIFI_PASS = "Sifren"; // Wi-Fi şifresi / Wi-Fi password
8// Türkiye: UTC+3, yaz saati yok / Turkey: UTC+3, no daylight saving
9// Orta Avrupa / Central Europe: "CET-1CEST,M3.5.0,M10.5.0/3"
10const char* TZ_INFO = "<+03>-3";
11
12RTC_DS3231 rtc;
13unsigned long lastSync = 0;
14
15void syncFromNtp() {
16 struct tm t;
17 if (getLocalTime(&t, 10000)) { // en fazla 10 sn bekle / wait up to 10 s
18 rtc.adjust(DateTime(t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec));
19 Serial.println("DS3231 NTP ile ayarlandi / DS3231 synced from NTP");
20 }
21 lastSync = millis();
22}
23
24void setup() {
25 Serial.begin(115200);
26 Wire.begin(21, 22); // SDA, SCL pinleri / SDA, SCL pins
27 rtc.begin();
28
29 WiFi.begin(WIFI_SSID, WIFI_PASS);
30 unsigned long start = millis();
31 while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) delay(250);
32
33 if (WiFi.status() == WL_CONNECTED) {
34 configTzTime(TZ_INFO, "pool.ntp.org", "time.google.com");
35 syncFromNtp();
36 } else {
37 Serial.println("Wi-Fi yok, DS3231 saati kullaniliyor / No Wi-Fi, using the DS3231");
38 }
39}
40
41void loop() {
42 DateTime now = rtc.now();
43 char buf[] = "DD.MM.YYYY hh:mm:ss";
44 Serial.println(now.toString(buf));
45
46 if (WiFi.status() == WL_CONNECTED && millis() - lastSync > 86400000UL) {
47 syncFromNtp(); // günde bir kez eşitle / sync once a day
48 }
49 delay(1000);
50}El RTC interno de la Raspberry Pi Pico
El chip RP2040 de la Raspberry Pi Pico incluye un bloque RTC, mientras que el RP2350 de la Pico 2 hace lo mismo con un temporizador siempre activo (AON timer). En MicroPython ambos se usan con la misma clase machine.RTC: RTC().datetime() lee o escribe la hora como (año, mes, día, día de la semana, horas, minutos, segundos, subsegundos), y time.localtime() también usa este reloj. Pero este reloj no tiene pila: cuando la Pico se queda sin alimentación, MicroPython arranca el reloj el 1 de enero de 2021 a las 00:00.
Aquí hay una trampa que sorprende a los principiantes: por defecto, Thonny sincroniza el reloj de la Pico con el de tu ordenador al conectarse. Así, durante las pruebas todo parece correcto, pero cuando conectas la Pico a un cargador de móvil o a una batería, el reloj vuelve a 2021. La solución es conectar un DS3231 a la Pico y ajustar el RTC interno a partir de él al arrancar. El código siguiente no necesita ningún archivo de controlador; lee los siete primeros registros del DS3231 por I2C y los convierte de BCD a decimal. Con una Pico W también puedes obtener la hora de internet con ntptime.settime(); como devuelve la hora UTC, tendrás que sumar tú el desfase de tu zona horaria. Si eres nuevo con la Pico, empieza por ¿Qué es la Raspberry Pi Pico?.
1from machine import Pin, I2C, RTC
2import time
3
4i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100000)
5DS_ADDR = 0x68 # DS3231 ve DS1307 adresi / DS3231 and DS1307 address
6
7def bcd2dec(b):
8 return (b >> 4) * 10 + (b & 0x0F)
9
10def dec2bcd(d):
11 return ((d // 10) << 4) | (d % 10)
12
13def ds_read():
14 b = i2c.readfrom_mem(DS_ADDR, 0x00, 7) # saniyeden yıla 7 kayıt / 7 registers, seconds to year
15 return (2000 + bcd2dec(b[6]), bcd2dec(b[5] & 0x1F), bcd2dec(b[4] & 0x3F),
16 bcd2dec(b[2] & 0x3F), bcd2dec(b[1] & 0x7F), bcd2dec(b[0] & 0x7F))
17
18def ds_write(y, mo, d, h, mi, s):
19 # 24 saat biçiminde yazar; 4. bayt haftanın günü (1-7) / writes 24-hour time; 4th byte is day of week (1-7)
20 i2c.writeto_mem(DS_ADDR, 0x00, bytes([dec2bcd(s), dec2bcd(mi), dec2bcd(h), 1,
21 dec2bcd(d), dec2bcd(mo), dec2bcd(y - 2000)]))
22
23# İlk kurulumda bir kez çalıştır, sonra satırı sil / run once on first setup, then delete the line
24# ds_write(2026, 11, 3, 14, 30, 0)
25
26y, mo, d, h, mi, s = ds_read()
27RTC().datetime((y, mo, d, 0, h, mi, s, 0)) # dahili RTC'yi ayarla / set the internal RTC
28
29while True:
30 t = time.localtime() # artık dahili RTC'den okunur / now read from the internal RTC
31 print("{:02d}.{:02d}.{} {:02d}:{:02d}:{:02d}".format(t[2], t[1], t[0], t[3], t[4], t[5]))
32 time.sleep(1)Ideas de proyectos con un módulo RTC
- Reloj de escritorio digital con calendario: muestra la hora, la fecha y la temperatura que mide el DS3231 en un LCD, una OLED o una matriz LED.
- Riego automático de plantas: comprueba la humedad del suelo cada mañana y, si hace falta, activa la bomba durante un tiempo fijo.
- Comedero para mascotas: abre la compuerta del depósito con un servo dos o tres veces al día y deja caer una ración de comida.
- Registrador de datos con marca de tiempo: guarda las lecturas de temperatura y humedad junto con la fecha y la hora en un módulo de tarjeta SD y luego haz la gráfica en Excel.
- Timbre escolar o de taller: haz sonar un zumbador o un timbre con relé al inicio y al final de cada clase, y sáltate los fines de semana con dayOfTheWeek().
- Temporizador para acuario y luz de cultivo: enciende la luz por la mañana y apágala por la tarde, cambiando el brillo poco a poco con PWM para simular el amanecer y el atardecer.
Errores frecuentes y cómo solucionarlos
- "RTC no encontrado", begin() devuelve false: SDA y SCL están intercambiados, GND no es común o el módulo no recibe alimentación. Ejecuta un escáner I2C y comprueba si aparece la dirección 0x68.
- Valores sin sentido como el año 2165, 165 u 85: no llegan datos del chip y todos los bytes leídos valen 0xFF. Revisa el cableado; si alimentas un DS1307 a 3,3 V, pásalo a 5 V.
- Tras cada reinicio el reloj vuelve al mismo momento: la línea rtc.adjust() sigue sin condición dentro de setup(); vincúlala a lostPower().
- El reloj se pone a cero tras un corte de luz: la pila está agotada, puesta al revés o no está. Mide su tensión y recuerda que el circuito de carga puede haber estropeado la CR2032.
- El reloj se desvía varios minutos por semana: lo causan el cristal del DS1307 o del DS1302 y los cambios de temperatura. Pásate a un DS3231 o sincroniza la hora con NTP de forma periódica.
- La hora difiere exactamente una o varias horas: la zona horaria o el horario de verano están mal configurados. Escribe la hora local en el RTC; si usas NTP, elige la regla de zona horaria correcta.
- El DS3231 marca más temperatura que la de la habitación: ese valor es la temperatura del propio chip, con una precisión de ±3 °C y afectada por el calentamiento de la placa. Para la temperatura ambiente usa un sensor aparte.
En resumen, el DS3231 es la elección correcta para casi cualquier proyecto que necesite fecha y hora; el DS1307 cumple en proyectos sencillos a 5 V y el DS1302 sirve para aprender. En el ESP32 usa NTP cuando haya internet y un DS3231 cuando no; en la Pico, ajustar el RTC interno desde un DS3231 al arrancar es lo más fiable. En la app BlueGrays encontrarás proyectos paso a paso con esquemas y código: configuración de un reloj DS1302 y reloj con LCD, reloj y calendario de matriz de puntos con DS1307, reloj digital con RTC en el ESP32, hora de internet con NTP y un registrador de temperatura con marca de tiempo.
Preguntas frecuentes
¿Funciona un módulo RTC sin pila?
Mientras VCC esté conectado, el reloj funciona y se puede leer. Pero en cuanto se va la luz, el reloj se detiene o se reinicia y tendrás que ajustarlo de nuevo en el siguiente arranque. Como la razón de ser de un RTC es conservar la hora durante los cortes de luz, la pila es casi siempre necesaria; si usas un DS1307 sin pila, su pin VBAT debe conectarse a GND.
¿Qué es mejor, el DS3231 o el DS1307?
El DS3231 es mejor en casi todos los casos. Gracias a su cristal integrado y compensado en temperatura, se desvía solo un minuto al año aproximadamente, mientras que un DS1307 puede desviarse hasta un minuto al mes. Además, el DS3231 funciona de 2,3 a 5,5 V, así que sirve directamente con el ESP32 y la Pico, y tiene dos alarmas y un sensor de temperatura. Con RTClib el código de ambos es casi idéntico.
¿Cuánto dura la pila de un módulo RTC?
Cuando el módulo funciona solo con la pila, un DS3231 consume como máximo unos 3 µA y un DS1307 alrededor de 0,5 µA. Sobre el papel, una CR2032 de 220 mAh dura más de 8 años con esas corrientes. En la práctica, la vida útil de la pila y el circuito de carga del módulo pueden acortar ese tiempo; en un módulo con el cargador activo, una CR2032 puede agotarse mucho antes.
¿Por qué mi módulo RTC reinicia la hora?
Hay tres causas habituales: la línea rtc.adjust() de setup() que vuelve a poner la hora de compilación en cada arranque, una pila agotada o colocada al revés, y un circuito de carga que ha estropeado la CR2032. Primero vincula la línea adjust() a lostPower(); después mide la tensión de la pila con un multímetro y cámbiala si está por debajo de 2,5 V.
¿Necesito un módulo RTC con el ESP32?
No si el dispositivo siempre está conectado a internet; el ESP32 obtiene la hora exacta por NTP en pocos segundos. En proyectos donde internet puede fallar, donde hay que saber la hora tras un corte de luz antes de que arranque el router o que funcionan totalmente sin conexión, añadir un DS3231 es la opción más segura. Lo ideal es usar ambos y sincronizar el DS3231 con NTP una vez al día.
¿Se puede poner una CR2032 en un módulo DS3231?
Sí, pero en módulos con circuito de carga, como la ZS-042, primero tienes que cortar el camino de carga. Si desueldas la resistencia de 200 Ω (código 201) o el diodo que hay a su lado, una CR2032 funcionará de forma segura durante años. Si no quieres modificar la placa, usa una pila recargable LIR2032.
Proyectos para hacer después de leer esto
Ver todos los proyectos
Configuración del módulo de reloj RTC DS1302
Pones en marcha un pequeño módulo de reloj que no olvida la hora aunque el Arduino se apague. El módulo tiene su propia pila diminuta y, una vez puesta la hora, la fecha y la hora aparecen cada segund

Reloj RTC DS1302 con pantalla LCD
Un pequeño reloj de mesa que no pierde la hora aunque se vaya la luz. El módulo de reloj DS1302 guarda la hora gracias a su propia pila diminuta; cada segundo el Arduino la lee y escribe la hora y la

Reloj digital con ESP32 y RTC DS1307 (I2C + LCD)
En este proyecto, mostramos la hora y la fecha en una pantalla LCD I2C de 16x2 mediante el módulo de reloj en tiempo real (RTC) DS1307. El DS1307 es un RTC con batería de respaldo que conserva la hora incluso si el ESP32 se apaga. Ambos módulos comparten la misma línea I2C (SDA/SCL), por lo que aprendemos a controlar varios dispositivos con solo dos cables de señal. Con este proyecto conocerás el protocolo I2C, el funcionamiento de los módulos RTC y la visualización dinámica en pantallas LCD.

Reloj y calendario de matriz de puntos (MAX7219, DS1307)
Un panel luminoso para tu mesa o tu pared que muestra la hora y la fecha con texto en movimiento. En la pantalla LED de 8x32 se ve un reloj de números grandes cuyos dos puntos parpadean cada segundo;

Reloj matricial, calendario y estación meteorológica (MAX7219, DS1307)
Un panel de texto en movimiento para tu mesa o tu pared que muestra por turnos la hora, la fecha y el clima de la habitación. En la pantalla LED de 8x32 aparece primero la temperatura en grados Celsiu

Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
¡Construye un registrador de temperatura con marca de tiempo con ESP32! Lee temperatura/humedad del DHT22 cada minuto, obtén la hora real del DS1307 RTC y registra en tarjeta microSD como CSV. El OLED muestra en vivo la temperatura (fuente grande), porcentaje de humedad, marca de tiempo y contador de registros. El archivo `/temp_log.csv` en la tarjeta SD se abre en Excel, Google Sheets o Python pandas para análisis — perfecto para monitoreo de invernadero, seguimiento de temperatura del hog

ESP32: hora real desde Internet con NTP
El ESP32 se conecta a Wi-Fi y obtiene la hora real con precisión de milisegundos desde servidores NTP (Network Time Protocol). Gracias a `configTzTime()`, se aplica automáticamente la zona horaria de Turquía (TRT, UTC+3) y el cambio DST se gestiona mediante la cadena POSIX TZ. La hora se muestra en el monitor serie y en una pantalla LCD I2C opcional. `configTzTime()` inicia el servicio SNTP; se realizan resincronizaciones periódicas mientras hay acceso a la red, y el reloj del sistema sigue avan

Reloj digital con display de 7 segmentos de 4 dígitos
Un reloj digital luminoso de cuatro cifras, parecido al del horno de la cocina. El módulo de reloj DS1302 guarda la hora y cada segundo el Arduino lee las horas y los minutos y los muestra en el indic
Más artículos
App BlueGrays
Monta este circuito paso a paso en tu teléfono
Esquema, código y lista de piezas en una sola pantalla. Más de 160 proyectos de Arduino, ESP32 y Pico listos para montar.
Escanea con tu teléfono
Apunta la cámara al código y se abrirá la tienda de apps de tu teléfono.
o ábrela en la tienda

