Todos somos conscientes de que la mayoría de las MCU utilizadas en nuestros proyectos son independientes del tiempo; es decir, no son conscientes del tiempo que les rodea. Está bien para la mayoría de nuestros proyectos, pero de vez en cuando, cuando se ocurre una idea en la que mantener el tiempo es fundamental, el módulo RTC de precisión DS1307 resulta útil. Es adecuado para una amplia gama de proyectos, incluidos relojes, temporizadores y alarmas, así como registro de datos y marcas de tiempo.

Descripción general del hardware

Este módulo se basa en el chip RTC DS1307 de alta capacidad y la EEPROM AT24C32, los cuales han existido por un tiempo y tienen un buen soporte de librería.

Chip RTC DS1307

En el corazón del módulo se encuentra un chip RTC extremadamente preciso y de bajo costo de Maxim: el DS1307. Maneja todas las funciones de cronometraje y se comunica con el microcontrolador a través de I2C.

El DS1307 puede realizar un seguimiento de segundos, minutos, horas, días, fechas, meses y años. Puede funcionar en formato de 12 horas o de 24 horas y tiene un indicador AM/PM. Para meses con menos de 31 días, ajusta automáticamente la fecha al final del mes, incluidas las correcciones de año bisiesto (válido hasta 2100).

Otra característica interesante del DS1307 es el pin SQW, que se puede programar para generar una de cuatro frecuencias de onda cuadrada: 1 Hz, 4 kHz, 8 kHz o 32 kHz.

El DS1307 requiere un cristal externo de 32 kHz para el cronometraje, cuya frecuencia se ve fácilmente afectada por la temperatura externa. Aunque este cambio en la frecuencia es insignificante, se suma.

Puede parecer un problema, pero no lo es. En realidad, hace que el reloj se atrase unos dos minutos al mes.

Batería de respaldo

El IC DS1307 incorpora una entrada de batería para mantener un cronometraje preciso incluso cuando se interrumpe la alimentación principal del dispositivo.

El circuito integrado de detección de energía monitorea continuamente el estado de VCC para detectar fallas de energía y cambia automáticamente al suministro de respaldo. Esto significa que incluso en el caso de un corte de energía, el IC aún puede mantener el tiempo.

Para energía de respaldo, la parte inferior de la placa alberga un soporte de batería para una celda de pila de litio de 20 mm y 3 V. Cualquier batería CR2032 encajará muy bien aquí.

Suponiendo que utilices una batería de tipo botón de 47 mAh completamente cargada y mantenga el consumo de corriente del chip en un mínimo de 300 nA, la batería debería poder alimentar el RTC durante al menos 17 años sin necesidad de una fuente de alimentación externa.

47mAh/300nA = 156666,67 horas = 6527,78 días = 17,87 años

EEPROM 24C32 integrado

El módulo RTC DS1307 también incluye un chip AT24C32 EEPROM (no volátil) de 32 bytes (4K x 8 bits) con 1 000 000 de ciclos de escritura. Este chip realmente no tiene nada que ver con el RTC, pero puede ser útil para cosas como el registro de datos o el almacenamiento de cualquier otro dato que desee que no sea volátil.

La EEPROM 24C32 se comunica a través de I2C y comparte el mismo bus I2C que el DS1307. Integrada tiene una dirección I2C fija de 0x50.

La EEPROM AT24C32 está clasificada para 1.000.000 de ciclos de escritura, por lo que no se desgastará durante las aplicaciones normales de registro de datos, siempre y cuando no esté escribiendo datos cada segundo.

Función oculta del módulo: DS18B20

El módulo RTC DS1307 tiene una disposición para instalar un sensor de temperatura DS18B20 que a menudo pasa desapercibido.

El DS18B20 se puede instalar utilizando los tres orificios de montaje en la esquina superior derecha, cerca del portapilas (marcado como U1).

Después de instalar el DS18B20, podrás obtener lecturas de temperatura del pin DS. Estas lecturas se pueden usar para compensar la desviación del tiempo basada en la temperatura.

Suelda el DS18B20 según la polaridad que se muestra en la serigrafía. También podrías necesitar una resistencia de 4,7 K entre VCC y DS.

Interfaz I2C

El módulo tiene una interfaz I2C simple que ocupa dos direcciones. La dirección I2C fija del chip DS1307 RTC es 0x68, y la dirección I2C fija de la EEPROM 24C32 es 0x50.

Las señales SDA y SCL, así como la alimentación y la conexión a tierra, también se dividen en el otro lado del módulo para permitir que estas señales se transmitan en bucle a otro módulo.

Para habilitar la comunicación, las líneas SDA y SCL tienen resistencias pull-up de 4.7K.

Especificaciones técnicas

Aquí están las especificaciones:

Para obtener más información sobre el DS1307 RTC y el chip EEPROM 24C32, consulta las hojas de datos.

Asignación de pines del módulo RTC DS1307

El módulo DS1307 RTC tiene 7 pines en total. El pinout es el siguiente:

SQW El pin emite una de cuatro frecuencias de onda cuadrada: 1 Hz, 4 kHz, 8 kHz o 32 kHz.

DS El pin debe proporcionar lecturas de temperatura si se instala un sensor de temperatura DS18B20 utilizando los tres orificios de montaje en la esquina superior derecha, cerca del portapilas (marcado como U1).

SCL es un pin de reloj en serie para la interfaz I2C.

SDA es un pin de datos en serie para la interfaz I2C.

VCC proporciona energía al módulo. Puedes conectarlo a una fuente de alimentación de 5 voltios.

GND es el pin de tierra.

BAT es una entrada de suministro de respaldo para cualquier celda de litio estándar de 3V u otra fuente de energía para mantener la hora exacta cuando se interrumpe la alimentación principal del dispositivo.

Cableado de un módulo RTC DS1307 a un Arduino

Conectemos el RTC al Arduino.

Las conexiones son sencillas. Comienza conectando el pin VCC a la salida de 5V de Arduino y el pin GND a tierra. Ahora nos quedan los pines que se usan para la comunicación I2C. Ten en cuenta que cada placa Arduino tiene diferentes pines I2C que deben conectarse correctamente. En las placas Arduino con el diseño R3, SDA (línea de datos) y SCL (línea de reloj) están en los encabezados de los pines cerca del pin AREF. También se conocen como A5 (SCL) y A4 (SDA).

Consulta la siguiente tabla para obtener una referencia rápida.

El siguiente diagrama muestra cómo conectar todo.

Instalación de la librería uRTCLib

Se necesita mucho esfuerzo para comunicarse con un módulo RTC. Afortunadamente, la librería uRTCLib se creó para ocultar todas las complejidades, permitiéndonos emitir comandos simples para leer los datos RTC. Es una librería simple pero poderosa que también admite la programación de la salida SQW, que no es compatible con muchas librerías RTC.

Para instalar la librería, ve a Programa > Importar librería > Añadir librerías..  Espera a que el Administrador de librerías descargue el índice y actualice la lista de librerías instaladas.

Filtra la búsqueda ingresando ‘urtclib‘ . Busca uRTCLib de Naguissa. Haz clic en esa entrada y luego elije Instalar.

Al final del tutorial, también incluimos código para leer y escribir la EEPROM 24C32 integrada. Si estás interesado, deberás instalar la librería uEEPROMLib. Busca ‘ueepromlib‘ e instálalo también.

Código Arduino – Fecha y hora de lectura

Este es un código simple para configurar/leer la fecha y la hora del módulo RTC DS1307

#include "Arduino.h"
#include "uRTCLib.h"

// uRTCLib rtc;
uRTCLib rtc(0x68);

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup() {
  Serial.begin(9600);
  delay(3000); // wait for console opening

  URTCLIB_WIRE.begin();

  // Comment out below line once you set the date & time.
  // Following line sets the RTC with an explicit date & time
  // for example to set January 13 2022 at 12:56 you would call:
   rtc.set(0, 56, 12, 5, 13, 1, 22);
  // rtc.set(second, minute, hour, dayOfWeek, dayOfMonth, month, year)
 // set day of week (1=Sunday, 7=Saturday)
}

void loop() {
  rtc.refresh();

  Serial.print("Current Date & Time: ");
  Serial.print(rtc.year());
  Serial.print('/');
  Serial.print(rtc.month());
  Serial.print('/');
  Serial.print(rtc.day());

  Serial.print(" (");
  Serial.print(daysOfTheWeek[rtc.dayOfWeek()-1]);
   Serial.print(") ");

  Serial.print(rtc.hour());
  Serial.print(':');
  Serial.print(rtc.minute());
  Serial.print(':');
  Serial.println(rtc.second());
  
  delay(1000);
}

Así es como se ve la salida:

Explicación del código:

El código comienza con la inclusión de las librerías Arduino.h y uRTCLib.h para comunicarse con el módulo. Luego creamos un objeto de librería uRTCLib y definimos la matriz daysOfTheWeek de caracteres 2D para almacenar la información de los días.

Para interactuar con el módulo RTC, usamos las siguientes funciones en las secciones de configuración y bucle del código:

La función begin() garantiza que el módulo RTC se inicialice correctamente.

La función set(ss, mm, hh, day, dd, mm, yy) establece el RTC en una fecha y hora explícitas. Por ejemplo, para configurar el 13 de enero de 2022 a las 12:56, llamaría a: rtc.set(0, 56, 12, 5, 13, 1, 22);

La función refresh() actualiza los datos del HW RTC.

La función year() devuelve el año actual.

La función month() devuelve el mes actual.

La función day() devuelve el día actual.

La función dayOfWeek() devuelve el día actual de la semana (1 a 7). Esta función se usa normalmente como un índice para una matriz de caracteres 2D que almacena información sobre los días.

La función hour() devuelve la hora actual.

La función minute() devuelve el minuto actual.

La función second() devuelve los segundos actuales.

Código Arduino: lee/escribe la EEPROM 24C32

Como bono adicional, el módulo DS1307 RTC incluye 32 bytes de ROM borrable eléctricamente. Su contenido no se borrará incluso si se interrumpe la alimentación principal del dispositivo.

Este es un código simple que intenta escribir un número entero, flotante, carácter y cadena en la EEPROM 24C32 y luego los vuelve a leer. Este programa se puede ampliar para guardar configuraciones, contraseñas o casi cualquier cosa.

#include "Arduino.h"
#include "Wire.h"
#include "uEEPROMLib.h"

// uEEPROMLib eeprom;
uEEPROMLib eeprom(0x50);

void setup() {
  Serial.begin(9600);
  delay(2500);

  Wire.begin();

  int inttmp = 32123;
  float floattmp = 3.1416;
  char chartmp = 'A';
  char c_string[] = "lastminuteengineers.com"; //23
  int string_length = strlen(c_string);

  Serial.println("Writing into memory...");
  
  // Write single char at address 
  if (!eeprom.eeprom_write(8, chartmp)) {
  Serial.println("Failed to store char.");
  } else {
  Serial.println("char was stored correctly.");
  }

  // Write a long string of chars FROM position 33 which isn't aligned to the 32 byte pages of the EEPROM
  if (!eeprom.eeprom_write(33, (byte *) c_string, strlen(c_string))) {
  Serial.println("Failed to store string.");
  } else {
  Serial.println("string was stored correctly.");
  }

  // Write an int
  if (!eeprom.eeprom_write(0, inttmp)) {
    Serial.println("Failed to store int.");
  } else {
    Serial.println("int was stored correctly.");
  }

  // write a float
  if (!eeprom.eeprom_write(4, floattmp)) {
    Serial.println("Failed to store float.");
  } else {
    Serial.println("float was stored correctly.");
  }

  Serial.println("");
  Serial.println("Reading memory...");
  
  Serial.print("int: ");
  eeprom.eeprom_read(0, &inttmp);
  Serial.println(inttmp);

  Serial.print("float: ");
  eeprom.eeprom_read(4, &floattmp);
  Serial.println((float) floattmp);

  Serial.print("char: ");
  eeprom.eeprom_read(8, &chartmp);
  Serial.println(chartmp);

  Serial.print("string: ");
  eeprom.eeprom_read(33, (byte *) c_string, string_length);
  Serial.println(c_string);

  Serial.println();
}

void loop() {
}

Así es como se ve la salida:

Cuando leas/escribas la EEPROM, ten en cuenta que diferentes tipos de datos ocupan diferentes cantidades de memoria. Por ejemplo, un carácter es un byte, un número entero es de dos bytes y un flotante es de cuatro bytes.

En otras palabras, si estás almacenando un caracter, puede escribirse en cada ubicación de memoria (0, 1, 2, 3, 4, 5….).

Sin embargo, si estás almacenando un número entero, debes reservar dos ubicaciones de memoria para cada valor, por lo que querrás almacenar datos en cualquier otra ubicación de memoria, como (0,2,4,6…).

Interface DS1307 RTC Module with Arduino. Last Minute Engineers. https://lastminuteengineers.com/ds1307-rtc-arduino-tutorial/