Reloj que muestra la hora en forma de operaciones aritméticas (sumas y restas) para desarrollar el cálculo mental. También se puede poner en modo de funcionamiento normal.

Se controla por Bluetooth para cambiar de hora, funcionalidad y brillo de los leds. Posee un pulsador lateral que cambia la función de normal a aritmética. Muestra la información con dos pantallas matrices 8 módulos de 8×8 leds. Es alimentado con corriente continua de 35 a 5 Voltios.
Materiales necesarios
- 1 Arduino nano
- 2 Matrices leds rojos MAX7219
- 1 Módulo reductor DC-DC, LM2596 (opcional dependiendo de la fuente).
- 1 Módulo Bluetooth HC-05
- 1 Módulo reloj en tiempo real DS3231
- 1 Pulsador metálico 16mm
- 1 Conector de entrada CC 8mm
Matriz MAX7219
Compuesta de 4 módulos controlados por el chip MAX7219 que maneja cada matriz de 8×8, esto implica utilizar 16 señales digitales y refrescar la imagen de una forma constante.

Vamos a utilizar dos de estos paneles en el proyecto por lo que tendremos que unir los 5 hilos desde la salida de uno de ellos a la entrada del otro. Luego conectaremos en la entrada del primero los pines al Arduino. Usaremos D13 para CLK, D11 conectado a CL y D10 irá conectado al pin DIN (ver esquema eléctrico de conexiones).
Para alimentar los módulos recordar que no pueden ser alimentados por la salida de Arduino 5V, pues el consumo del display es muy superior a la entrega del micro-controlador. Teniendo en cuenta esto, deben conectarse directamente a la salida de corriente del LM2596.
Convertidor Voltaje DC-DC Step-Down 3A LM2596
El convertidor de voltaje DC-DC Step-Down 3A LM2596 tiene como función entregar un voltaje de salida constante inferior al voltaje de entrada frente a variaciones del voltaje de entrada o de carga. Soporta corrientes de salida de hasta 3A, voltaje de entrada entre 4.5V a 40V y voltaje de salida entre 1.23V a 37V. El voltaje de salida se selecciona mediante un potenciómetro multivuelta.

Es importante ajustar la salida para que entregue unos 5V de lo contrario podríamos dañar toda la electrónica.
Bluetooth HC-05
Se usará para cambiar la hora y algunas funciones desde el móvil. Lo conectaremos directamente al Serial de Arduino D0 y D1.

Se puede usar también SoftwareSerial para emplear otros pines, pero he decidido usar los directos. Esto hará que para enviar el código de programación del Arduino tenga que hacerse sin que el módulo esté conectado pues de lo contrario no conseguiremos programarlo. Una vez enviado el código debemos volver a conectarlo físicamente.
Los datos que recibirá el BT serán lo siguientes:
Si se recibe un «9» por el Serial el reloj interpretará que debe cambiar su función a expresiones aritméticas.
Si recibe un «8» entenderá que debe mostrar la hora de forma tradicional.
Cuando reciba un «6» encabezando una cadena, buscará el siguiente entero de la cadena que estará comprendido entre 0 y 15 para cambiar el brillo. de la forma «6,15».
Y para el cambio de hora se realizará cuando reciba una cadena de caracteres que empiece por «7» de la forma «7, x, y«. Donde x será el entero de la hora e y será el entero de los minutos.
Modulo re reloj D3231
Alimenta su memoria interna con una pila de 3V así en cualquier momento está en hora. Se comunica por el bus I2C por lo que resulta sencilla su implantación. Usaremos los pines A4 y A5 para SDA y SCL respectivamente. lo alimentaremos a 5 voltios. Los demás pines quedarán al aire.

Este módulo cuenta con un medidor de temperatura pero de baja precisión ±3ºC, y el tiempo de adquisición puede durar hasta 1 segundo. En la versión inicial se implementó su uso en el reloj, pero en la versión actual se desecha por motivos de fiabilidad y consumo. (Nótese que en el apartado del código de programación se menciona).
Pulsador
En un lateral encontramos un pulsador de 16mm de diámetro conectado a tierra y D2 en Pull-up (sin resistencias, directamente a los pines). Servirá para cambiar del modo de mostrar la hora.

