/* 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)); }
Formación Profesional Básica Electricidad-Electrónica. I.E.S. Al-Baytar. http://bit.ly/1WQT7RF
Código para el reloj con LED's con Arduino y RTC DS3231.
Suscribirse a:
Entradas (Atom)
No hay comentarios:
Publicar un comentario