Vamos a programar #26 - Inútil Apps #2 - Clock View
Hola de nuevo a todos, el día de hoy vamos a continuar con el código de Clock View, la vez anterior solo implementamos las parte mas "criticas" de el, y ya podría considerarse cómo un reloj funcional, pero vamos a agregar unas cuantas funciones para hacerlo más funcional.
Para empezar echemos un vistazo al nuevo código.
Analicemos un poco el código, para empezar, he creado algunas variables que sirven para controlar algunos de los aspectos del reloj. Podemos elegir entre mostrar la hora en formato de 12 o de 24 horas, decidir si se quiere mostrar o no los segundos y ademas, ahora podemos apagar las matrices, útil para cuando llega la hora de dormir.
En la matriz que almacena los datos de los números, ademas de agregar las letras "a", "m" y "p", se agregaron las letras "h" y "r", estas se usan cuando la hora esta en formato de 24 horas y ademas la opción de "no mostrar los segundos" está activa
Para poder mostrar algunas opciones, se han agregado algunos símbolos, pero por ahora no se usan, decidí ponerlos en una matriz a parte para que se puedan modificar sin alterar los numero, ademas estos serán un poco mas "grandes" que los números, lo que hace necesario crear una función aparte para imprimirlos en las matrices.
Para empezar echemos un vistazo al nuevo código.
//Clockview 1.0 #include <DS1302.h> #include "LedControl.h" //Constantes para los pines usados en la matriz const int MaxDIn = 12; const int MaxCS = 11; const int MaxCLK = 10; int MaxNDevices = 3; bool IsConnected = false; //Constantes para los pines usados en el reloj const int kCePin = 7; // RST const int kIoPin = 8; // Dat const int kSclkPin = 9; // Serial Clock //Inicializacion de la matriz //DIN,CLK,CS LedControl lc = LedControl(MaxDIn, MaxCLK, MaxCS, MaxNDevices); //Inicializacion del reloj DS1302 rtc(kCePin, kIoPin, kSclkPin); //Algunas variables char Texto[24]; int MatrixB = 4; bool H24 = true; bool HalfSecond = true; bool IsScreenEnable = true; bool ShowSeconds = true; //Matriz con los "Numeros" const unsigned char Numbers[] = { B111110, B100010, B111110, //0 B100100, B111110, B100000, //1 B111010, B101010, B101110, //2 B100010, B101010, B111110, //3 B001110, B001000, B111110, //4 B101110, B101010, B111010, //5 B111110, B101010, B111010, //6 B000010, B000010, B111110, //7 B111110, B101010, B111110, //8 B001110, B001010, B111110, //9 B111110, B001010, B001110, //A B111110, B001100, B111110, //M B111110, B001010, B001110, //P B111110, B001000, B111110, //H B111110 ,B011010, B101110, //R }; //Definimos simbolos const unsigned char Symbols[] = { B0100010, B0010100, B0001000, B1111111, B0101010, B0010100, //BT 0 B0011110, B0100011, B0101101, B0100101, B0100101, B0011110, //Clock Adjust 1 }; //Imprimir simbolos void PrintSymbol(byte Index,byte SymDevice){ for (int Y = 1; Y < 7; Y++){ lc.setRow(SymDevice, Y, Symbols[Index * 5 + Y - 1]); } } //Funcion para escribir los numero en la matriz. void PrintNumber(byte NumberOne, byte NumberTwo, byte Device){ for (int X = 1; X < 8; X++){ if (X < 4){ lc.setRow(Device, X, Numbers[NumberOne * 3 + X - 1]); } if (X == 4){ lc.setRow(Device, 4, 0); } if (X > 4){ lc.setRow(Device, X, Numbers[NumberTwo * 3 + X - 5]); } } } //Imprimir el tiempo en las matrices y en el monitor serie void printTime(){ Time t = rtc.time(); const String day = dayAsString(t.day); char buf[50]; snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d", day.c_str(), t.yr, t.mon, t.date, t.hr, t.min, t.sec); PrintNumber(AdjustTime(t.hr, H24) / 10,AdjustTime(t.hr, H24) % 10, 0); PrintNumber(t.min / 10, t.min % 10, 1); if (ShowSeconds){ PrintNumber(t.sec / 10, t.sec % 10, 2); }else{ if(H24) PrintNumber(13, 14, 2); if(!H24 && (t.hr-12) < 13) PrintNumber(10, 11, 2); if(!H24 && (t.hr-12) > 12) PrintNumber(10, 12, 2); } //PrintSymbol(0, 2); if (HalfSecond == true){ digitalWrite(13, HIGH); HalfSecond = false; }else{ digitalWrite(13, LOW); HalfSecond = true; } Serial.println(buf); } //Ajustar la hora int AdjustTime(int Hour, bool In24Hformat){ if(In24Hformat == true){ return Hour; } else{ Hour = Hour - 12; return Hour; } } void CheckPetition(char DATA[]){ int i = 0; int j = 0; String Texto(DATA); //>SETH2016121221001007 //Bright = Texto.substring(4).toInt(); //MatrixB if (Texto.startsWith(">DISS")){ ShowSeconds = !ShowSeconds; Serial.print("No/Se muestran los segundos"); for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){ lc.shutdown(CurrentDevice, !IsScreenEnable); } for (j = 0; j < 11; j++) { DATA[j] = 0; } i = 0; } if (Texto.startsWith(">SCRA")){ IsScreenEnable = !IsScreenEnable; Serial.print("Las matrices se apagaron/encendieron"); for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){ lc.shutdown(CurrentDevice, !IsScreenEnable); } for (j = 0; j < 11; j++) { DATA[j] = 0; } i = 0; } if (Texto.startsWith(">SETF")){ H24 = !H24; Serial.print("EL reloj cambio de formato 12H-24H"); for (j = 0; j < 11; j++) { DATA[j] = 0; } i = 0; } if (Texto.startsWith(">SETH")){ AdjustTime(Texto.substring(9, 5).toInt(),Texto.substring(11,9).toInt(),Texto.substring(13, 11).toInt(), Texto.substring(15, 13).toInt(), Texto.substring(17, 15).toInt(), Texto.substring(19, 17).toInt(), Texto.substring(21, 19).toInt()); Serial.print("La hora se ajusto."); for (j = 0; j < 11; j++) { DATA[j] = 0; } i = 0; } if (Texto.startsWith(">SETB")){ MatrixB = Texto.substring(5).toInt(); Serial.print("El brillo se cambio"); for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){ lc.setIntensity(CurrentDevice, MatrixB); } for (j = 0; j < 11; j++) { DATA[j] = 0; } i = 0; } else { for (j = 0; j < 11; j++) { DATA[j] = 0; } i = 0; } } //Convertir los dias String dayAsString(const Time::Day day){ switch (day){ case Time::kSunday: return "DOM"; case Time::kMonday: return "LUN"; case Time::kTuesday: return "MAR"; case Time::kWednesday: return "MIE"; case Time::kThursday: return "JUE"; case Time::kFriday: return "VIE"; case Time::kSaturday: return "SAB"; } return "(unknown day)"; } //Ajustar la hora void AdjustTime(int Year,int Month, int Day, int Hour, int Minute, int Second, int DayOfWeek){ Time::Day CurrentDay; switch (DayOfWeek){ case 1: CurrentDay = Time::kSunday; break; case 2: CurrentDay = Time::kMonday; break; case 3: CurrentDay = Time::kTuesday; break; case 4: CurrentDay = Time::kWednesday; break; case 5: CurrentDay = Time::kThursday; break; case 6: CurrentDay = Time::kFriday; break; case 7: CurrentDay = Time::kSaturday; break; } //Esta parte se usa para actualizar la hora. rtc.writeProtect(false); rtc.halt(false); Time t(Year, Month, Day, Hour, Minute, Second, CurrentDay); rtc.time(t); } //Setup void setup(){ for (int CurrentDevice = 0; CurrentDevice < MaxNDevices; CurrentDevice++){ lc.shutdown(CurrentDevice, false); lc.setIntensity(CurrentDevice, MatrixB); lc.clearDisplay(CurrentDevice); } pinMode(13, OUTPUT); Serial.begin(9600); } //Loop void loop(){ int i = 0; printTime(); delay(500); if (Serial.available()) { while (Serial.available() > 0) { Texto[i] = Serial.read(); i++; } Texto[i] = '\0'; } CheckPetition(Texto); }
Analicemos un poco el código, para empezar, he creado algunas variables que sirven para controlar algunos de los aspectos del reloj. Podemos elegir entre mostrar la hora en formato de 12 o de 24 horas, decidir si se quiere mostrar o no los segundos y ademas, ahora podemos apagar las matrices, útil para cuando llega la hora de dormir.
En la matriz que almacena los datos de los números, ademas de agregar las letras "a", "m" y "p", se agregaron las letras "h" y "r", estas se usan cuando la hora esta en formato de 24 horas y ademas la opción de "no mostrar los segundos" está activa
La opción de 24 horas y la opción de "No mostrar los segundos" activos. |
La opción de 24 horas no está activa y la opción de no mostrar los segundos tampoco. |
//Imprimir simbolos void PrintSymbol(byte Index,byte SymDevice){ for (int Y = 1; Y < 7; Y++){ lc.setRow(SymDevice, Y, Symbols[Index * 5 + Y - 1]); } }
Cómo notarás, la mayor parte del código es similar a la función "PrintNumber", solo que en este caso, lee completamente de 5 en 5 y no de 3 en tres como en la función para mostrar los números. Recibe cómo parámetros, el indice en donde se encuentra la primera fila a desplegar y ademas, también recibe en que numero de matriz se va a mostrar el resultado.
La función "PrintTime" se ha modificado para que la hora se muestre de acuerdo a las opciones que el usuario haya pedido, en los casos anteriores, para mostrar la información de un formato u otro, solo basta con que se le mande un comando para que se hagan los cambios pertinentes. Toda la parte de los comandos lo veremos un poquito más adelante.
//Imprimir el tiempo en las matrices y en el monitor serie void printTime(){ Time t = rtc.time(); const String day = dayAsString(t.day); char buf[50]; snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d", day.c_str(), t.yr, t.mon, t.date, t.hr, t.min, t.sec); PrintNumber(AdjustTime(t.hr, H24) / 10,AdjustTime(t.hr, H24) % 10, 0); PrintNumber(t.min / 10, t.min % 10, 1); if (ShowSeconds){ PrintNumber(t.sec / 10, t.sec % 10, 2); }else{ if(H24) PrintNumber(13, 14, 2); if(!H24 && (t.hr-12) < 13) PrintNumber(10, 11, 2); if(!H24 && (t.hr-12) > 12) PrintNumber(10, 12, 2); } //PrintSymbol(0, 2); if (HalfSecond == true){ digitalWrite(13, HIGH); HalfSecond = false; }else{ digitalWrite(13, LOW); HalfSecond = true; } Serial.println(buf); }
Los cambios que se hicieron, son prácticamente los que indican el despliegue de la información, los nuevos "if" solo controlan que es lo que se debe de mostrar.
Cómo mencione en hace un poco, se han añadido algunos comandos que se usaran para modificar las propiedades del reloj sin la necesidad de re-compilar el código cada vez, actualmente los comandos disponibles son los siguientes:
- >DISS (Display Sesconds) - Intercambia entre mostrar o no los segundos.
- >SCRA (Screen Active) - Apaga o enciende las matrices.
- >SETF (Set Format) - Intercambia entre el formato de 12/24 horas.
- >SETHYYYYMMDDHHmmSSdd (Set Hour) - Cambia la hora del reloj, donde YYYY es el año, MM son los meses, DD son los días, HH son las horas en formato de 24 horas, mm son los minutos, SS los segundos y dd es el dia de la semana del 1 al 7 en donde el día 1 es domingo.
- >SETBxx (Set Brightness) - Cambia el brillo de las matrices, en donde xx es un valor que este entre el rango de 1 a 15, donde 1 es lo menos brillantes y 15 es el máximo.
Algo importante por mencionar es que todos los comados se enviaran por la interfaz serial, por lo que se puede usar el monitor serial del IDE de arduino u otros métodos que veremos un poco después.
Cuando se quiere ajustar la hora, podemos usar el comando ">SETH", si por ejemplo queremos establecer la siguiente hora:20:30:45 Miércoles 28 de diciembre del 2016, entonces el comando deberá de tener el siguiente aspecto. ">SETH2016122820304504". Si la hora que se quiere ingresar tiene un formato incorrecto, el reloj mostrará las 00:00:00 del 1/1/2000 domingo. si eso llegará a pasar, se corrige cuando se ingresa un fecha válida.
Para el caso del brillo, cualquier valor fuera de los limites validos (1-15) hará que las matrices tengan el brillo más bajo.
Por ultimo, se ha agregado una función que prende y apaga el LED que está conectado al PIN 13, esto con la finalidad de que se use como indicador, la mayoría de los relojes digitales, tiene un par de puntos entre cada par de dígitos que prenden y apagan cada segundo, si se quiere mostrar algo similar, bastara con conectar LED al pin 13.
Este reloj está lejos de ser terminado por completo, pero por ahora es todo, si en el transcurso de la semana llegan los otros componentes que quiero agregar, la semana que viene, veremos cómo agregar un medio para que todas las configuraciones que se cambien, queden guardadas y así si por alguna razón se quiere desconectar todo el proyecto, no se tendrán que hacer cambios a los ajustes cada vez.
Ademas de que agregaremos una solución "móvil" para que el reloj se pueda controlar a distancia.
Y bien, por ahora es todo, el código completo actualizado, cómo siempre, lo puedes descargar de mi dropbox.
Por ahora es todo. Los leo luego.
Creo que debes de poner los esquemas de las conexiones para que se entienda mejor
ResponderBorrarYa lo hice y va de maravilla pero cuando son las doce del dia, el reloj muestra que son las 0 horas, puedes arregalrlo
ResponderBorrar