Código para el reloj con LED's con Arduino y RTC DS3231.

/* PROGRAMA_RELOJ_FPB_V4 *  VERSIÓN 4: POR PROBLEMAS EN LAS LIBRERÍAS DS3231 PARA LEER LAS HORAS Y ADEMÁS  *  POR LAS CONVERSIONES INNECESARIAS ENTRE DECIMAL Y BCD A PARA LEER Y ESCRIBIR EL CI DS3231 *  HEMOS CREADO LAS FUNCIONES NECESARIAS *   *  PROGRAMA CON CAMBIO DE HORARIO AUTOMÁTICO HORARIO-INVIERNO  --> SOLO SI ESTÁ ENCHUFADO *  Y BOTONES D PUESTA EN HORA - MINUTOS. *   *  PROGRAMA PARA EL RELOJ DE FP BÁSICA CURSO 2014-2015 *  SE UTILIZA UN RELOJ DS3231 QUE SE CONTROLA A TRAVES DE I2C *  SE CONECTA A ARDUINO NANO V3.0 *  SALIDAS MEDIANTE 4 74HC959 (SE UTILIZAN LAS SALIDAS D1 A D7) *  HACE USO DE LAS LIBRERÍAS DS3231 Y WIRE *  FRANCISCO J. JIMÉNEZ NOVIEMBRE DE 2015 *   *  http://www.fpbasicaelectricidad.blogspot.com.es/ */

#include <Wire.h>

#define CLOCK_ADDRESS 0x68
#define DIR_SEGUNDOS 0x00
#define DIR_MINUTOS 0x01
#define DIR_HORAS 0x02
#define DIR_DIA_SEM 0x03
#define DIR_DIA 0x04
#define DIR_MES 0x05
#define DIR_AGNO 0x06
#define DIR_TEMPERATURA 0x11

// DECLARACIONES DE VARIABLES GLOBALES

const byte pinLatch   = 10; //Pin para el latch de los 74CH495
const byte pinDatos   = 11; //Pin para Datos serie del 74CH495
const byte pinReloj   = 12; //Pin para reloj del 74CH495
const byte pinSeconds = 13; //Pin de salida del segundos BLINK
const byte pinGrados  = 9;  //Pin del signo menos de los grados
const byte pinhora_mas = 4;    // Entrada de botón de aumento de hora
const byte pinminuto_mas = 3;  // Entrada de botón de aumento de minutos
const byte digitos_LED[10]= {0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B};        // CAMBIADO ---> CAMBIAR EN FUNCIÓN DE NUESTROS LED'S
byte registro_segundos;         // registros de segundos del DS3231
unsigned int  numero_pulsaciones =0; // Para cambiar la velocidad de actualización de la hora en cambio de hora
byte cambiada_hora;             // Registro auxiliar para el Cambio de hora automático en horario de verano a invierno

// DECLARACIÓN DE FUNCIONES
byte leer_DS3231(byte registro);
void escribir_hora_minuto_leds(void);
void escribir_temperatura_leds(void);
void escribir_fecha_leds(void);

/* FUNCIÓN PRINCIPAL SETUP */
void setup() {
  Wire.begin();           // Se inicial la interfaz I2C

  // ACTIVAR LAS ENTRADAS -SALIDAS DE NUESTRO ARDUINO
  pinMode(pinhora_mas, INPUT);         // pin 2 como entrada
  digitalWrite(pinhora_mas, HIGH);     // activar la resistencia pull-up interna en el pin 2
  pinMode(pinminuto_mas, INPUT);         // pin 3 como entrada
  digitalWrite(pinminuto_mas, HIGH);     // activar la resistencia pull-up interna en el pin 3
  pinMode(pinLatch, OUTPUT);         
  pinMode(pinDatos, OUTPUT);         
  pinMode(pinReloj, OUTPUT);  
  pinMode(pinSeconds, OUTPUT); 
  pinMode(pinGrados, OUTPUT);
  registro_segundos = leer_DS3231(DIR_SEGUNDOS);    // INICIALIZA LA VARIABLE DE LOS SEGUNDOS
  escribir_hora_minuto_leds();
  cambiada_hora=0;
}

