RELOJ BINARIO A DECIMAL

INTEGRANTES DEL GRUPO

  1. SANTIAGO RAMOS GÓMEZ

INTRODUCCIÓN

He decidido realizar un reloj binario como proyecto de DSE. Este es un curioso formato para medir la hora, ya que se deben sumar los leds de las columnas para obtener números:

Figura 1: Ejemplo de reloj binario.
Fuente de la imagen: https://es.wikipedia.org/wiki/Reloj_binario

Desde un principio quería realizar una práctica que tuviera LEDs, ya que había visto en un montón de video de YouTube auténticas barbaridades, además, el hecho de que se puedan variar colores, posiciones y velocidades abría un montón de puertas a posibles proyectos.
Se comenzó con dos ideas: un reloj binario o un juego.
Al final decidí decantarme por el reloj ya que me parecía mucho más nicho que un juego ya creado como es el de la serpiente, el cual no descarto hacer en un futuro. En un principio quería que fuera un reloj que mostrara la hora de varios países en función del botón, pero decidí continuar con este inexplorado binario.
Habiendo tomado una decisión final me puse a trastear con la matriz LED que incluye la caja de Arduino proporcionada. Tras un rato me di cuenta de que en esta solo se podían encender filas y columnas, pero en ningún momento podía encender una posición especifica (o al menos no lo supe hacer). Tras esto navegué un poco por internet para ver que necesitaba y que modelos, que tipos de conexiones y lo más importante, cuándo llegaría, ya que la nevada de Madrid no ponía las cosas fáciles. Por último, necesitaba que algo me proporcionara la hora local y no paraba de ver en foros y post que Arduino como tal no proporcionaba esto, así que recurrí a la compra de un reloj conectado a una batería. Teniendo todos los materiales, solo me faltaba continuar con las bases de Arduino y electrónica.
Por último, comentar que este proyecto lo he realizado solo, ya que mi anterior grupo planteaba algo demasiado difícil para mí.

HARDWARE

Para esta práctica se han utilizado:

COMPONENTESCANTIDADPRECIO
Protoboard 64×10 pines 10, ya la tenía
Modulo de Arduino UNO 10, venía incluidos en la caja
Resistencia de 1KΩ 10, venía incluidos en la caja
Reloj WINGONEER DS3231 AT24C32I2C 16€
Paneles LED 8×8 310€
Botón/Pulsador 10, venía incluidos en la caja
Cables Muchos0, venían incluidos en la caja

Por lo cual, con un gasto de aproximadamente 16€, he podido realizar el proyecto al completo.
Las conexiones de manera resumida son las siguientes:


• Protoboard: Vin y Vout de la placa Arduino en ambas filas. Una resistencia de 1KΩ a Vout y la pata de un botón (a la otra Vin), esta conexión llevada al pin 8 de la placa de Arduino. Las tres matrices LED con Vin y Vout en sus correspondientes puertos. El reloj conectado a Vin y Vout.


• Placa Arduino UNO: Se han tomado los pines de Vin(5v), Vout.
Pines 13,11,10: conectados a los puertos CLK, DOUT y GS de las matrices LED. (entre las matrices LED), el puerto DOUT se comparte en cascada entre ellas, teniendo que conectar los pines DIN con los DOUT de los anteriores).


Pin 8: Conexión al botón.


Pines A5, A4: conectados a los puertos SCL (clock/ reloj) y SDA (data/datos) del reloj.


Todas estas conexiones se pueden ver con mayor perspectiva en el video.


El único problema que he tenido ha sido el que comenté en la introducción. La matriz de LEDs proporcionada en la caja no se podía encender una posición específica.

Figura 2: conexión trasera de los LEDs (efectivamente, no se aprecia mucho porque está hecho un lio).

SOFTWARE

El código es bastante extenso pero sencillo, se podría dividir en las siguientes partes:


• Definición de variables, número de matrices y sus pines y el pin del botón.
• Funciones implementadas del propio reloj para obtener la hora y temperatura.
• Separación de las horas, minutos y segundos.
• Comprobar si el botón se ha pulsado o no y dependiendo del caso mostrar por pantalla la hora en estado decimal o binario.
• Las funciones Binario (mostrar por pantalla en binario) y Dibujar (mostrar por pantalla en decimal), las cuales se componen de un “switch” que determina el número a dibujar. Dentro de los “Case” se muestran los LEDs a encender y apagar para poder dibujar este número.


El principal problema que he tenido ha sido la pulsación del botón ya que provocaba un efecto rebote y tuve que consultar por internet como solucionarlo.


