CAP4- Controlando la Fecha y la Hora (Modulo reloj DS1037)

  • Iniciador del tema Iniciador del tema jmcadsl
  • Fecha de inicio Fecha de inicio

jmcadsl

Miembro Honorífico
Registrado
17 Ene 2010
Mensajes
1.095
Ubicación
España
Provincia
Madrid
Buenas, supongo que ya hemos tenido tiempo para "jugar" con el potenciometro y cada una ya ha programado su menu personalizado con los opciones que ha creído oportunas....bien.

Ahora vamos a conectar un módulo de reloj, concretamente un DS1307, ya que es el más economico que he encontrado y va bastante bien, si es cierto que en algunos casos se atrasa o adelanta un poco debido generalmente a interferencias con el cristal de cuarzo que lleva, pero nada que no lo podamos solucionar mediante un pequeño ajuste con el programa.

-HARDWARE:
Al ser un módulo integrado y preparado para Arduino solo tenemos que conectar los pines en sus correspondientes lugares. Es muy fácil, solo tenemos 4 pines, 0v , 5v, SDA y SCL (los pines SDA y SCL están marcados en la placa Arduino asi que no tenemos problema.
Ejemplo en placa MEGA:
[TodoMarino.com] CAP4- Controlando la Fecha y la Hora (Modulo reloj DS1037)

Ejemplo en Placa aTreef Shield:
[TodoMarino.com] CAP4- Controlando la Fecha y la Hora (Modulo reloj DS1037)[TodoMarino.com] CAP4- Controlando la Fecha y la Hora (Modulo reloj DS1037)

Para no tener problemas con el cuarzo yo os aconsejo que lo pongais en una zona alejada de los reles y que no este tocando ningun otro componente y que tambien es bueno que no sufra moviemientos ni vibraciones.

-SOFTWARE:
Existen varias librerias para el módulo del reloj pero tienen mucho código el cual yo nunca he utilizado por lo que os voy a copiar el codigo que yo utilizo sin problemas:
Código:
//CAP4 Modulo reloj DS1307

//LIBRERIAS
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>// Debemos instalar la libreria LiquidCrystal_I2C en la carpeta "libraries" del arduino IDE
LiquidCrystal_I2C lcd(0x27,16,2);  // direccion i2c(puede variar segun la placa) del LCD y columnas,lineas

#include <Wire.h>//RELOJ
#define DS1307_I2C_ADDRESS 0x68//RELOJ Direccion

/*PINES CONECTADO EN ARDUINO MEGA
ANALOGICOS:
A14 - Potenciometro

DIGITALES:
D19 - Boton
D20 - SDA I2C  / LCD+reloj
D21 - SCL I2C  / LCD+reloj

*/

//VARIABLES
byte boton=19, pot=A14; //declaramos que la variable de los pines donde esta conectado boton y potenciometro
int menupot;// numero de menu
byte vboton,menus, menuactual,cambiomenu;//variables para los menus

//RELOJ

//RELOJ
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year,ajustereloj=0;
int hora=hour;
long offset;
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   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));    // 0 to bit 7 starts the clock
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}


void setup()
{
  pinMode(boton, INPUT);//Inidicamos que es  una entrada 
  pinMode(pot, INPUT);
  
  Wire.begin();//Inicializamos el reloj   
  setDateDs1307(0, 0, 8,1,1,1,2014);//Esto solo hay que ponerlo una vez, es para grabar la primera vez la hora luego se puede borrar esta linea
  lcd.init();//Inicializamos el LCD
  lcd.backlight();//Encendemos la luz
  lcd.print(" CAP4. EL RELOJ ");
  
  delay(2000);//Hacemos una pausa de 2 segundos
  lcd.init();//Al inicializar el LCD tambien borramos la pantalla
}

void loop()
{
leehora();//funcion para leer la hora
verhora();//Mostramos informacion en pantalla
}


void leehora()
{
     getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);//Almacenamos los valores actualizados en las variables
}


