Está en la página 1de 6

Reloj de Tiempo Real con Arduino y DS3231

En este tutorial vamos a aprender a utilizar el módulo DS3231, un Reloj de Tiempo Real (RTC)
de alta precisión.
Con ayuda de un Arduino Nano y una pantalla lcd 16×2 vamos a realizar un sencillo reloj que
muestre la hora y fecha.
Características DS3231
El módulo DS3231 cuenta con excelentes características, integra un cristal oscilador
compensado por temperatura que ayuda a mantener la precisión del reloj en +-2 minutos por
año en temperaturas con rango de -40°C a +85°C.

El módulo DS3231 proporciona información de segundos, minutos, horas, día de la semana,


día del mes, mes y año, además se ajusta automáticamente a los meses con menos de 31 días
y a los años bisiestos, toda la información es válida hasta el año 2099.

El reloj puede operar en formato de 24 o 12 horas con indicador AM/PM, incluye dos alarmas
programables y una señal cuadrada programable.

Emplea interfaz I2C, así que es posible utilizar el módulo RTC con cualquier microcontrolador
que cuente con esta comunicación.

Pines DS3231

Para más detalles puedes consultar la hoja de datos.


Interfaz I2C
El módulo RTC utiliza la dirección 104 para conectarse al bus I2C y se puede comunicar con el
dispositivo maestro (en nuestro caso Arduino Nano) en modo receptor o transmisor:

DS3231 Modo Receptor:


Cuando el módulo DS3231 se encuentra en modo receptor se puede acceder a los registros de
hora y fecha y cambiar sus valores.

DS3231 Modo Transmisor:

En el modo transmisor el RTC envía la información de los registros que almacenan la hora y
fecha al dispositivo maestro.

 Registros de configuración
Los registros que almacenan la información del RTC comienzan en la dirección 00H y terminan
en 12H, en este tutorial vamos a acceder a las direcciones 00h – 06h que son las
correspondientes a  hora y fecha.

Circuito de conexión
Programación
Para configurar la fecha y hora en nuestro módulo DS3231 usamos la función:

setDate(00, 6, 18, 06, 26, 02, 16);

El orden de los valores tiene el siguiente formato:

setDate(seconds(0-59), minutes(0-59), hours(0-23), day(1-7), date(0-31), month(1-12), year(0-


99))

Para utilizar la función en el programa principal debemos:

1.- Quitar los signos de comentario de la función

2.- Fijar los valores de fecha y hora

3.- Subir el programa a Arduino

4.- Volver a comentar la función

5.- Programar nuevamente el Arduino para evitar que se reinicie la  fecha por algún reset.
Programa principal

// include the library code:


#include <LiquidCrystal.h>
#include <Wire.h>

#define DS3231_I2C_ADDRESS 104


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

// variables
int  seconds, minutes, hours, day, date, month, year;
String weekDay;

void setup()
{
  Wire.begin();
  // set up the LCD's number of columns and rows:

  lcd.begin(16, 2);
  // to set hour and date use the following steps
  // 1.- Uncomment the instruction
  // 2.- Set time and date
  // 3.- Upload the sketch
  // 4.- Comment and upload again to prevent a reset time
  // setDate(seconds(0-59), minutes(0-59), hours(0-23), day(1-7), date(0-31), month(1-12), year(0-99))
  //setDate(00, 6, 18, 06, 26, 02, 16);
}
 
void loop()
{
  lcd.clear();

  // get date from DS3231


  getDate();

  // display time and date


  lcd.setCursor(1,0);
  lcd.print(weekDay);
  lcd.print(" ");

  if(date<10)
    lcd.print("0");
  lcd.print(date);
  lcd.print("/");
  if(month<10)
    lcd.print("0");
  lcd.print(month);
  lcd.print("/20");
  lcd.print(year);
  lcd.setCursor(4,1);
  lcd.print(hours);
  lcd.print(":");

  if(minutes<10)
    lcd.print("0");
  lcd.print(minutes);
  lcd.print(":");
  if(seconds<10)
    lcd.print("0");
  lcd.print(seconds);

  delay(1000);
 
}
 
void getDate()
{
  // Send request to DS3231 to receive the date
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00);  // start at register 00h (seconds)
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);   // Request 7 bytes (00h - 006h)
 
  while(Wire.available())
  {
    seconds = Wire.read();
    minutes = Wire.read();
    hours = Wire.read();
    day = Wire.read();
    date = Wire.read();
    month = Wire.read();
    year = Wire.read();
    
    // convert BCD to decimal
    seconds = (((seconds >> 4) * 10) + (seconds & B00001111));
    minutes = (((minutes >> 4) * 10) + (minutes & B00001111));
    hours = ((((hours & B00110000) >> 4) * 10) + (hours & B00001111));
    day = (day & B00000111);
    month = ((((month & B00010000) >> 4) * 10) + (month & B00001111));
    date = ((((date & B00110000)>> 4) * 10) + (date & B00001111));  
    year = (((year >> 4) * 10) + (year & B00001111));
  }

   switch (day)  {
    case 1:
      weekDay = "Sun";
      break;
    case 2:
      weekDay = "Mon";
      break;
    case 3:
      weekDay = "Tue";
      break;
    case 4:
      weekDay = "Wed";
      break;
    case 5:
      weekDay = "Thu";
      break;
    case 6:
      weekDay = "Fri";
      break;
  
    default: break;
  }
}
 
void setDate(byte seconds, byte minutes, byte hours, byte day, byte date, byte month, byte year)
{
  // convert DEC to BCD
  seconds = (seconds % 10) + ((seconds / 10) << 4);
  minutes = (minutes % 10) + ((minutes / 10) << 4);
  hours = (hours % 10) + ((hours / 10) << 4);
  date = (date % 10) + ((date / 10) << 4);
  month = (month % 10) + ((month / 10) << 4);
  year = (year % 10) + ((year / 10) << 4);
 
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00);
  Wire.write(seconds);
  Wire.write(minutes);
  Wire.write(hours);
  Wire.write(day);
  Wire.write(date);
  Wire.write(month);
  Wire.write(year);
  Wire.endTransmission(); 
}

También podría gustarte