Tutorial RTC DS1307 y EEPROM AT24C Leave a comment

Comparte este Post

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 I2CArduino Uno, Nano, Mini.Arduino Mega , DUEArduino Leonardo
  SCLA5213
  SDAA4202
  VCC5V5V5V
  GNDGNDGNDGND
  SCLA5213

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


Comparte este Post

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Abrir chat
Powered by
0

Tu carrito