También, encontré que estaba actualizando TODAS las pantallas cuando pasaba un segundo, en vez de solo la parte de los segundos, por lo cual, al estar dentro de la función Loop() y se comprobara de continuo, provocaba un parpadeo muy incómodo de los LEDs. Para solucionar esto decidí poner unas variables de control. Estas se irían actualizando cada vez que pasar una hora, minuto o segundo, dependiendo. Si había cambiado algo refrescaba la pantalla LED, si no, no ocurría nada.


Ejemplo:
horaControl = -1;
minutoControl = -1;
horaReal = 9; -> horaControl = 9;
minutosReal = 16; -> minutoControl = 16;
Pasa un minuto:
horaReal y horaControl son las mismas, por lo cual nada ha cambiado, no se actualiza la pantalla.
minutosReal = 17 y minutoControl = 16; Ya no son los mismos valores, por lo cual se actualiza la pantalla de minutos y se copia de nuevo el valor real al de control.

CÓDIGO ARDUINO

#include <DS3232RTC.h> 
#include <Streaming.h>     
#include <TimeLib.h>
#include <Wire.h>
#include "LedControlMS.h"

LedControl lc=LedControl(11,13,10,3); 

void Binario(int numero, int tipo);
void Dibujar(int matrix, int num, int tipo);

int Horas1, Horas2;
int Min1, Min2;
int Sec1, Sec2;

//Para comparar con los otros tiempos y no esta parpadeando todo el raot la matriz de LEDs
int Horas1C = -1;
int Horas2C = -1;
int Min1C = -1;
int Min2C = -1;
int Sec1C = -1;
int Sec2C = -1;

//Boton
int Pulsador=8;

int inicio = 0;
int estadoAN = 0;
int estadoAC =0;

void setup()
{


Serial.begin(115200);
int devices=lc.getDeviceCount();
for(int address=0;address<devices;address++) {
lc.shutdown(address,false);
lc.setIntensity(address,8);
lc.clearDisplay(address);
}
    
    setSyncProvider(RTC.get);
    Serial << F("RTC Sync");
    if (timeStatus() != timeSet) Serial << F(" FAIL!");
    Serial << endl;
    
    pinMode(Pulsador, INPUT);
}

void loop()
{
    static time_t tLast;
    time_t t;
    tmElements_t tm;
    // check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
    if (Serial.available() >= 12) {
        // note that the tmElements_t Year member is an offset from 1970,
        // but the RTC wants the last two digits of the calendar year.
        // use the convenience macros from the Time Library to do the conversions.
        int y = Serial.parseInt();
        if (y >= 100 && y < 1000)
            Serial << F("Error: Year must be two digits or four digits!") << endl;
        
            tm.Day = Serial.parseInt();
            tm.Hour = Serial.parseInt();
            tm.Minute = Serial.parseInt();
            tm.Second = Serial.parseInt();
            t = makeTime(tm);
            RTC.set(t);        // use the time_t value to ensure correct weekday is set
            setTime(t);
            Serial << F("RTC set to: ");
            printTime(t);
            Serial << endl;
            // dump any extraneous input
            while (Serial.available() > 0) Serial.read();
        
    }

    t = now();
    if (t != tLast) {
        tLast = t;
        printTime(t);
        if (second(t) == 0) {
            float c = RTC.temperature() / 4.;
            float f = c * 9. / 5. + 32.;
            Serial << F("  ") << c << F(" C  ") << f << F(" F");
        }
        Serial << endl;
    }



    
Horas1 = hour(t)/10;
Horas2 = hour(t)%10;
Min1 = minute(t)/10;
Min2 = minute(t)%10;
Sec1 = second(t)/10;
Sec2 = second(t)%10;

estadoAC = digitalRead(Pulsador);
if(estadoAC && estadoAN == 0){
  inicio = 1-inicio;
  delay(100);
  Horas1C=-1;
  Min1C=-1;
  Sec1C=-1;
lc.clearDisplay(0);
lc.clearDisplay(1);
lc.clearDisplay(2);


}
  estadoAN = estadoAC;

  
  if(inicio == 1){
if(Horas1C!=Horas1 || Horas2C!= Horas2){
  Horas1C=Horas1;
  Horas2C=Horas2;
lc.clearDisplay(0);
Dibujar(0,Horas1,1);
Dibujar(0,Horas2,2);
}
if(Min1C!=Min1 || Min2C!= Min2){
  Min1C = Min1;
  Min2C = Min2;
lc.clearDisplay(1);
Dibujar(1,Min1,1);
Dibujar(1,Min2,2);
} 
if(Sec1C!=Sec1 || Sec2C!= Sec2){
  Sec1C = Sec1;
  Sec2C = Sec2;
lc.clearDisplay(2);
Dibujar(2,Sec1,1);
Dibujar(2,Sec2,2);
}
  }else{

Binario(Horas1,0);
Binario(Horas2,1);

Binario(Min1,3);
Binario(Min2,4);

Binario(Sec1,6);
Binario(Sec2,7);


}
}
// print time to Serial
void printTime(time_t t)
{
    printI00(hour(t), ':');
    printI00(minute(t), ':');
    printI00(second(t), ' ');
}