/* FUNCIÓN PRINCIPAL LOOP O MAIN */
void loop() {
  byte para_minutos, para_horas, segundos_bucle;

  /* FUNCIONAMIENTO 1: ACTUALIZANDO LAS HORAS */
  if (digitalRead (pinminuto_mas)==HIGH || digitalRead (pinhora_mas)==HIGH){
    if (digitalRead (pinminuto_mas)==HIGH){                                // CONDICIÓN 1: SE PULSA PONER EN HORA AUMENTAR 1 MINUTO
      para_minutos = BCDabinario (leer_DS3231(DIR_MINUTOS));
      if (para_minutos<59) para_minutos++;                                // Y AUMENTA 1 MINUTO
      else para_minutos=0;
      escribir_DS3231(DIR_MINUTOS, binarioaBCD(para_minutos));             // SE ESCRIBEN LOS MINUTOS
      registro_segundos = 0;
      escribir_DS3231(DIR_SEGUNDOS, registro_segundos );                                 // SE PONEN LOS SEGUNDOS A 0
      escribir_hora_minuto_leds();                       // Y SE PRESENTA LA HORA Y MINUTOS, AUNQUE ESTÉ PRESENTADO LA TEMPERATURA
      if (++numero_pulsaciones<5) delay (500);          //RETARDA 1 SEGUNDO EN LAS PRIMERAS 5 PULSACIONES.
      else delay(100);                                   //RETARDA 0,2 SEG EN LAS SIGUIENTES
    }  
    if (digitalRead (pinhora_mas)==HIGH){    // CONDICIÓN 2: SE PULSA PONER EN HORA AUMENTAR 1 HORA
      para_horas = BCDabinario (leer_DS3231(DIR_HORAS)& 0x3F );
      if (para_horas<23) para_horas++;                                // Y AUMENTA 1 HORA
      else para_horas=0;
      escribir_DS3231(DIR_HORAS, (binarioaBCD(para_horas) & 0x3F) );        // SE ESCRIBEN LAS HORAS EN MODO 24 HORAS
      //escribir_DS3231(DIR_SEGUNDOS, 0x00);                                 // SE PONEN LOS SEGUNDOS A 0
      escribir_hora_minuto_leds();                       // Y SE PRESENTA LA HORA Y MINUTOS, AUNQUE ESTÉ PRESENTADO LA TEMPERATURA
      if (++numero_pulsaciones<5) delay (500);          //RETARDA 1 SEGUNDO EN LAS PRIMERAS 5 PULSACIONES.
      else delay(100);                                   //RETARDA 0,2 SEG EN LAS SIGUIENTES
     
      escribir_hora_minuto_leds();                       // Y SE PRESENTA LA HORA Y MINUTOS, AUNQUE ESTÉ PRESENTADO LA TEMPERATURA
      if (++numero_pulsaciones<5) delay (1000);          //RETARDA 1 SEGUNDO EN LAS PRIMERAS 5 PULSACIONES.
      else delay(200);                                   //RETARDA 0,2 SEG EN LAS SIGUIENTES
    }
  }

  /* SI NO SE ESTÁ ACTUALIZANDO LA HORA SE ESCRIBE:   *  LA TEMPERATURA: entre el segundo 20 y el 24   *  LA FECHA:       entre el segundo 40 y el 44   *  LA HORA:        el resto del tiempo   */
  else {
    if ((BCDabinario(registro_segundos)>=20) && (BCDabinario(registro_segundos)<25)) {    //CONDICIÓN 3: DURANTE 5 SEGUNDOS SE PRESENTAN LAS TEMPERATURAS
        escribir_temperatura_leds();
    }
    
    else if ((BCDabinario(registro_segundos)>=40) && (BCDabinario(registro_segundos)<43)) {     //CONDICIÓN 4: DURANTE 5 SEGUNDOS SE PRESENTA LA FECHA
        escribir_fecha_leds();
        digitalWrite(pinSeconds, HIGH);
    }
    else if ((BCDabinario(registro_segundos)>=43) && (BCDabinario(registro_segundos)<46)) {     //CONDICIÓN 4: DURANTE 5 SEGUNDOS SE PRESENTA LA FECHA
        escribir_agno_leds();
        digitalWrite(pinSeconds, LOW);
    }
    else {                                // CONDICIÓN 5: SI NO PRESENTA TEMPERATURA...SE PRESENTA LA HORA Y MINUTOS
      escribir_hora_minuto_leds();
      digitalWrite(pinSeconds, HIGH);     // ACTIVA EL PIN DE SEGUNDOS DURANTE 0,30 SEGUNDOS
      delay(300);
      digitalWrite(pinSeconds, LOW);     // Y LO DESACTIVA
      }
    
    /* ANTES DE SALIR DEL BUCLE ESPERA A QUE CAMBIEN LOS SEGUNDOS O BOTON PULSADO   */
  
    do {
      delay (100);
      segundos_bucle = leer_DS3231(DIR_SEGUNDOS);
    } while (segundos_bucle==registro_segundos );
    registro_segundos = segundos_bucle;
  }
  if (digitalRead (pinminuto_mas)==LOW && digitalRead (pinhora_mas)== LOW) numero_pulsaciones =0;

  /* CAMBIAR AUTOMÁTICAMENTE LA HORA EN HORARIOS DE VERANO E INVIERNO  */
  /********************************************************************/
  if (registro_segundos == 5){                        /* CADA MINUTO EN EL SEGUNDO 5 */
    if( leer_DS3231(DIR_DIA_SEM)== 7 && BCDabinario(leer_DS3231(DIR_DIA))>= 25){ /* DOMINGO DE FECHA MAYOR A 25 */
      
  /* CAMBIO DE HORA DE VERANO A INVIERNO. A LAS 3 SON LAS 2. ULTIMO DOMINGO DE OCTUBRE */
  
      if ( BCDabinario(leer_DS3231(DIR_MES) & 0x7F) == 10) {                      /* MES DE OCTUBRE */
        if ( (BCDabinario(leer_DS3231(DIR_HORAS) & 0x3F) == 3)                     /* LAS 3 DE LA MADRUGADA */
                        && (BCDabinario(leer_DS3231(DIR_MINUTOS)==0))){                /* EN PUNTO */
          if (cambiada_hora == 0){                                       // SI NO SE HA CAMBIADO LA HORA
            escribir_DS3231(DIR_HORAS, (binarioaBCD( 2 ) & 0x3F) );          // SE RETRASA EL RELOJ A LAS 2
            cambiada_hora =1;
          }
        }
        if ( (BCDabinario(leer_DS3231(DIR_HORAS) & 0x3F) == 4)            /*A LAS 4 DE LA MADRUGADA */
                      && (BCDabinario(leer_DS3231(DIR_MINUTOS)==0))){                /* EN PUNTO */
          cambiada_hora = 0;                                          // VUELVO A PONER EL REGISTRO A 0           
        }
   /* CAMBIO DE HORA DE INVIERNO A VERANO. A LAS 3 SON LAS 2. ULTIMO DOMINGO DE MARZO */
      }
      if ( BCDabinario(leer_DS3231(DIR_MES) & 0x7F) == 3) {                      /* MES DE MARZO */
        if ( (BCDabinario(leer_DS3231(DIR_HORAS) & 0x3F) == 2)                    /* LAS 2 DE LA MADRUGADA */
                      && (BCDabinario(leer_DS3231(DIR_MINUTOS)==0))){                /* EN PUNTO */
          escribir_DS3231(DIR_HORAS, (binarioaBCD( 3 ) & 0x3F) );          // SE ADELANTA EL RELOJ A LAS 3
        }
      }
    }
  }
}

/*  FUNCIÓN:      byte leer_DS3231(byte registro) *  DESCRIPCIÓN:  Lee el registro del DS3132 y retorna el resultado */
byte leer_DS3231(byte registro){
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(registro);
  Wire.endTransmission();
  Wire.requestFrom(CLOCK_ADDRESS, 1);
  return(Wire.read());
}

/*  FUNCIÓN:      void escribir_DS3231(byte registro, byte dato_BCD) *  DESCRIPCIÓN:  Lee el registro del DS3132 y retorna el resultado */
void escribir_DS3231(byte registro, byte dato_BDC){
  Wire.beginTransmission(CLOCK_ADDRESS);
  Wire.write(registro);
  Wire.write(dato_BDC);
  Wire.endTransmission();
  Wire.requestFrom(CLOCK_ADDRESS, 1);
}

/*  FUNCIÓN:      void escribir_hora_minuto_leds(void) *  DESCRIPCIÓN:  Actualiza las hora y los minutos en el display de LED's */
void escribir_hora_minuto_leds(void){
  byte temporal;
 
 /* ESCRIBIR LOS MINUTOS */
  digitalWrite(pinLatch, LOW);                  // DESACTIVA LATCH
  temporal = leer_DS3231(DIR_MINUTOS);          // LEE EL REGISTRO DE LOS MINUTOS

  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) (temporal & 0x0F)]); 
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) ((temporal>>4) & 0x0F)]); 

/* ESCRIBIR LAS HORAS */
  temporal = leer_DS3231(DIR_HORAS);          // LEE EL REGISTRO DE LAS HORAS
  if ((temporal & 0b01000000) && (temporal & 0b00100000)){                // SI ESTÁ EN MODO 12 HORAS Y ADEMÁS ES PM --> CONVERTIR
    temporal = ((byte) ((int)(temporal & 0b00011111)+12));
  }
                                     // ESTÁ EN MODO 24 HORAS O EN MODO 12 HORAS Y ES AM o ya se ha convertido
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) (temporal & 0x0F)]); 
  if ((temporal>>4) & 0x03){
    shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) ((temporal>>4) & 0x03)]); // SOLO LOS 2 PRIMEROS BITS DESPUÉS DE DESPLAZAR
  }
  else shiftOut(pinDatos, pinReloj, LSBFIRST, 0x00); // Para no escribir el 0 delante de las horas de una cifra
  digitalWrite(pinLatch, HIGH);   // ACTIVA LATCH
}

/*  FUNCIÓN:      void escribir_temperatura_leds(void) *  DESCRIPCIÓN:  Escribe la temparatura en el display de LED's */
void escribir_temperatura_leds(void){
  const byte simbolo_grado = 0x63;
  const byte simbolo_C = 0x4E;
  const byte simbolo_menos = 0x01;
  int decenas, unidades;
  byte temporal;
 
  digitalWrite(pinLatch, LOW);                  // DESACTIVA LATCH
  temporal = leer_DS3231(DIR_TEMPERATURA);          // LEE EL REGISTRO DE LOS MINUTOS
  // temporal = 0b00101011;
  
  if (temporal &&    0x80){                        // TEMPERATURA POSITIVA
    temporal &= 0x7F;                           // Le quitamos el signo 
    temporal -=2;                                 // corregir 2 grados
    decenas = temporal / 10 ;
    unidades = temporal % 10; 
    shiftOut(pinDatos, pinReloj, LSBFIRST, simbolo_C); 
    shiftOut(pinDatos, pinReloj, LSBFIRST, simbolo_grado); 
    shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[unidades]); 
    shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[decenas]); 
  }
  else {                                        // TEMPERATURA NEGATIVA
    decenas = temporal / 10 ;
    unidades = temporal % 10;
    shiftOut(pinDatos, pinReloj, LSBFIRST, simbolo_grado); 
    shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[unidades]); 
    shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[decenas]);
    shiftOut(pinDatos, pinReloj, LSBFIRST, simbolo_menos);
    
  }
  digitalWrite(pinLatch, HIGH);   // ACTIVA LATCH
}

/*  FUNCIÓN:      void escribir_agno_leds(void) *  DESCRIPCIÓN:  Actualiza el año en el display de LED's */
void escribir_agno_leds(void){
  byte temporal;
 
  digitalWrite(pinLatch, LOW);                  // DESACTIVA LATCH
  temporal = leer_DS3231(DIR_AGNO);          // LEE EL REGISTRO DEL AÑO

  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) (temporal & 0x0F)]); 
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) ((temporal>>4) & 0x0F)]); 
  // SOLO EL SIGLO 20 */
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[0]); 
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[2]);

  digitalWrite(pinLatch, HIGH);   // ACTIVA LATCH
}

/*  FUNCIÓN:      void escribir_fecha_leds(void) *  DESCRIPCIÓN:  Actualiza las el día y mes en el display de LED's */
void escribir_fecha_leds(void){
  byte temporal;
 
 /* ESCRIBIR EL MES */
  digitalWrite(pinLatch, LOW);                  // DESACTIVA LATCH
  temporal = leer_DS3231(DIR_MES);          // LEE EL REGISTRO DEL MES

  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) (temporal & 0x0F)]); 
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) ((temporal>>4) & 0x01)]); 

/* ESCRIBIR EL DÍA */

  temporal = leer_DS3231(DIR_DIA);          // LEE EL REGISTRO DEL DÍA

  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) (temporal & 0x0F)]); 
  shiftOut(pinDatos, pinReloj, LSBFIRST, digitos_LED[(int) ((temporal>>4) & 0x03)]);

  digitalWrite(pinLatch, HIGH);   // ACTIVA LATCH
}
/*  FUNCIÓN:      byte binarioaBCD(byte num_binario) *  DESCRIPCIÓN:  Convierte un número binario de 8 bits sin signo en BCD */
byte binarioaBCD(byte num_binario){
  return ((num_binario/10 * 16) + (num_binario % 10));
}

/*  FUNCIÓN:      byte BCDabinario(byte num_BCD) *  DESCRIPCIÓN:  Convierte un número BCD en binario de 8 bits sin signo */
byte BCDabinario(byte num_BCD){
  return ((num_BCD/16 * 10) + (num_BCD % 16));
}




No hay comentarios:

Publicar un comentario