Haga clic para más productos.
No se encontraron productos.

Tutorial RTC DS1307 y EEPROM AT24C

79087

En este tutorial trabajaremos con el Modulo  RTC (Real Time Clock) DS1307, podremos saber la hora exacta, día mes año e incluso el día de la semana, a su vez gracias a una EEPROM que trae el modulo podemos guardar los datos sin que se borren al apagar el Arduino.

Agregando el modulo El RTC a nuestro Arduino es como darle un reloj y un calendario, con el DS1307 nuestro Arduino sabrá la hora exacta como segundos, minutos y horas. También podremos saber el día del mes, día de la semana, mes, y año. EL ds1307 tiene implementado su calendario hasta el 2100 y tiene en cuenta también los años bisiestos.

 Módulo I2C RTC DS1307 AT24C32

La comunicación entre el Arduino y el Modulo RTC es por I2C (pines SDA y SCL), También tiene un pin (SQ) que envía un pulso cada segundo (1 Hz), que nos puede servir para sincronizar otros componentes o para realizar un contador de segundos. A su vez, el modulo tiene un espacio para soldar un DS18B20 (sensor de temperatura) y acceder a este a través del pin DS

 Módulo I2C RTC DS1307 AT24C32

Al reverso tiene un socket para insertar una batería de 3V, que le permite al RTC mantener en funcionamiento la hora y fecha cuando se apague el Arduino o se le quiete la alimentación principal. Esta batería dependiendo de la marca y del tiempo apagado, puede durar desde los 3 hasta los 10 años aproximadamente.

Este módulo también trae una memoria no volátil, una EEPROM  AT24C32 con capacidad para 32Kbit o 4Kbytes y también se comunica con el Arduino a través del bus I2C, bus que comparte con el DS1307, de esta forma solo necesitamos 2 pines del Arduino para controlar el RTC y EEPROM del Módulo.



Conexiones entre Modulo RTC DS1307 y Arduino

Adaptador LCD a I2C

Arduino Uno, Nano, Mini.

Arduino Mega , DUE

Arduino Leonardo

  SCL

A5

21

3

  SDA

A4

20

2

  VCC

5V

5V

5V

  GND

GND

GND

GND

  SCL

A5

21

3

 Conexion RTC DS1307 y Arduino

Como se observa la conexión es como cualquier conexión I2C.



Librería para el RTC DS1302


Para este ejemplo usaremos la librería RTClib de Adafruit, librería que pueden descargarlo en:

https://github.com/adafruit/RTClib

Necesitamos descargar e importar dicha librería al IDE de Arduino.



Actualizando la Hora y fecha de nuestro DS1307


Cuando  adquirimos un DS1307, al no traer su pila, no tiene la hora actualizada, cada vez que quitamos la pila el DS1307 pierde la hora, estableciéndose como hora 0:0:0 y fecha 00/00/00,

Este ejemplo solo se utiliza para poner a la hora nuestro DS1307:

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

void setup () {
  Serial.begin(9600);
  rtc.begin(); //Inicializamos el RTC
  Serial.println("Estableciendo Hora y fecha...");
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  Serial.println("DS1307 actualizado con la hora y fecha que se compilo este programa:");
  Serial.print("Fecha = ");
  Serial.print(__DATE__);
  Serial.print("  Hora = ");
  Serial.println(__TIME__);
}

void loop () {
}

De esta forma cada vez que el Arduino se enciende  o se reinicia, el Arduino actualizara al DS1307 con la hora que fue compilado el programa.

Después de cargar el código anterior, tan pronto termine la carga  Arduino actualizará la hora, pero cada vez que se habré el monitor serial o se reinicie el Arduino, nuevamente vuelve a actualizase con la misma hora de compilación.

Actualizar hora y fecha DS1307

El monitor serial solo nos sirve para verificar que nuestro programa es correcto. Después de esto hay que compilarlo y cargarlo de nuevo, para que tenga la hora correcta.


Después de cargar este programa se debe cargar otro distinto, o uno en blanco, para evitar que se esté actualizando con la misma hora de compilación cada vez que se reinicia o enciende el Arduino.

Si deseamos actualizar a una hora y fecha en específico deben de modificar a la siguiente línea de código:

rtc.adjust(DateTime(2016,6,10,18,29,0));//2016,Junio,10,18 h,29 min,0 seg