// Print an integer in "00" format (with leading zero),
// followed by a delimiter character to Serial.
// Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
{
    if (val < 10) Serial << '0';
    Serial << _DEC(val);
    if (delim > 0) Serial << delim;
    return;
}
void Binario(int numero, int tipo){ //tipo = horas, min, sec
int matrix=0;
switch(numero){
  case 0:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,false);
     lc.setLed(matrix,tipo,5,false); 
     lc.setLed(matrix,tipo,4,false);
     break;
  case 1:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,false);
     lc.setLed(matrix,tipo,5,false); 
     lc.setLed(matrix,tipo,4,true);
     break;
  case 2:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,false);
     lc.setLed(matrix,tipo,5,true); 
     lc.setLed(matrix,tipo,4,false);  
     break;      
  case 3:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,false);
     lc.setLed(matrix,tipo,5,true); 
     lc.setLed(matrix,tipo,4,true);
     break;
  case 4:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,true);
     lc.setLed(matrix,tipo,5,false); 
     lc.setLed(matrix,tipo,4,false);
     break;
  case 5:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,true);
     lc.setLed(matrix,tipo,5,false); 
     lc.setLed(matrix,tipo,4,true);  
     break;
  case 6:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,true);
     lc.setLed(matrix,tipo,5,true); 
     lc.setLed(matrix,tipo,4,false); 
     break;
  case 7:
     lc.setLed(matrix,tipo,7,false); 
     lc.setLed(matrix,tipo,6,true);
     lc.setLed(matrix,tipo,5,true); 
     lc.setLed(matrix,tipo,4,true); 
     break;
  case 8:
     lc.setLed(matrix,tipo,7,true); 
     lc.setLed(matrix,tipo,6,false);
     lc.setLed(matrix,tipo,5,false); 
     lc.setLed(matrix,tipo,4,false);   
     break;
  case 9:
     lc.setLed(matrix,tipo,7,true); 
     lc.setLed(matrix,tipo,6,false);
     lc.setLed(matrix,tipo,5,false); 
     lc.setLed(matrix,tipo,4,true); 
     break;             
}

}
void Dibujar(int matrix, int num, int tipo){ //matrix = si está en la 0(horas), 1(min), 2(sec), num es el numero a escribir y tipo es h1/h2 m1/m2 s1/s2, es decir, su posición, esto espera los valores: 1 y 2.

  if(tipo==2){
    tipo = 5;
  }
    //lc.clearDisplay(0);

  switch(num){

  case 0:
      for(int i=1;i<8;i++){
          lc.setLed(matrix,tipo-1,i,true);
          lc.setLed(matrix,tipo+1,i,true);
      }
          lc.setLed(matrix,tipo,1,true);
          lc.setLed(matrix,tipo,7,true);
  break;
  
  case 1:
   for(int i=1;i<8;i++){
      lc.setLed(matrix,tipo+1,i,true);
    }
  break;
  case 2:
         for(int i=1;i<4;i++){
         lc.setLed(matrix,(tipo-2+i),7,true);
         lc.setLed(matrix,(tipo-2+i),4,true);
         lc.setLed(matrix,(tipo-2+i),1,true);
          }
         lc.setLed(matrix,tipo+1,6,true);
         lc.setLed(matrix,tipo+1,5,true);
         lc.setLed(matrix,tipo-1,2,true);
         lc.setLed(matrix,tipo-1,3,true);
  break;
  case 3:
         for(int i=1;i<4;i++){
         lc.setLed(matrix,(tipo-2+i),7,true);
         lc.setLed(matrix,(tipo-2+i),4,true);
         lc.setLed(matrix,(tipo-2+i),1,true);
          }
         lc.setLed(matrix,tipo+1,6,true);
         lc.setLed(matrix,tipo+1,5,true);
         lc.setLed(matrix,tipo+1,2,true);
         lc.setLed(matrix,tipo+1,3,true);
  break;
  case 4:
         for(int i=1;i<8;i++){
         lc.setLed(matrix,tipo+1,i,true);
         }
         for(int i=0;i<3;i++){
         lc.setLed(matrix,(tipo-1+i),4,true);
         lc.setLed(matrix,tipo-1,i+5,true);
         }
         
        
  break;
  case 5:
           for(int i=1;i<4;i++){
         lc.setLed(matrix,(tipo-2+i),7,true);
         lc.setLed(matrix,(tipo-2+i),4,true);
         lc.setLed(matrix,(tipo-2+i),1,true);
          }
         lc.setLed(matrix,tipo-1,6,true);
         lc.setLed(matrix,tipo-1,5,true);
         lc.setLed(matrix,tipo+1,2,true);
         lc.setLed(matrix,tipo+1,3,true);
  break;
  case 6:
  for(int i=1;i<4;i++){
         lc.setLed(matrix,(tipo-2+i),7,true);
         lc.setLed(matrix,(tipo-2+i),4,true);
         lc.setLed(matrix,(tipo-2+i),1,true);
          }
         lc.setLed(matrix,tipo-1,6,true);
         lc.setLed(matrix,tipo-1,5,true);
         lc.setLed(matrix,tipo+1,2,true);
         lc.setLed(matrix,tipo+1,3,true);
         lc.setLed(matrix,tipo-1,2,true);
         lc.setLed(matrix,tipo-1,3,true);
         
  break;
  case 7:
     for(int i=1;i<8;i++){
      lc.setLed(matrix,tipo+1,i,true);
    }
     lc.setLed(matrix,tipo,7,true);
     lc.setLed(matrix,tipo-1,7,true);
  break;

  case 8:
  for(int i=1;i<4;i++){
         lc.setLed(matrix,(tipo-2+i),7,true);
         lc.setLed(matrix,(tipo-2+i),4,true);
         lc.setLed(matrix,(tipo-2+i),1,true);
          }
         lc.setLed(matrix,tipo-1,6,true);
         lc.setLed(matrix,tipo-1,5,true);
         lc.setLed(matrix,tipo+1,6,true);
         lc.setLed(matrix,tipo+1,5,true);
         lc.setLed(matrix,tipo+1,2,true);
         lc.setLed(matrix,tipo+1,3,true);
         lc.setLed(matrix,tipo-1,2,true);
         lc.setLed(matrix,tipo-1,3,true);
  break;

  case 9:
    for(int i=1;i<4;i++){
         lc.setLed(matrix,(tipo-2+i),7,true);
         lc.setLed(matrix,(tipo-2+i),4,true);
         lc.setLed(matrix,(tipo-2+i),1,true);
          }
         lc.setLed(matrix,tipo-1,6,true);
         lc.setLed(matrix,tipo-1,5,true);
         lc.setLed(matrix,tipo+1,6,true);
         lc.setLed(matrix,tipo+1,5,true);
         lc.setLed(matrix,tipo+1,2,true);
         lc.setLed(matrix,tipo+1,3,true);
  break;
}
}