void verhora()
{
  lcd.setCursor(0,0);
  lcd.print (" CAP4. EL RELOJ ");
  lcd.setCursor(0,1);
  if (dayOfMonth <10) {lcd.print("0");}
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");  
  if (month < 10){lcd.print("0");}
  lcd.print(month, DEC);
  lcd.print("  ");
  if (hour < 10){lcd.print("0");}
  lcd.print(hour, DEC);
  lcd.print(":");  
  if (minute < 10){lcd.print("0");}
  lcd.print(minute, DEC);
  lcd.print(":");  
  if (second < 10){lcd.print("0");}
  lcd.print(second, DEC);
}

Para ajustar la hora del reloj debemos utilizar el comando:
setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year );
Donde cada variable debe tener su correspondiente valor, tambien valdría poner los valores directamente:
setDateDs1307(1, 1, 1, 1, 1, 1, 2014 ); Lo que dará como resultado 01:01:01 h , 1 de enero de 2014

Bueno pues ya teneis para entreteneros otro rato.
Cuando lo veais correctamente os aconsejo que programeis un submenu dentro de vuestro menu que sea "ajuste de reloj" y donde vayais pasando valores a las variables y al final las mandeis con el somando setDateDs1307.

Saludos
Jorge
 
como siempre entusiasmado con tus capítulos
muchas gracias Jorge
 
Muchas gracias Jorge!

Mira que no tengo casi conocimientos y cuando me ven trastear en casa me tratan de científico loco.

A ver si voy metiendo líneas que me estoy volviendo un poco majara.

Gracias de nuevo!!
 


Buenas,
gracias a las aportaciones de Jorge voy viendo como avanza mi proyecto. Os dejo un video donde se ve lo que llevo hecho. ahora mismo me queda ampliar el menú pudiendo modificar la hora con los botones. estudiaré a ver como lo logro porque estoy todavía pez con esto de la programación.
 
que bien se ve eso dem365 se nota que le as pillado el hilo enhorabuena ,me gustaría ver el de Jorge para hacerme una idea de lo que se puede llegar a hacer
 
  • Iniciador del tema
  • Moderador
  • #7
Buen trabajo dem365!!!
Se ve que le estas cogiendo el truco, pues ahora a terminar de codificar todos lo menus e ir rellenandolos poco a poco!!

que bien se ve eso dem365 se nota que le as pillado el hilo enhorabuena ,me gustaría ver el de Jorge para hacerme una idea de lo que se puede llegar a hacer

Hola mateo69, pues la verdad es que tengo poco tiempo libre, pero estoy detrás de hacer un video chulo del controlador, (tambien lo quiero poner en mi web) ....espero poder hacerlo pronto y compartirlo.

Pero la verdad es que es parecido al del dem365, es decir una caja,lcd 16x2 , boton y potenciometro...van saliendo la info por pantalla, aceso a los menus etc etc...jejeje

Un saludo
 
Hola ,tengo una duda y me he quedado aqui estancado,,,,,si anteriormente he conectado la pantalla lcd a los pines de arduino mega 2560 , SDA 20 Y SDL 21.
AHORA EL RELOJ ME DICE QUE LO CONECTE A LOS PINES SDA Y SDL......LOS CUALES ESTAN OCUPADOS.
Que puedo hacer conectarlo en paralelo con los pin de la pantalla.
0 SE DEBE ASIGNAR OTRO PIN,,,,,COMO PUEDO HACERLO.
GRACIAS.
 
  • Iniciador del tema
  • Moderador
  • #9
B.tardes...y feliz año!
Efectivamente los pines sda y scl son pines de comunicación y se pueden utilizar varios dispositivos. ...es por ello que cada disposotivo se le tiene que asignar una dirección única.
Un saludo
 
Hola feliz año,,,,,no te comprendo,,,,que tengo que hacer asignar un nuevo pin al reloj,,,,,cuales serian,,,,me podrias dar un ejemplo,,,,gracias.
 