En el modo aritmético se muestra una operación aleatoria cada minuto. Puede ser una suma o una resta y la elección de los operadores que intervienen también es aleatoria. Esto hace que las operaciones raramente se repitan.
Se muestran el modo aritmético y el modo normal de funcionamiento para las 7 y 55 minutos.
Conector CC para trasformador
Diámetro de 8mm está ubicado en la parte derecha con la etiqueta 35-5V.

Lo soldaremos a la entrada del LM2596 respetando la polaridad.
Esquema eléctrico y conexiones
La imagen real de las conexiones en la carcasa frontal.


Piezas de la caja
Constará de 2 tapas externas y 4 sujeciones internas en forma ce C para las pantallas leds.
Las pequeñas piezas en forma de «C» deben ir atornilladas a las pantallas led con tornillos 3M. Luego estas 4 piezas se anclarán sobre la carcasa frontal.

Consejo: una vez atornillada toda la electrónica y antes de cerrar la caja, te recomiendo que la equilibres con algún contrapeso pues el centro de masas puede hacer que al colocarlo en la pared tenga tendencia hacia algún lado.
Librerías
Las librerías empleadas en el proyecto son:
1 2 3 4 5 6 |
#include <EEPROM.h> #include <SPI.h> #include <bitBangedSPI.h> #include <MAX7219_Dot_Matrix.h> #include <Wire.h> #include <DS3231.h> |
La mayoría de las librerías empleadas se pueden descargar desde el IDE de Arduino, pero en el repositorio faltan algunas. Aquí puedes descargar las más específicas.
Código de programación
El código de programación fue realizado para un modelo anterior que contenía un módulo de matrices leds adicional que mostraba los grados centígrados del ambiente facilitados por el reloj DS3231 que aporta esa posibilidad. Se realizó un reloj con los 3 módulos operacionales con los inconvenientes del gran consumo de de energía para alimentar los paneles leds adicionales y de la poca precisión del sensor de temperatura del reloj que al estar demasiado cerca de los leds absorbía calor de los mismos dando lecturas con variaciones desviadas de la realidad dependiendo del brillo de los leds.
Por ello se decidió prescindir del dato de la temperatura y de uno de los módulos matriciales. En el código se ha mantenido la programación original pues no afecta al modelo actual aunque si se le añadiera este módulo opcional funcionaría como el original.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
/* Juan Carlos Pedrajas del Molino 2019 Reloj matemático polimónico. Revisión 19/02/2025 https://geniero.es/ código de envio por BT o serial. 38400 bps 9-> Muestra poliminio. 8-> Muestra la hora normal 7,int,int->ajusta la hora 6,int-> cambia el brillo de la pantalla */ #include <EEPROM.h> #include <SPI.h> #include <bitBangedSPI.h> #include <MAX7219_Dot_Matrix.h> #include <Wire.h> #include <DS3231.h> DS3231 rtc(SDA, SCL); Time t; MAX7219_Dot_Matrix myDisplay(12, 10); // 8 chips, and then specify the LOAD pin only unsigned long previousMillis = 0; long interval = 60000; int hora; int hora1; int hora2; int minuto; int minuto1; int minuto2; int segundo; String dates; float tempe; int modos = 255; String horita = ""; String minutito = ""; String b = ""; char c[11]; String cadenaInvertida; String h1 = ""; String h2 = ""; String m1 = ""; String m2 = ""; unsigned long currentMillis; int instante; String str = ""; const char separator = ','; const int dataLength = 3; int data[dataLength]; int ajuste = 1; //grados de temp que se restarán para ajustar a la temperatura real. int borra = 0; int intenso = 2; void setup() { pinMode(2, INPUT_PULLUP); EEPROM.get(0, intenso); rtc.begin(); Serial.begin(38400); Wire.begin(); myDisplay.begin(); myDisplay.setIntensity(intenso); // 15 maximo modos = 1; instante = 1; myDisplay.sendString(" se.oreineG"); delay(4000); polinomio(); } void loop() { currentMillis = millis(); if (Serial.available() > 0) { str = Serial.readStringUntil('\n'); Serial.println(str); for (int i = 0; i < dataLength; i++) { int index = str.indexOf(separator); data[i] = str.substring(0, index).toInt(); str = str.substring(index + 1); } if (data[0] == 9) { modos = 1; instante = 1; // primera vez del buble de 60 segundos. Salta el ciclo de intervalo la primera vez. } if (data[0] == 8) { modos = 2; instante = 1; } if (data[0] == 7) // cambio de hora. Se debe recibir: "7,hora,min". { rtc.setTime(data[1], data[2], 0); modos = 2; instante = 1; } if (data[0] == 6) { intenso = data[1]; EEPROM.put(0, intenso); myDisplay.setIntensity(intenso); } } if (digitalRead(2) == LOW) { modos = modos + 1; instante = 1; delay(300); if (modos >= 3) { modos = 1; } } switch (modos) { case 1: polinomio(); break; case 2: relojnormal(); break; } } String invertirCadena(String s) { /* La matrix que compré viene con los caracteres invertidos es necesaria esta función para invertir la cadena a mostar */ String temporal = ""; for (int m = s.length() - 1; m >= 0; m--) temporal += s[m]; return temporal; } void relojnormal() { t = rtc.getTime(); hora = t.hour; minuto = t.min; segundo = t.sec; tempe = rtc.getTemp(); tempe = tempe - ajuste; int kk = tempe * 10; int yy = kk / 10; float f = tempe - yy; int decimal = f * 10; String uno = (String)minuto; if (intenso > 5) { dates = (" "); } else { dates = (String)yy + "." + (String)decimal; } String horacero; if (hora < 10) { horacero = "0" + (String)hora; } else { horacero = (String)hora; } if (uno.length() < 2) { b = horacero + " 0" + (String)minuto + " "; } else { b = horacero + " " + (String)minuto + " "; } cadenaInvertida = invertirCadena(b); cadenaInvertida = dates + cadenaInvertida; cadenaInvertida.toCharArray(c, 14); if (instante == 3) { if (segundo == 0) { myDisplay.sendString(c); } } else { myDisplay.sendString(c); instante = 3; } } void polinomio() { t = rtc.getTime(); hora = t.hour; minuto = t.min; tempe = rtc.getTemp(); tempe = tempe - ajuste; segundo = t.sec; int kk = tempe * 10; int yy = kk / 10; float f = tempe - yy; int decimal = f * 10; if (hora > 12) { hora = hora - 12; } hora1 = random(hora + 9); if (hora1 >= hora) { hora2 = hora1 - hora; h1 = (String)hora1; h2 = (String)hora2; horita = h1 + "-" + h2; } else { hora2 = hora - hora1; h1 = (String)hora1; h2 = (String)hora2; horita = h1 + "+" + h2; } // Minutos minuto1 = random(minuto - 9, minuto + 9); if (minuto1 < 0) { minuto1 = minuto1 * -1; } if (minuto1 >= minuto) { minuto2 = minuto1 - minuto; m1 = (String)minuto1; m2 = (String)minuto2; minutito = m1 + "-" + m2; } else { minuto2 = minuto - minuto1; m1 = (String)minuto1; m2 = (String)minuto2; minutito = m1 + "+" + m2; } if (minutito.length() < 4) { minutito = " " + minutito; } if (intenso > 5) { dates = (" "); } else { dates = (String)yy + "." + (String)decimal; } b = (String)horita + (String)minutito; cadenaInvertida = invertirCadena(b); cadenaInvertida = dates + cadenaInvertida; cadenaInvertida.toCharArray(c, 14); if (instante == 3) { if (segundo == 0) { int tt = 1; if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; if (tt == 1) { myDisplay.sendString(c); tt = 2; } } } } else { myDisplay.sendString(c); instante = 3; } } |
Android
Para controlar el reloj desde un dispositivo Android con bluetooth hemos creado este pequeña aplicación que es bastante básica. En la que podemos controlar el comportamiento del reloj como cuando se pulsa el pulsador del mismo, ajustar la hora y alterar la intensidad del brillo de los leds de la pantalla.
Está realizada con MIT App Inventor 2 que es una aplicación online para desarrollar aplicaciones APK que se pueden instalar en móviles y tabletas Android.

La forma de programación es por bloques y gráfica. Aquí tienes una parte del código que puedes descargar más abajo.
Aquí puedes descargar la aplicación.