domingo, 21 de febrero de 2016

Poner reloj rtc DS3231 en hora y mostrar en pantalla lcd 1602

Introducción

Cuando queremos usar reloj rtc para arduino tenemos la desventaja que cuando desconectamos la alimentación del reloj se nos borra la hora aunque éste lleve pilas. Si lo aplicamos a cualquier proyecto que pueda necesitar calendario y se nos corta la electricidad nos causa un problema.
Bién, con los códigos que vamos a usar eso no va a pasar. Si se nos corta la alimentación, el reloj sigue marcando internamente la hora actual, siempre que lleve pila.

Este proyecto consta de dos partes, una poner en hora el rtc, y otra visualizar la hora y fecha en una pantalla lcd de 16x02.



Elementos

Placa Arduino Uno o compatible
Reloj rtc DS3231 con pila cr2032 de 3v
Pantalla LCD 1602
Potenciómetro 50k
Protoboard
Cables jumpers
Fuente alimentación



Reloj en hora

Esquema:

SDA-A4
SCL-A5
GND-GND
VCC-5V



Ponemos el rtc en hora con el siguiente código:


#include "Wire.h" 
#define DS1307_I2C_ADDRESS 0x68
 
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
 
void setDateDs1307(
byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7 1=Lunes, 7=Domingo
byte dayOfMonth,    // 1-28/29/30/31
byte month,         // 1-12
byte year           // 0-99
)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
 
void setup()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  pinMode(13, OUTPUT);
 
  // Cambiamos los parámetros como queramos
  // Lo mejor es poner la hora del script 30 segundos antes que es lo que tarda el ordenador aproximadamente en compilar el programa
  // Sólo es necesario compilar el script una vez
  // El formato es de 24 horas
  // Días de la semana lunes es 1 a domingo que es 7
  // El formato de año son los dos últimos dígitos del año
  //
  // Una vez cargado el programa el led 13 parpadeará cada segundo, no debemos resetear.
 
  second = 0;
  minute = 06;
  hour = 10;
  dayOfWeek = 7;
  dayOfMonth = 24;
  month = 1;
  year = 16;
  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  //*/
}
 
void loop()
{
  digitalWrite(13, HIGH);   
  delay(1000);               
  digitalWrite(13, LOW);    
  delay(1000);
}

El led 13 de la placa arduino uno parpadeará cada segundo, indicando que está el programa cargado en el rtc.

Visualización en pantalla lcd 1602

Esquema conexión:

pin 1 lcd VSS-GND
pin 2 lcd VDD-5V
pin 15 lcd A-5V
pin 16 lcd K-GND

pin 1 potenciómetro-GND
pin 2 potenciómetro-pin 3 lcd VO
pin 3 potenciómetro-5V

pin 4 lcd RS-pin 7 arduino
pin 5 lcd RW-GND
pin 6 lcd E-pin8 arduino
pin 11 lcd D4-pin 9 arduino
pin 12 lcd D5-pin 10 arduino
pin 13 lcd D6-pin 11 arduino
pin 14 lcd D7-pin 12 arduino

pin rtc VCC-5V
pin rtc GND-GND
pin rtc SDA-pin A4 arduino
pin rtc SCL-pin A5 arduino





Código:


#include "Wire.h"
#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
 
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
 
void getDateDs1307(byte *second,byte *minute,byte *hour,byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
 
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}
 
 
void setup()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  
  lcd.begin(16, 2);
}
 
void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  String s, m, d, mth, h;
   
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
 
  if (second < 10) { s = "0" + String(second); } else { s = String(second); }
  if (minute < 10) { m = "0" + String(minute); } else { m = String(minute); }
  h = String(hour);
  if (dayOfMonth < 10) { d = "0" + String(dayOfMonth); } else { d = String(dayOfMonth); }
  if (month < 10) { mth = "0" + String(month); } else { mth = String(month); }
   
  char* days[] = { "NA", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
   
  lcd.clear();
  
  lcd.setCursor(4,0);
  
  lcd.print(h + ":" + m + ":" + s);
  
  lcd.setCursor(1,1);
  
  lcd.print(String(days[dayOfWeek]) + " " + d + "/" + mth + "/20" + year);
  delay(1000); // Esperamos un segundo
}

Notas:
Antes de cargar el primer código debemos poner la hora y fecha actual en ese código.
Girar potenciómetro hasta que aparezca hora y fecha.
Podemos interrumpir la alimentación todo lo que queramos, una vez establecida dará la hora actual.

Códigos:

Poner en hora rtc
Visualizacion hora rtc lcd 1602

Librerías:
La librería wire.h viene incluida en el ide de arduino
LiquidCrystal.zip

Fuentes:
Tutorial 1
Tutorial 2

Presentación

Aficionado a la electrónica, informática y programación, uso este blog a modo de diario, para mis proyectos de Arduino. Las entradas de este blog no son tutoriales (existen muchos y muy buenos), es anotar cada uno de los pasos de mis proyectos, al mismo tiempo conservarlo, y divulgarlo para que el que lo desee los pueda aplicar a los suyos.