Obteniendo Hora y Fecha del DS1307


En este ejemplo realizaremos la lectura de los segundos, minutos y horas del DS1307, y a su vez también obtendremos la fecha.

Para realizar este ejemplo usamos el siguiente código:

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

int segundo,minuto,hora,dia,mes;
long anio; //variable año
DateTime HoraFecha;

void setup () {
  Serial.begin(9600);
  rtc.begin(); //Inicializamos el RTC
  
}

void loop () {
    HoraFecha = rtc.now(); //obtenemos la hora y fecha actual
    
    segundo=HoraFecha.second();
    minuto=HoraFecha.minute();
    hora=HoraFecha.hour();
    dia=HoraFecha.day();
    mes=HoraFecha.month();
    anio=HoraFecha.year();

    //Enviamos por el puerto serie la hora y fecha.
    Serial.print("hora = ");
    Serial.print(hora);
    Serial.print(":");
    Serial.print(minuto);
    Serial.print(":");
    Serial.print(segundo);
    Serial.print("  Fecha = ");
    Serial.print(dia);
    Serial.print("/");
    Serial.print(mes);
    Serial.print("/");
    Serial.print(anio);
    Serial.println();
    delay(1000);
}

Como se observa el código es simple y fácil de entender

En el void Setup solamente inicializamos el RTC y en void loop() realizamos la lectura del DS1307, esto se hace en una sola línea de código:

    HoraFecha = rtc.now(); //obtenemos la hora y fecha actual

Cada vez que se llama a rtc.now se actualiza la hora y se guarda en el objeto HoraFecha que es de la clase DateTime propia de la librería RTClib

Seguidamente guardamos la hora y fecha en variables separadas, pero también podemos trabajar directamente con el objeto HoraFecha si lo deseamos por ejemplo: HoraFecha. minute()

A continuación mostramos el monitor serial de este ejemplo:

 hora y fecha DS1307

A este ejemplo, podemos agregar variables tipo cadena para mostrar o tener la fecha en formato de texto, por ejemplo para el nombre de los días de la semana y los nombres del mes.

El ejemplo muestra los cambios para mostrar la fecha de forma textual:

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

char nombreDia[7][12] = {"Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado"};
char nombreMes[12][12]= {"Enero", "Febrero", "Marzo", "Abril", "Mayo",  "Junio", "Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"};
int segundo,minuto,hora,dia,mes,diaDeLaSemana;
long anio; //variable año

DateTime HoraFecha;

void setup () {
  Serial.begin(9600);
  rtc.begin(); //Inicializamos el RTC
}

void loop () {
    HoraFecha = rtc.now(); //obtenemos la hora y fecha actual
    
    segundo=HoraFecha.second();
    minuto=HoraFecha.minute();
    hora=HoraFecha.hour();
    dia=HoraFecha.day();
    mes=HoraFecha.month();
    anio=HoraFecha.year();
    diaDeLaSemana=HoraFecha.dayOfTheWeek();
    

    //Enviamos por el puerto serie la hora y fecha.
    Serial.print(hora);
    Serial.print(":");
    Serial.print(minuto);
    Serial.print(":");
    Serial.print(segundo);
    Serial.print(" , ");
    Serial.print(nombreDia[diaDeLaSemana]);
    Serial.print(" ");
    Serial.print(dia);
    Serial.print(" de ");
    Serial.print(nombreMes[mes-1]);
    Serial.print(" del ");
    Serial.print(anio);
    Serial.println();
    delay(1000);
}

La salida del monitor serial es el siguiente:

 hora y fecha DS1307 formato 2

Luz con encendido y apagado automático

En este ejemplo mostraremos el código para encender un foco, o una salida digital que puede ser un motor, un electrodoméstico, una lámpara reflectora, etc, en un horario determinado por nuestro programa.

Por ejemplo para encender la luz de nuestra fachada todos los días  de 7:00pm a 11:00pm, o para encender una bomba o electroválvula para establecer un horario de riego en un jardín, etc.

El ejemplo que mostramos a continuación activa la salida digital 2  de lunes a viernes de 6:30 pm a 11:30pm

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

int segundo,minuto,hora,dia,mes,diaDeLaSemana;

DateTime HoraFecha;

void setup () {
  Serial.begin(9600);
  rtc.begin(); //Inicializamos el RTC
  pinMode(2, OUTPUT);
}

void loop () {
    HoraFecha = rtc.now(); //obtenemos la hora y fecha actual
    
    segundo=HoraFecha.second();
    minuto=HoraFecha.minute();
    hora=HoraFecha.hour();
    diaDeLaSemana=HoraFecha.dayOfTheWeek(); //0:Dominogo, 1:Lunes, 2:Martes ...
    
    float horas=hora+minuto/60.0;

    //condicion: >Domingo y  <sabado    y   >6.30pm  y <11.30pm
    if(diaDeLaSemana>0&&diaDeLaSemana<7 && horas>18.5&&horas<23.5)
    {
      digitalWrite(2, HIGH);
      Serial.print("Salida digital 13 = ON");
    }
    else
    {
      digitalWrite(2, LOW);
      Serial.print("Salida digital 13 = OFF");
    }

    //Enviamos por el puerto serie la hora y fecha.
    Serial.print("   hora = ");
    Serial.print(hora);
    Serial.print(":");
    Serial.print(minuto);
    Serial.print(":");
    Serial.print(segundo);
    Serial.print("  dia de La semana = ");
    Serial.print(HoraFecha.dayOfTheWeek());
    Serial.println();
    delay(1000);
}

Para cambiar de horario solo hay que modificar la condición, notar que los minutos convertimos a horas para trabajar la condición de forma más corta.

Los serial println() solo los usamos para fines demostrativos pues solo es para monitorear el estado:

 Temporizador RTC1307

Librería para la EMPROM AT24C32


La librería del RTC DS1307 también tiene funciones para usar la EEPROM AT24C32, pero nosotros usaremos otra librería, más especializada y con mayor cantidad de funciones:

Usaremos la librería AT24CX escrita por Christian Paul, librería que lo pueden descargar desde su GitHub:
AT24CX Library: https://github.com/cyberp/AT24Cx

Con esta librería podemos programar las siguientes memorias EEPROM: AT24C32, AT24C64, AT24C128, AT24C256 y AT24C512



Lectura y escritura en la EEPROM AT24C32


En este ejemplo guardaremos datos en nuestra EEPROM y posteriormente realizaremos la lectura de los datos guardados.

El código para manejar la EEPROM es el siguiente:

#include <Wire.h>
#include <AT24CX.h>

AT24C32 EepromRTC;

void setup() {
  Serial.begin(9600);
}


void loop() {
  // read and write byte
  byte variable_byte=235;
  int variable_int=3000;
  long variable_long=48300011;
  float variable_float=3.14;
  char cadena[30] = "Naylamp Mechatronics";
  
  Serial.println("Guardando datos en la EEPROM...");
  
  EepromRTC.write(1,variable_byte); // posiscion 1:ocupa 1 byte de tamaño
  EepromRTC.writeInt(2,variable_int); // posiscion 2:ocupa 2 bytes de tamaño 
  EepromRTC.writeLong(4,variable_long); // posiscion 4: ocupa 4 bytes de tamaño 
  EepromRTC.writeFloat(8,variable_float); // posiscion 8:ocupa 4 bytes de tamaño 
  EepromRTC.writeChars(12, cadena, 30);// posiscion 16 y  20 bytes de tamaño 

  
  Serial.println("Leyendo datos guardados...");

  byte a = EepromRTC.read(1);
  int b = EepromRTC.readInt(2);
  long c = EepromRTC.readLong(4);
  float d = EepromRTC.readFloat(8);
  char cadena2[30];
  EepromRTC.readChars(12,cadena2,30);

  Serial.print("Dato byte: ");Serial.println(a);
  Serial.print("Dato int: "); Serial.println(b);
  Serial.print("Dato long: "); Serial.println(c);
  Serial.print("Dato float: "); Serial.println(d);
  Serial.print("Dato Cadena : "); Serial.println(cadena2);
  Serial.println();

  delay(5000);
}

En el ejemplo anterior es una muestra de cómo leer y escribir datos en la EEPROM AT24C32, se muestra la forma de escribir diferentes tipos de variables.

Cada posición de la memoria es de un byte, si guardamos una variable debemos tener en cuenta el tamaño en bytes de esa variable, y no usar esas posiciones de memoria para guardar otros datos, pues borraríamos el dato inicial.