Utiliza los mismos pines sda y scl para el reloj...es decir saca 2 cables de cada pin y copia el código del programa..
.la linea donde pone define ds1307......es lo que te comentaba de la dirección
 
Chiclanero2000.
El reloj y el lcd comparten los mismos pines SDA y SCL, sin problemas.
Pruebalo en una pla[FONT=arial, sans-serif]ca de puebas.

Saludos
[/FONT]
 
Unas dudas...

1º El codigo se tiene que pegar un capitulo detras del otro y cargarlo todo a la vez? o voy cargando cada capitulo al arduino por separado???

2º Que IDE deberiamos usar? Lo digo porque estoy con el IDE 0022 y me da error al cargar el codigo del reloj:

sketch_jan27a.cpp: In function 'void setDateDs1307(byte, byte, byte, byte, byte, byte, byte)':
sketch_jan27a:62: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:63: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:64: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:65: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:67: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:68: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:69: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:70: error: 'class TwoWire' has no member named 'write'
sketch_jan27a.cpp: In function 'void getDateDs1307(byte*, byte*, byte*, byte*, byte*, byte*, byte*)':
sketch_jan27a:83: error: 'class TwoWire' has no member named 'write'
sketch_jan27a:89: error: 'class TwoWire' has no member named 'read'
sketch_jan27a:90: error: 'class TwoWire' has no member named 'read'
sketch_jan27a:91: error: 'class TwoWire' has no member named 'read'
sketch_jan27a:92: error: 'class TwoWire' has no member named 'read'
sketch_jan27a:93: error: 'class TwoWire' has no member named 'read'
sketch_jan27a:94: error: 'class TwoWire' has no member named 'read'
sketch_jan27a:95: error: 'class TwoWire' has no member named 'read'

Hasta aqui, cargando los codigos por separado, todo bien, pero de aqui no paso...:yb620[1]:

Gracias por vuestra paciencia...
 
Cada capítulo es independiente. ...luego sois vosotros los que teneis que ver que os viene mejor modificarlo e ir uniendolo para completar el programa que llevara vuestro controlador.
En cuando a los errores quebte da es por la versión del ide y las librerías.
Yo uso el.1.0.2 y las librerias las colge en uno de los post del tutorial.

Saludos
 
Muchas gracias no habia visto las librerias...

He descargado la version 1.02 y las librerias y funciona todo bien, es decir he podido cargar cada sketch por separado sin problemas.

Me podrias poner un ejemplo de como juntar dos scketch, no se los que quieras.... por ejemplo, el reloj + la medicion de temperaturas?

Muchas gracias por ayudarnos a poder montar un controladorpara nuestro acuario a los que esto se nos hace tan complicado
 
Hola dedete32.
Lo ideal es que comprendas el funcionamiento de los programas de Arduino, de la estructura.
Te recomiendo que te descargues y leas detenidamente el libro básico que tengo en mi firma.

De momento he unido los 2 códigos que me has pedido, espero que te leas el libro !! :yb63[1]:
Código:
//Reloj DS1307 + temperatura

//LIBRERIAS
 
#include <LiquidCrystal_I2C.h>// Debemos instalar la libreria LiquidCrystal_I2C en la carpeta "libraries" del arduino IDE
LiquidCrystal_I2C lcd(0x27,16,2);  // direccion i2c(puede variar segun la placa) del LCD y columnas,lineas

#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68//RELOJ Direccion

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 14 //Conectaremos sonda a pin digital 14
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);



/*PINES CONECTADO EN ARDUINO MEGA
ANALOGICOS:
A14 - Potenciometro

DIGITALES:
D14 - sonda ds18b20
D19 - Boton
D20 - SDA I2C  / LCD+reloj
D21 - SCL I2C  / LCD+reloj

*/

//VARIABLES
byte boton=19,tempagua=14, pot=A14; //declaramos que la variable de los pines donde esta conectado boton y potenciometro
int menupot;// numero de menu
byte vboton,menus, menuactual,cambiomenu;//variables para los menus

//RELOJ

