El módulo DS3231, un reloj para Arduino

46
16627
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.

DS3231_front

 

DS3231_back

 

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.

DS3231

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.

DS3231

 

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:

 

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.

 

El resultado que se obtiene debe ser similar a lo que se muestra a continuación.

monitor serial

 

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.

 

 

46 Comentarios

  1. 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

  2. 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

  3. 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

  4. 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);
    }

  5. 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.

  6. 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.

  7. 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.

  8. 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

  9. 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.

  10. 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

  11. 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

  12. 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.

      • 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».

    • 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

Dejar respuesta

Please enter your comment!
Please enter your name here