Podemos guardar en cualquier posición, por ejemplo un dato en la posición 10, otro en la posición 100 y otro en la posición 1500, la cosa es asegurarnos que los datos no se crucen. Para la EEPROM AT24C32, la primera posición es 0 y la posición máxima que podemos usar es de 4095, pues la memoria es de 4kBytes (4096Bytes) de tamaño

A continuación mostramos la salida del monitor serial del ejemplo:

Arduino EEPROM AT24C32

Productos relacionados
Artículos relacionados
25 Comentarios
  • Ma***

    Ma*** 20/10/2021 Responder

    Hola!!!, muchas gracias por la información, el programa me funciona sin embargo como podría agregar el cambio de horario de forma automática, he agregado condiciones if, pero no me da los datos
  • Lu** *****ue

    Lu** *****ue 08/09/2020 Responder

    Si quisiera modificar los registros del ds1307 o ds3231 ,como seria ?
  • sa******

    sa****** 06/06/2020 Responder

    aqui encontre como conectar un rtc al microcontrolador

    https://www.youtube.com/watch?v=0jzvvjIfrdY&t=83s
  • ta**** ****ia

    ta**** ****ia 30/05/2020 Responder

    You really have great talent to write wonderful articles. Keep it going.
  • Gu*******

    Gu******* 07/08/2019 Responder

    la memoria EEPROM que se maneja en el tutorial es del arduino o del modulo rtc???
    • Gu*******

      Gu******* 07/08/2019 Responder

      ademas si desconecto el modulo de la alimentación no me guarda la hora y fecha
  • Ro******

    Ro****** 01/05/2019 Responder

    Hola, muchas gracias por este tutorial, e aprendido mucho sobre el uso de este módulo.
    Con respecto al uso de la librería para manejar la EEPROM AT24C32, no me a funcionado la opción de cambiar la dirección I2C de la memoria con AT24C32(0x57); en el sketch.
    Solo funciona modificando el archivo AT24CX.h de la librería.
    Saludos, Rodrigo.
  • lu**

    lu** 21/02/2018 Responder

    disculpa y como lo puedo incluir en una pantalla con modulo 12c
  • Ba*****

    Ba***** 04/02/2018 Responder

    Hola, Al compilar me salta este error: Arduino:1.8.5 (Windows Store 1.8.10.0) (Windows 10), Tarjeta:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

    C:UsersalbitDesktopsketch_feb04asketch_feb04asketch_feb04a.ino: In function 'void loop()':

    sketch_feb04a:22: error: 'class DateTime' has no member named 'dayOfTheWeek'

    diaDeLaSemana=HoraFecha.dayOfTheWeek(); //0:Dominogo, 1:Lunes, 2:Martes ...

    ^

    sketch_feb04a:36: error: expected '}' at end of input

    }

    ^

    exit status 1
    'class DateTime' has no member named 'dayOfTheWeek'

    Este reporte podría tener más información con
    "Mostrar salida detallada durante la compilación"
    opción habilitada en Archivo -> Preferencias.
  • Se*******

    Se******* 28/06/2017 Responder

    Hola Naylamp, pase el ejemplo Search_IC y me da como resultado Found X57, vi que en el primer comentario decis que hay que agregar AT24C32(byte index) en el void setup(); lo agregue en el Skecht y me un error. Por favor necesito tu ayuda como lo puedo resolver, no entendi muy bien tu respuesta, disculpa mi ignorancia, tengo un ArduinoUNO y un DS3231 y deseo guardar una fecha en la EEPROM.
    Desde ya muchisimas gracias
    • Al**

      Al** 13/05/2020 Responder

      Hola Sebastian, tuve el mismo problema. Lo que me funciono a mi fue poner:
      void setup() {
      Serial.begin(9600);
      AT24C32(0x57);
      }
      Como dijo Naylamp, pero luego tuve que soldar en el modulo tres cosas. Si te fijas, en una esquina del modulo vas a ver que hay 6 cuadraditos que dicen A0, A1, A2. Bueno, yo lo que hice fue puentear A0 con el de arriba, A1 con el de arriba, y a" con el de arriba.
      Espero te sirva!
      Saludos
    • Na*****

      Na***** 16/07/2017 Responder

      Hola Sebastián el setup debe quedar así:

      void setup() {

      Serial.begin(9600);

      AT24C32(0x57);

      }
      • Al*****

        Al***** 11/08/2017 Responder

        Tengo el mismo problema que Sebastian, tuve que cambiar en el archivo.h la direccion I2C. También hice en el setup
        void setup() {
        Serial.begin(9600);
        AT24C32(0x57);
        }

        Pero no se logra cambiar la dirección I2C.
  • Jo***

    Jo*** 06/06/2017 Responder

    Tengo una duda... como puedo cambiarle la bateria al modulo? o que arreglo le puedo hacer si me marca" FECHA:01/01/2000 HORA:00:00:00"??
    • Na*****

      Na***** 18/06/2017 Responder

      Hola Jorge, si es un problema de batería, siempre que se paga el circuito cunado nuevamente se enciende la fecha se pierde e inicia con la hora y fecha que indicas. Mientras este encendido debe trabajar normal. Solo comprarle una pila nueva e insertarla en el del modulo.
  • Os***

    Os*** 25/05/2017 Responder

    Una Pregunta,
    ¿Como hago para que cada ves que conecte el arduino no se me reinicie la hora?
    siempre que lo conecto de nuevo sale la hora en que fue compilado y cargado
    • Na*****

      Na***** 28/05/2017 Responder

      Hola Oscar, como se explica en el tutorial solo se debe hacer una sola vez, y tan pronto después de cargar el programa en donde se configura la hora, se debe de cargar otro programa que ya no modifique la hora. Si has incluido las líneas de configurar de la hora en tu programa, tan pronto después de cargar el programa a tu arduino, comenta las líneas de configuración y nuevamente carga el programa.
  • sa***

    sa*** 30/04/2017 Responder

    Hola, gracias por vuestros ejemplos, he probado solo dos, la puesta en horay va bien. Pero en la obtencion de la fecha y hora me carga bien el programa pero en el puerto serie no me da la hora correcta. Por favor me pueden ayudara entender porque me da estos valores
    hora=165:165:85 Fecha=165/165/2165

    Muchas gracias y felicitaciones por sus articulos.
    Santi
    • Na*****

      Na***** 04/05/2017 Responder

      Hola Santi, los resultados que obtienes es porque no hay una comunicación correcta entre el arduino y el RTC, revisa tus conexiones y/o cambia tus cables de conexión.
      • sa***

        sa*** 12/05/2017 Responder

        Muchas gracias por responderme, efectivamente era un error en la comunicación.
        Muchas gracias de nuevo por toda vuestra ayuda.
        Saludos desde A Coruña, España.
        Santi
  • Pa**

    Pa** 25/02/2017 Responder

    Hola,
    He probado varios modulos , y todos desfasan varios segundos al dia. Hace dos meses, programe uno y ahora tiene media
    hora de diferencia, y otro 45 minutos. Como es esto posible?
    • Na*****

      Na***** 07/03/2017 Responder

      Hola Paco, los DS1307 con el tiempo siempre se van a retrasar, por eso es bueno siempre dejar a nuestro sistema alguna forma de poder configurar la hora. EL retraso es debido a la influencia de la temperatura en el oscilador, provocando que varía su frecuencia. Una solución sería ver si el retraso es constante, de ser así podrías compensar por programa el error. Podes usar también otro RTC de mayor precisión como el DS3231, que incluso funciona con la misma librería del este tutorial.
  • Ju*****

    Ju***** 21/01/2017 Responder

    Buenas tardes, viendo este trabajo y la libreria para el manejo de la eeprom 24c32 me surgio un problema. Como puedo cargar la dirección I2C correspondiente a la memoria. La libreria viene por defecto para la dirección 0x50 pero algunos modulos RTC traen otra dirección de eeprom. De momento solo pude realizarlo modificando el valor directamente en el archivo .h correspondiente a la libreria.
    • Ju**

      Ju** 29/06/2017 Responder

      Hola Julian, lo has podido resolver, porque tengo el mismo inconveniente, mi EEPROM esta en la dirección 0X57. Saludos y gracias
    • Na*****

      Na***** 01/02/2017 Responder

      Hola Julián, sin modificar la librería, agrega AT24C32(byte index) en el void setup(); donde index es un numero entre 0 y 7 correspondientes a A2|A1|A0 de los pines de dirección de la eeprom. La librería asigna la dirección a 0x50 - 0x57.
Dejar un comentario
Deja su comentario

Menú

Ajustes

Crear una cuenta gratuita para usar listas de deseos.

Registrarse