El módulo DS3231 permitirá que podamos llevar un registro detallado del transcurso del tiempo en nuestro microcontrolador. Los proyectos que podemos llevar a cabo con este módulo van desde estaciones de sensores hasta alarmas y sondas de registro de datos.
En múltiples ocasiones vamos a necesitar que nuestros proyectos lleven un conteo estricto sobre el tiempo transcurrido. Esto es imposible de conseguir con nuestro Arduino debido a que el mismo no está capacitado para ello. Necesitamos un circuito que sea capaz de mantener el conteo del tiempo aún cuando el microcontrolador esté apagado.
Afortunadamente existe el módulo DS3231.
Este módulo incluye un circuito integrado, el DS3231, además de un regulador de tensión, una batería de 3.6 voltios (de las que se encuentran en los motherboard de las computadoras), entre otras cosas (es capaz de medir temperatura).
Se comunica con Arduino utilizando el protocolo I2C, por lo que encontraremos los pines VCC, GND, SCL y SDA.
Buscando por Internet me he encontrado con una librería muy útil para comunicarse con este dispositivo. Ha sido desarrollada por alguien que tiene un blog llamado Hardware Hacks.
La librería la podemos encontrar en el siguiente enlace.
Una vez se ha descargado e instalado la librería podemos proceder a probar nuestro módulo. Como siempre, cada vez que se vaya a utilizar la interfaz I2C los pines A4 y A5 deben ser reservados para conectar el SDA y SCL, respectivamente.
Las conexiones con Arduino se deben realizar de la siguiente manera.
Con las conexiones hechas, se procede a la configuración inicial del módulo. Es necesario llevar a cabo un proceso de asignación de fecha y hora. Esta información será almacenada en el circuito integrado y se mantendrá en el tiempo gracias a la pila con la que cuenta el dispositivo.
El código para setear la hora es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#include <DS3231.h> #include <Wire.h> DS3231 Clock; void setup() { // Se inicial la interfaz I2c Wire.begin(); // Se inicia la Comunicación Serial Serial.begin(9600); //Se establece el modo horario en 12 horas (false = 24h) Clock.setClockMode(true); //Se establece el año Clock.setYear((byte)(14)); //Mes Clock.setMonth((byte)05); //Dia de la semana (no lo estoy considerando) //Clock.setDoW((byte)dia); //Día Clock.setDate((byte)22); //Hora Clock.setHour((byte)8); //Minutos Clock.setMinute((byte)11); //Segundos Clock.setSecond((byte)0); } void loop() { } |
No estoy considerando el día de la semana ya que no me parece relevante. Esta librería me ha dado problemas cuando la seteo en 24 horas debido a que luego de las 15 horas regresa a 10. Supongo que algo tiene que ver con los 5 bits que requeriría ir mas allá del 16. En fin, utilizándola en 12 horas trabaja muy bien.
La hora que he establecido en este ejemplo es las 8:11 PM, del 22 de mayo de 2014.
Ahora les presentaré el código que se utiliza para rescatar la hora de nuestro dispositivo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <DS3231.h> #include <Wire.h> DS3231 Clock; byte year, month, date, DoW, hour, minute, second; void setup() { // Se inicial la interfaz I2c Wire.begin(); // Se inicia la Comunicación Serial Serial.begin(9600); } void loop() { delay(1000); //Se rescata la información Clock.getTime(year, month, date, DoW, hour, minute, second); //Se imprime Serial.print(date, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/"); Serial.print(year, DEC); Serial.print(" "); Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.println(second, DEC); } |
El resultado que se obtiene debe ser similar a lo que se muestra a continuación.
La librería cuenta con algunas otras opciones interesantes como alarmas y funciones de oscilador. Dentro del paquete se pueden encontrar algunos ejemplos.
Espero que la información suministrada sea de utilidad para todos y todas. Saludos.
Que tal Anthony está muy buena tu información, quiero ocupar el Arduino como timmer y me surgen estas dudas: Cuando recupero la info de la hora, cómo puedo hacerle para que dependiendo de esta se ponga en 1 un puerto? siendo más específico, si fueran las 6 am quisiera que encienda un foco y cuando sean las 6 pm que se apague. Ya se cómo tengo que decir que se ponga de 1 y en 0 un pin, lo que no logro hacer funcionar es que la lectura de la hora, minuto o segundo las compare con un valor numérico. Cuando pongo la condición If (hora>=6; hora<=12;){….. con el valor que toma de hora ya no hace nada, tengo la ecuación hora=(now.hour(),DEC); hora está declarada como un entero. Alguna idea? Saludos
con un rele. es lo que estoy intentando hacer, pero me surge un problema que cuando desconecto el reloj del arduino y lo conecto a las 2 o x horas las horas estan totalmente mal (ejemplo: hoy puse en hora el DS3231 a las 5:50 ahora son las 20:55 y el reloj me mostro 28 horas y 47 minutos) ya medi la pila del reloj y esta todo ok. no se que puede ser.
Es un error en la librería. Necesito cambiar esa versión. En Internet se encuentra la versión corregida
Con el relé se puede, mi problema no es tanto con qué encender el foco, sino más bien el tratamiento que se le da a la lectura del rtc y en función de eso llevar a cabo una acción o una sub rutina. Algo no estoy haciendo bien que cuando pregunto por la hora la lee muy bien e imprime el valor de la hora pero después no la actualiza, algo no estoy haciendo bien. Pero no doy con el «que».
Adrian, te mande mensaje mp por facebook. gracias.
Que tal amigo, muchas gracias. He recibido tu mensaje y ya te lo contesté, cualquier ayuda en cuanto al tema me sirve de mucho. Estamos en contacto por el facebook. Saludos.
Probablemente es un error de la librería del reloj
Recuerda que Arduino posee la función loop que se ejecuta infinitas veces. Eso quiere decir que siempre que el Arduino esté encendido podrás verificar el estado de la hora y tomar decisiones en base a ello
Necesitas colocar la condición dentro de un IF y declarar una salida digital que se colocará en HIGH si la condición se cumple
Arduino:1.6.7 (Windows 10), Placa:»Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)»
Opciones de compilación cambiadas, reconstruyendo todo
reloj1:1: error: #include expects «FILENAME» or
#includeÂ
^
reloj1:2: error: #include expects «FILENAME» or
#includeÂ
^
exit status 1
#include expects «FILENAME» or
Sugerencia de que pasa? Segui el montaje y el primer codigo , instale la libreria
MI error es este, lo hago todo tal cual, me compila perfecto, pero en el monitor me sale esto, ayuda porfavor!
165/85/165 25:165:165
165/85/165 25:165:165
165/85/165 25:165:165
165/85/165 25:165:165
165/85/165 25:165:165
165/85/165 25:165:165
usaste el mismo código?
Si, el mismo codigo vaya, lo seguí paso a paso y me pone eso :S, que puede ser??
sí, use el mismo codigo, ayuda porfavor ;(
Compartenos el código
Si estas usando un Arduino mega debes usar los pines 21 para SCL y 20 SDA
Estoy usando arduino uno….
Hola me pasa exactamente lo mismo, y ya he ensayado con otros codigos que he encontrado, y simpre me pasa lo mismo me compilan bien pero en el monitor me sale eso. Que puedo hacer?
esta mal conectado los cables del rtc a arduino
No está mal conectado. A menos que uses un Arduino que no sea UNO o ATmega328P. Tienes que verificar los puertos I2C del Arduino que estés utilizando.
El error que se produce para leer en modo 24 horas se debe a un bug en dicha función de la librería.
Solo hay que cambiar la línea incorrecta
tempBuffer = bcdToDec(Wire.read());
por la correcta
tempBuffer = Wire.read();
Dejo aquí la función corregida completa, que hay que cambiar en el archivo DS3231.cpp
void DS3231::getTime(byte& year, byte& month, byte& date, byte& DoW, byte& hour, byte& minute, byte& second) {
byte tempBuffer;
bool PM;
bool h12;
Wire.beginTransmission(CLOCK_ADDRESS);
Wire.write(uint8_t(0x00));
Wire.endTransmission();
Wire.requestFrom(CLOCK_ADDRESS, 7);
second = bcdToDec(Wire.read());
minute = bcdToDec(Wire.read());
tempBuffer = Wire.read();
h12 = tempBuffer & 0b01000000;
if (h12) {
PM = tempBuffer & 0b00100000;
hour = bcdToDec(tempBuffer & 0b00011111);
} else {
hour = bcdToDec(tempBuffer & 0b00111111);
}
DoW = bcdToDec(Wire.read());
date = bcdToDec(Wire.read());
month = bcdToDec(Wire.read() & 0b01111111);
year = bcdToDec(Wire.read());
}
hola. Lo que dices es cierto, ahora me funciona en 24 horas. Lo gracioso es que ya no me va en 12 horas pero no fue por cambiar si el código sino que desde antes no leía bien, no sé por qué porque hace tiempo las 12 horas funcionan bien.
Saludos y gracias.
Disculpa, muy buena informacion la verdad, no sabia muy bien el funcionamiento de arduino hasta que me encontré con esta tu pagina.
podrias ayudarme? necesito que enciende un led (que representa un foco) cuando
8am=<tiempo<=1pm AND 4pm <= tiempo =< 7pm …..encerio seria de mucha ayuda porfavor, no conosco el lenguaje :s
Lee la hora y usa un IF
al momento de imprimir/mostrar la fecha hay que hacer que se muestre de esa forma.
Verifica las conexiones del sensor
Verifica las conexiones
Hola, oye como puedo imprimir en el LCD, por que intente utilizar el siguiente formato, pero me marca error.
lcd.write(minute, DEC);
me dice que minute no puede ser utilizada como función.
Para solucionar el problema coloqué:
lcd.write(«»);
lcd.write(minute,DEC);
lcd.write(«:);
etc… etc…
y con la primera linea se soluciona el problema.
GRACIAS.
Gracias por el aporte amigo
Hola lo primero agradezco la explicación gracias por el gran trabajo.
Mi problema es que cuando los segundos cambian de 60 a 1 me lo imprime por un lcd i2c mal osea imprime un 1 y un carácter extraño.
Verifica con el Serial el dato que se está enviando al LCD para ver qué debería imprimir
Muchísimas gracias. Me la he pasado leyendo diferentes explicaciones y todas las que encontré resultan ser muy complicadas. Tu explicación es fácil y práctica, y sobretodo te permite utilizar la información del reloj para que el microcontrolador efectúe tareas a horas específicas.
Gracias amigo por tus comentarios
Buenas noches monte el programa y cuando lo subo da la hora pero me la cambia se mantiene si tengo conectado el pin vin del arduino al pin de sqw del ds3231y al desconectarlo se desconfigura ya que vuelve a la hora inicial que hago este es: como hago para mantener la hora cuando no haya suministro de energia.
#include
#include
#include
// el rtc se conecta a 3.3v con scl-A5 y sda en A4-el tm1637 se conecta a 5.v
#include
#include
#include
#define CLK 6
#define DIO 7
TM1637Display display(CLK, DIO);
DS3231 Clock;
bool h12, PM;
byte year, month, date, DoW, hour, minute, second;
void setup() {
display.setBrightness(0x0f);
Wire.begin();
// Se inicial la interfaz I2c
Wire.begin();
// Se inicia la Comunicación Serial
Serial.begin(9600);
//Se establece el modo horario en 12 horas (false = 24h)
Clock.setClockMode(true);
//Se establece el año
Clock.setYear((byte)(17));
//Mes
Clock.setMonth((byte)03);
//Dia de la semana (no lo estoy considerando)
//Clock.setDoW((byte)dia);
//Día
Clock.setDate((byte)9);
//Hora
Clock.setHour((byte)6);
//Minutos
Clock.setMinute((byte)44);
//Segundos
Clock.setSecond((byte)0);
}
void ReadDS3231()
{
int second,minute,hour;
uint8_t segto;
second=Clock.getSecond();
minute=Clock.getMinute();
hour=Clock.getHour(h12, PM);
display.showNumberDec(hour*100+minute, true);
delay(500);
segto = 0x80 | display.encodeDigit(hour%10);
display.setSegments(&segto, 1, 1);
delay(500);
}
void loop() {
ReadDS3231();
delay(1000);
//Se rescata la información
Clock.getTime(year, month, date, DoW, hour, minute, second);
//Se imprime
Serial.print(date, DEC);
Serial.print(«/»);
Serial.print(month, DEC);
Serial.print(«/»);
Serial.print(year, DEC);
Serial.print(» «);
Serial.print(hour, DEC);
Serial.print(«:»);
Serial.print(minute, DEC);
Serial.print(«:»);
Serial.println(second, DEC);
}
Verifica la pila del módulo
Estas haciendo algo mal. O la batería de tu módulo está muerta
Perdona mi ignorancia pero son dos códigos distintos?
O un código con los dos programas uno detrás de otro?
Hay un código para setear la hora y el otro es para poner un ejemplo en funcionamiento
No debe haber problemas
he usado tu codigo, pero no logro obtener la distincion entre am o pm. Que condgo deberia agregar par identificar esto, sin afectar la libreria.
Hola. Es estrictamente necesario que hagas la distinción en AM/PM? Cuando se programa es mas fácil usar el formato 24H
Buen día,
Me arroja el siguiente error al ejecutar el código:
Arduino: 1.8.7 (Windows 8.1), Board: «Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)»
C:\Users\rodrigo_guiza\Documents\Arduino\sketch_oct10b\sketch_oct10b.ino: In function ‘void loop()’:
sketch_oct10b:17:9: error: ‘class DS3231’ has no member named ‘getTime’
Clock.getTime(year, month, date, DoW, hour, minute, second);
^
exit status 1
‘class DS3231’ has no member named ‘getTime’
Me puedes ayudar con esto.
Saludos
Rodrigo Guiza
Cómo hiciste para instalar la librería?
Hola que tal estoy haciendo un timbre escolar pero me salta este error y ya no se que es:
C:\Users\User\Documents\Arduino\TIMBRE_CON_IF\TIMBRE_CON_IF.ino: In function ‘void loop()’:
TIMBRE_CON_IF:20:9: error: ‘class DS3231’ has no member named ‘getTime’
Clock.getTime(year, month, date, DoW, hour, minute, second);
^
exit status 1
‘class DS3231’ has no member named ‘getTime’
no se si me pudiera ayudar
Busca los ejemplos de la librería que estás usando
Hola
Estoy haciendo un reloj y necesito que cuando esté en 11 este 11 AM y cuando llegue a 12 se ponga 12 PM
Gracias de antemano
Eso se logra verificando la documentación de la librería