FUNCIONAMIENTO


Por último, los casos de uso. Estos son únicamente dos y dependen de la pulsación del botón. Al comienzo se mostrará en estado binario y al pulsar el botón en estado decimal y viceversa.


En el vídeo se puede ver perfectamente el funcionamiento a tiempo real del reloj.


Este apartado no me ha traído excesivos problemas, pero por aquí dejo algunos de los imprevistos:


En un principio no sabía cómo realizar la conexión en cascada y sólo podía utilizar una matriz LED, pero no fue nada grave. El parpadeo de los LEDs ya ha quedado explicado, junto con el botón.


Lo más grave fue que programé el reloj de tal manera que seguía el orden 1,2,4,8; en vez del original 8,4,2,1. Fue un poco molesto por el tema de tener que editar el código, pero de nuevo digo, nada realmente problemático.


Por último, aprovecho para informar que el funcionamiento del reloj binario se da en el área delimitada por el rectángulo rojo, para que no se sufran confusiones con los números.

REFERENCIAS


https://es.wikipedia.org/wiki/Reloj_binario
https://www.prometec.net/scroll-max7219/
https://www.makerguides.com/max7219-led-dot-matrix-display-arduino-tutorial/
https://www.youtube.com/watch?v=Z-66x-9-7T0
https://www.youtube.com/watch?v=_QNUIiuW2N0&t=377s
https://www.youtube.com/watch?v=nmul0-Z9lks&ab_channel=iTechWare

VÍDEO CASOS DE USO

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *