Ocasionalmente en algún proyecto surge la necesidad de conocer la hora del día. Por ejemplo una estación meteorológica que almacena en su memoria las mediciones que realiza debe agregarles la hora en que fueron efectuadas, o el timbre de una escuela, que debe sonar en determinados horarios son casos en los que necesitamos algún tipo de “reloj”. Una solución es implementarlo a través de retardos de software, pero si no son lo suficientemente precisos, a lo largo de las semanas o meses, este reloj se irá corriendo y ya no marcará la hora precisa. Afortunadamente se pueden adquirir circuitos integrados que realizan esta función, denominados “Real Time Clock” o “Relojes de Tiempo Real”, que también están disponibles como módulos para conectar al Arduino. En este artículo veremos en detalle como utilizar uno de ellos.
Existen chips RTC de distintas marcas, pero una de las mas populares es MAXIM, que comercializa una gran variedad de ellos, con distintas características y aplicaciones. En esta ocasión, analizaremos el funcionamiento del módulo denominado ZS-042, que incluye un integrado DS3231, un RTC de alta precisión que emplea para comunicarse un bus serie del tipo I²C (“I cuadrado C”). Este chip no solo lleva cuenta de la hora sino también la fecha (día, mes, año y día de la semana) haciendo los ajustes necesarios según la cantidad de días de cada mes e incluso los años bisiestos. Es capaz de seguir funcionando con una tensión de 3 Voltios consumiendo muy poca corriente, lo que le permite usar una batería como alimentación, de manera de poder seguir llevando la hora aún cuando se apaga el equipo en el que está conectado.
Descripción
El módulo ZS-042 tiene pocos componentes, cuyas funciones se pueden explicar viendo el esquemático que se muestra a continuación
El circuito integrado U1 es el DS3231, Reloj de Tiempo Real, alimentado a través de la batería BAT conectada en su zócalo J3. Los pines SQW, 32K, SCL y SDA se conectan al conector J1 de 6 pines y al J2 de 4 contactos. Estos pines tienen resistencias de “pull-up” en el puente RP1. El integrado U2 es la memoria EEPROM 24C32 marca Atmel capaz de almacenar 4 KB de datos, que se puede utilizar para guardar información sensible que no se debe perder aún cuando se quita la alimentación del equipo, ya que es del tipo no-volátil. Los pines A0, A1 y A2 permiten direccionar la memoria y están conectados a Vcc a través del puente de resistencias RP2. Si se quisiera cambiar la dirección se deben poner algunos de estos pines a masa soldando los puentes que están en el lugar de R2, R3 y R4. Los capacitores C1 y C2 desacoplan la alimentación de ambos circuitos integrados.
El LED D1 indica que el módulo está alimentado, ya que se conecta directamente a VCC a través de una resistencia limitadora de corriente (R1). El circuito formado por R5 y D2 es un cargador para la batería: el diodo impide que la misma se descargue a través de VCC cuando falla la alimentación principal y la resistencia limita la corriente de carga. Aquí vale una aclaración importante. El módulo que utilicé para este artículo tiene una batería de litio CR2032 que no es recargable. Este parece ser un tópico de discusión frecuente en varios foros, donde algunos usuarios comentan que sus módulos cuentan con una batería LIR2032, que si es recargable. Intentar cargar una CR2032 puede ser un inconveniente, por lo que se puede reemplazar la batería o anular el circuito de carga cortando una pista o desoldando alguno de los dos componentes (R5 o D2).
Conexiones
Las conexiones se pueden realizar a través del conector de 6 pines (J1) o los cuatro “pads” de conexión del lado opuesto (J2). La función de cada pin es la siguiente:
32K: Este pin es una salida del DS3231 y consiste en una señal de 32768 Hz que puede emplearse en algún otro circuito.
SQW: Es otra salida del DS3231 y puede ser configurado para producir señales de distintas frecuencias o como salida de alarma que se activa a una determinada hora y fecha o cada cierto tiempo.
SCL y SDA: Comunicación I²C con el DS3231 y la memoria
VCC: Alimentación (5 Voltios)
GND: masa o negativo de la alimentación
Las conexiones al Arduino son directas. Es imprescindible cablear la alimentación (VCC y GND) y los datos (SDA y SCL), el resto de las conexiones son opcionales y dependerán del uso que le demos al módulo. En el caso de una placa UNO, SDA y SCL están ubicados en los pines analógicos A4 y A5 respectivamente. Si usamos otra placa debemos revisar su ubicación precisa.
Programación
Uno de los grandes beneficios de usar una placa Arduino es la disponibilidad de librerías para manejar distintos módulos, y este caso no es una excepción. De hecho, hay varias librerías que sirven para el DS3231, la cuales varían en su funcionamiento y la cantidad de funciones disponibles. En el ejemplo de mas abajo, he utilizado la librería Sodaq_DS3231 que puede descargarse aquí.
//Test RTC DS3231 #include <Wire.h> #include "Sodaq_DS3231.h" char weekDay[][4] = {"Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab" }; //año, mes, dia, hora, minutos, segundos y dia de la semana (0=Domingo hasta 6=Sabado) //Si se escribe una hora o fecha inexistente se puede interferir con la normal operación del RTC DateTime dt(2016, 9, 23, 19, 47, 0, 5); //año, mes, dia, hora, min, seg, diasem void setup() { Serial.begin(115200); // Abre el puerto serie para mostrar valores leídos Wire.begin(); //Inicializa la comunicacion con el RTC rtc.begin(); //Inicializa el RTC rtc.setDateTime(dt); //Establece fecha y hora cargada en "dt" } void loop() { DateTime now = rtc.now(); //Leer datos del RTC y mostrar Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.date(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); Serial.print(weekDay[now.dayOfWeek()]); Serial.println(); delay(1000); }
La librería empleada utiliza otra llamada “Wire” que se encarga de los detalles del bus I2C.
Al principio del ejemplo se define la variable “dt” del tipo “DateTime” y se la carga con los datos de fecha y hora actuales, para “poner en hora” al RTC.
En la función Setup se abre el puerto serie, para enviar datos a la PC que se pueden ver en la ventana Terminal, se inicializa el bus I2C, el reloj y se cargan los datos de fecha y hora actual.
En loop, cada un segundo se lee el RTC con la función rtc.now y se los carga en la variable now. En las instrucciones siguientes se sacan los distintos valores por el puerto serie.
Para comprobar el correcto funcionamiento del RTC se puede hacer la siguiente prueba: Hacer funcionar el programa para que la función “rtc.setDateTime (dt)” ajuste la hora actual. Luego, comentar esa función y cargar el programa de nuevo. A continuación, desconectar la alimentación del Arduino y por tanto del RTC (el reloj debe seguir funcionando con la batería). Esperar unos minutos y conectar la alimentación nuevamente. Si no se ven datos en la ventana Terminal, cerrarla y abrirla de nuevo. En esta ventana deberíamos ver la hora actual, indicando que el reloj ha seguido llevando el tiempo a pesar de estar desconectado.
Espero que el tutorial les haya sido de utilidad. Como siempre, cualquier consulta o idea, déjenla como un comentario.
Excelente explicación profesor!!!
Gracias! Espero que te sirva
Excelente post! obtuve la información que buscaba
pero tengo un problema con este modulo, no mantiene la hora, lo uso para un proyecto donde esta alimentado constantemente pero luego de unos días la hora se pierde y el dispositivo deja de funcionar para lo que fue programado. Cuando voy a revisar la pila esta agotada. No deberia estar agotada ya que estaba se mantenia alimentado a través del conector J1. ¿Que puede estar pasando?
Hola Alejandro. Fijate que bateria tiene tu placa. Si es una CR2032, no es recargable y según la fecha de fabricación del módulo y el cuidado que se haya tenido al manipularlo, puede que haya perdido su carga y debas reemplazarla.
Hola,
Tengo un proyecto de automatizar el timbre de una escuela utilizando un arduino y un RTC, pero no soy muy hábil en programación y menos de un Arduino. ¿Alguien me puede compartir un código que me pueda servir? Mi correo es: aritmetica47@gmail.com. Gracias!
Hola, gracias por el tutorial… mi DS3231 ya tiene la hora actual… podrias explicarme como usar la libreria Sodaq_DS3231 para programar alarma; ya he hecho algun codigo pero me sale error al definir “Alarm.alarmRepeat(18, 0, 0, EventoEnciendeLuz);” no se si es que la libreria no reconoce ese comando, gracias
Buenas noches, muy interesante el tutorial, me genera una pregunta, estoy realizando un cronómetro utilizando estos módulos, he logrado hacerlo funcionar pero quisiera que por medio del primero me lleve la cuenta de cronómetro y por medio de otro la hora, es decir dos módulos DS3231, se que debo conectarlos utilizando efectivamente la comunicación I2c pero al realizar un sketch de escaneo de dispositivos i2c que traen las librerías siempre me arroja que uno u otro tienen la dirección 0x68, así que para poder leer uno o otro deben tener direcciones diferentes, sería posible que me indicaran como realizo este procedimiento, el asignarles direcciones para posteriormente durante el void loop llamarlas en diferentes momentos y así mostrar el conteo en el que va cada uno mediante un display de 7 segmentos.
Muchas gracias por su atención.
Buenas noches, muy interesante el tutorial, me genera una pregunta, estoy realizando un cronómetro utilizando estos módulos, he logrado hacerlo funcionar pero quisiera que por medio del primero me lleve la cuenta de cronómetro y por medio de otro la hora, es decir dos módulos DS3231, se que debo conectarlos utilizando efectivamente la comunicación I2c pero al realizar un sketch de escaneo de dispositivos i2c que traen las librerías siempre que arroja que uno u otro tienen la dirección 0x68, así que para poder leer uno o otro deben tener direcciones diferentes, sería posible que me indicaran como realizo este procedimiento, el asignarles direcciones para posteriormente durante el void loop llamarlas en diferentes momentos y así mostrar el conteo en el que va cada uno mediante un display de 7 segmentos.
Muchas gracias por su atención.
Seguí las indicaciones al pie de la letra. Copié el codigo. Solo modifiqué la fecha y la hora. Compiló sin problemas. Ejecutó perfecto.
Hice la prueba apagando el pc.
Cuando volví a conectar el arduino Nano funcionó correctamente. No perdió la hora durante la desconexion.
Estoy muy satisfecho con sus explicaciones Profetolocka.
Desde Colombia un abrazo y felicitaciones por tan excelente tutorial.
Impecable, SIMPLE Y CLARO.
Muchisimas Gracias !
Debería tenerse MUY en cuenta que este modelo (ZS-042), SIEMPRE debe ponerse una pila LIR 2032, no la CR2032