//RELOJ
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year,ajustereloj=0;
int hora=hour;
long offset;
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   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));    // 0 to bit 7 starts the clock
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}


void setup()
{
  pinMode(boton, INPUT);//Inidicamos que es  una entrada 
  pinMode(pot, INPUT);
  pinMode(tempagua, INPUT);
  
  Wire.begin();//Inicializamos el reloj   
  setDateDs1307(0, 0, 8,1,1,1,2014);//Esto solo hay que ponerlo una vez, es para grabar la primera vez la hora luego se puede borrar esta linea
  lcd.init();//Inicializamos el LCD
  lcd.backlight();//Encendemos la luz
  lcd.print("  Reloj y Temp ");
  
  delay(2000);//Hacemos una pausa de 2 segundos
  lcd.init();//Al inicializar el LCD tambien borramos la pantalla
}

void loop()
{
leehora();//funcion para leer la hora
temperatura();
ver();//Mostramos informacion en pantalla
delay(500);
}


void leehora()
{
     getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);//Almacenamos los valores actualizados en las variables
}


void ver()
{
  lcd.setCursor(0,0);
  lcd.print("T.Agua: ");
  lcd.print(tempagua);
  lcd.print("   ");
  lcd.setCursor(0,1);
  if (dayOfMonth <10) {lcd.print("0");}
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");  
  if (month < 10){lcd.print("0");}
  lcd.print(month, DEC);
  lcd.print("  ");
  if (hour < 10){lcd.print("0");}
  lcd.print(hour, DEC);
  lcd.print(":");  
  if (minute < 10){lcd.print("0");}
  lcd.print(minute, DEC);
  lcd.print(":");  
  if (second < 10){lcd.print("0");}
  lcd.print(second, DEC);
}


void temperatura()
{
  
   sensors.requestTemperatures();
   delay(50);
   tempagua = sensors.getTempCByIndex(1);//En este caso si tenemos varias sondas estamos pidiendo que nos muestre kla lectura de la sonda "1"
              
  
}

Un saludo
 
Muchas gracias, he mirado manuales por internet, pero como voy dedicando solo ratos libres, y son pocos....no me acabo de aclarar....por eso te pedia un ejemplo de como fusionar dos códigos para ver como ir juntándolos todos.

El montaje no es problema pero la programación se em atraganta muchisimo.


Gracias de nuevo por tu ayuda
 
Hola a todos!!

Yo estoy usando otra version del arduino (1.0.6) y la libreria del DS1307 obtenida de Adafruit, lo digo por si a vosotros no os funciona lo que os voy a comentar saber porque puede ser.

Hay un comando muy interesante para poner el reloj en hora sin tener que escribir tal cantidad de lineas con algo tan simple como: RTC.adjust(DateTime(__DATE__, __TIME__)); Con eso toma la fecha del ordenador que estamos usando y se la escribe al reloj del arduino, así que si el ordenador está en hora queda la fecha perfecta. Os copio un programa super simple para enviar los datos por serie al PC para que todos podais ver si os funciona sin necesidad de más componentes fuera del RTC y del Arduino.

Código:
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;

void setup(){
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  if (!RTC.isrunning()){
    Serial.println("RTC is NOT running!");
    RTC.adjust(DateTime(__DATE__, __TIME__));        //Pone la fecha y hora del PC en el reloj
    //RTC.adjust(DateTime(2014, 1, 22, 3, 5, 15));   //Pone la fecha y hora elegida en el reloj (año, mes, dia, hora, minuto, segundo)
  }
}

void loop(){
  DateTime now = RTC.now();
  
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  delay(500);
}

Un detalle, el codigo está pensado para que si el reloj no tiene hora/fecha se la pone... pero si ya tiene no se la cambia así que si quereis probarlo quitad y poned la bateria del reloj, o bien del codigo dentro del setup quitar la 4 y 5 lineas y uno de los corchetes de cierre "}" (pero en ese caso os estará poniendo en hora el reloj continuamente).

Un saludo
 
Atrás
Arriba