Shadowplay LED Watch en la plataforma Arduino Uno

En lugar de unirse




Entonces, nuestro equipo de tres personas tenía la tarea: armar un pequeño proyecto de hardware en muy poco tiempo, preferiblemente en la plataforma Arduino. Vale la pena mencionar que hasta ese momento estábamos familiarizados con los circuitos, en su mayor parte, en teoría. Y esto significa: ni experiencia con un soldador (prácticamente), ni, especialmente, experiencia con Arduino.

De repente nos topamos con un artículodedicado al proyecto Shadowplay Clock. Este es un reloj de pared diseñado por un equipo de diseñadores vieneses, el momento en el que puedes ver tocando un dedo en su centro. Los LED se iluminan de tal manera que la sombra del dedo en el centro muestra la hora. Se decidió crear lo mismo (o muy similar), pero en casa. El artículo anterior, como puede ver, no contiene una descripción detallada del proyecto. De todo esto se dedujo que nosotros mismos teníamos que descubrir cómo funciona este dispositivo y darle vida. Lo que, de hecho, hicimos.

Materiales


Para crear un reloj necesitas:

  • espacios en blanco de fibra de madera
  • Tira de 60 diodos LED
  • Arduino uno
  • Módulo de reloj de tiempo real RTC DS1307
  • botón
  • protoboard
  • registro de desplazamiento 74HC595 (x2)
  • Pestillo de registro de 8 bits 74HC573N (x8)
  • decodificador 4-16 K155ID3
  • inversor de drenaje abierto IN74HC05AN (x10)
  • unidad de potencia

Empecemos


Entonces, el algoritmo del dispositivo:

  1. Cuando se aplica energía, los LED se encienden en una combinación predeterminada. En el Shadowplay original, todos los LED se encendieron, pero nos pareció que sería más interesante lanzar alguna combinación como protector de pantalla.
  2. Cuando se presiona el botón (sí, también nos alejamos del original e insertamos un pequeño botón en el centro), el tiempo se lee desde el módulo RTC.
  3. El tiempo de lectura se convierte en código binario (máscara) y se ingresa en los registros.
  4. Dependiendo de la máscara, se enciende el diodo requerido.

Hardware


Cuando finalmente decidimos la idea del proyecto, lo primero que intentamos fue esbozar mentalmente versiones aproximadas de los esquemas para su implementación. La pregunta principal era cómo abordar 60 LED. De hecho, la respuesta a esta pregunta determinó el método de construcción de casi todo el esquema.

La primera opción que me vino a la mente fue el uso de decodificadores. El circuito compilado era una cascada de cuatro decodificadores 4-16 y un decodificador 2-4, ambos con entradas habilitadas para descifrado. Tal cascada permitió el direccionamiento a 64 salidas, lo que fue más que suficiente para conectar 60 LED.

Sin embargo, surgió la pregunta de cómo hacer que más de un LED funcione (dirección) al mismo tiempo (después de todo, necesitábamos proporcionar al reloj al menos las manecillas de los minutos y del reloj). Aquí se manifestó el principal inconveniente de este esquema: el decodificador no puede, por definición, abordar más de una salida a la vez.

Este defecto nos obligó a abandonar la idea con una cascada de decodificadores. Además, ahora tenemos otro requisito para el futuro circuito: soporte para la operación simultánea de un número diferente de LED.

Para satisfacer este requisito, pensamos que es posible habilitar cada LED para almacenar su estado. Los registros son adecuados para este propósito, donde cada descarga individual corresponde al estado de uno de los LED. Decidimos usar registros de 8 bits, ya que son más comunes y más prácticos. En consecuencia, en nuestro circuito necesitaremos 8 de estos registros para proporcionar soporte para 60 LED.

Luego, pensamos en cómo controlar el estado de los LED con Arduino a través de registros. Cada registro para el funcionamiento normal debe recibir los 8 bits en su totalidad. Arduino Uno, por supuesto, proporciona suficientes salidas para transmitir varios bits a la vez, pero este enfoque no será racional. Además, el esquema contiene solo 8 registros, lo que significa que debe abordarlos de alguna manera. Para este propósito, agregamos un decodificador y dos registros de desplazamiento de 8 bits conectados en cascada al circuito. Un registro de desplazamiento almacena una máscara de estado de 8 bits, que se cargará en uno de los 8 registros regulares, cuyo número se almacena en el segundo registro de desplazamiento. En consecuencia, un decodificador está conectado al segundo registro de desplazamiento. Para estos fines, un decodificador de 3 por 8 es suficiente.

Para eliminar la inversión del número requerido de salidas, utilizamos dos circuitos inversores KR1533LN1. Esto, por supuesto, complica un poco el esquema.

Otra tarea era el voltaje de funcionamiento de los LED igual a 12 voltios en comparación con los 5 voltios de los circuitos lógicos. La solución propuesta fue utilizar un inversor de drenaje abierto. Tal microcircuito desempeña el papel de una tecla que cierra (con 1 lógico) o abre (con 0 lógico) uno de los contactos del LED con la tierra, por lo que enciende o apaga el LED. El circuito asume una operación de 12 voltios, de acuerdo con el voltaje de funcionamiento de los LED, por lo que para obtener 5 voltios para circuitos lógicos, se agregó al circuito el estabilizador KR142EN5A con dos condensadores.

Algunas entradas de ciertos microcircuitos implican un valor constante en la entrada, por lo que se conectaron a tierra o a una fuente de alimentación. En este caso, estas son las siguientes entradas:

  • La entrada inversa de restablecimiento de MR en ambos registros de desplazamiento está conectada a través del registro de carga a la salida del estabilizador a 5 voltios.
  • La entrada de habilitación de salida de OE inversa en ambos registros de desplazamiento está conectada directamente a tierra.
  • Decodificador inverso habilitar entrada E0 conectado a tierra




El circuito está controlado por cuatro entradas (E1, SH, ST, DS). El propósito y los niveles de señal de cada uno de ellos se analizan con más detalle a continuación:

La entrada E1 está diseñada para habilitar el decodificador. En nuestro caso, inicialmente en el decodificador hay dos entradas de control E1, E0, y ambas son inversas. Habrá suficiente una salida, por lo que la segunda (E0) puede llevarse al suelo. El estado del decodificador "predeterminado" es operativo hasta que se aplique un nivel de señal alto a E1. Para hacer lo contrario, conectamos esta entrada al inversor. Sin esto, el decodificador puede dar señales de control incorrectas a los registros, por ejemplo, al momento de actualizar los datos en el registro de desplazamiento. Como ya se mencionó, se puede usar un decodificador de 3 por 8 en el circuito, que puede tener una entrada de control no inversa, lo que facilitará la resolución de todos los problemas descritos anteriormente sin cables adicionales y un soldador.

Cuando se aplica un solo nivel de señal a E1, el decodificador decodifica la dirección de registro ubicada en el registro de desplazamiento correspondiente y envía una señal a la salida deseada. Después de eso, el decodificador se apaga nuevamente aplicando un nivel de señal bajo a E1. Tal interruptor del decodificador genera una señal en la salida deseada, cuyo borde y decaimiento sirve como un pulso de reloj de registro para ajustar en sí mismo los datos almacenados en el bus.

Las siguientes tres entradas ya están destinadas a controlar los registros de desplazamiento. Vale la pena comenzar con lo más simple: la entrada de datos DS. Esta entrada, como su nombre lo indica, está destinada a la transmisión de datos. Dado que los registros de desplazamiento en el circuito están conectados en cascada, el DS representa la salida correspondiente de uno de ellos. La entrada del segundo registro de desplazamiento está conectada a la salida del último bit del primer registro. El resultado es un registro de desplazamiento para 16 bits, de los cuales solo se utilizan 12 bits.

La entrada SH es una entrada de reloj. Se alimenta una onda cuadrada a esta entrada, que es responsable de cargar y cambiar los datos en cada uno de los registros, respectivamente, este contacto del circuito está conectado a los pines SHCP de ambos registros.

El último pin ST sirve como un pestillo de datos en las salidas del registro. Se da un impulso a esta entrada, sin embargo, solo se suministra cuando los datos en el registro de desplazamiento se cargan finalmente y se requiere fijarlos en la salida de los registros. Solo después de dar esta señal, los datos descargados dentro del registro en la primera fila de disparadores llegan a la segunda fila de disparadores y están disponibles en el bus. ST es un pin conectado a los pines STcp de ambos registros.

Queda por explicar el cableado de los dos pines de los registros de desplazamiento MR y OE. La primera entrada (MR) es responsable de descargar los datos dentro del registro. En este circuito, no se requiere dicha oportunidad, por lo tanto, se suministra un alto nivel de señal a esta salida a través de la carga.

La segunda entrada de registro (OE) es responsable de desconectar la segunda fila de disparadores dentro del registro de desplazamiento del bus, es decir, la entrada de habilitación. Esta función tampoco es necesaria, por lo tanto, la salida se enrolla en el suelo.

Otro contacto no descrito anteriormente está diseñado para eliminar el nivel de señal del botón en el centro del reloj, el diagrama de botones es típico y representa una carga y una tecla, dependiendo de la posición de la cual se envía un nivel de señal bajo o alto al Arduino. Dependiendo del estado del botón, el reloj funciona en modo de protector de pantalla o en modo de visualización de la hora.
La conexión al Arduino no tiene características especiales, excepto que el pin SH está idealmente conectado al pin digital SCK. El resto de las salidas del circuito se pueden conectar a cualquiera de las entradas digitales de uso general disponibles. En nuestro caso, la conexión tiene la siguiente forma:

  • Arduino pin13 (SCK) – SH
  • Arduino pin 11 – ST Arduino pin 8 – DS Arduino pin 5 – E1 Arduino pin 3 – Arduino pin GND – ( )
    , .

    : 36 — ; 36 ( ) \ 26 ( ) — . Shadowplay 72 , 36. , 60 ( + ). . , , , .



    , . , . , . , «» 50 — 60, . , 60 . : — .



    , , , . — . , , . , — .

    .


    -, .

    Shadowplay. , , . , , . , .. . , , 100% . , . . , . , .

    , ( ), , — . , , ! . , - - . , , . , , . , , , . ., - . , , , , , .



    , . . .. , , ( , , ), .


    , (). Arduino. , RTC, — . DS1307, — I2C. 2100 . . RTC Arduino, . RTC.



    , RTC, .

    #include <Time.h>
    #include <DS1307RTC.h>
    
    char REG [8];
    tmElements_t te;
    int c,reset=1;
    
    void setup() {
      pinMode(13, OUTPUT); 
      pinMode(11, OUTPUT); 
      pinMode(8, OUTPUT);  
      pinMode(5, OUTPUT);  
      pinMode(3, INPUT);   
      Serial.begin(57600);
      
      //      RTC  
      //te.Hour = 18;
      //te.Minute = 50;
      //te.Second = 0;
      //te.Day = 20; //
      //te.Month = 4; // 
      //te.Year = CalendarYrToTm(2016); 
      //RTC.write(te);
    }
    
    void loop()
    { 
    if(digitalRead(3))                    // ,     
      {RTC.read(te);
       SetShadowTime(te.Hour,te.Minute,te.Second,2);        //         
       delay(900);
       reset=1;
      }
    
    else                                   //    ,  
      {wait1();
       reset=1;
      }
                                             //  
      for(int j = 0; j<8 ; j++) SetUpLightByMask(j,0); 
       
     
    }
    
    
    //======================================================================= 
    
    void SetUpLightByMask(int RegNum, char LightMask) //         
    {
      
      digitalWrite(5, LOW);
      digitalWrite(11, LOW);
      shiftOut(8, 13, MSBFIRST, LightMask);
      shiftOut(8, 13, LSBFIRST, RegNum);
      digitalWrite(11, HIGH);
      digitalWrite(5, HIGH);
    }
    
    void digitalClockDisplay() {  //    RTC  ,    RTC  
      RTC.read(te);
      Serial.print(te.Hour);
      Serial.print(" : ");
      Serial.print(te.Minute);
      Serial.print(" :");
      Serial.print(te.Second);
      Serial.print(" ");
      Serial.print(te.Day);
      Serial.print(" ");
      Serial.print(te.Month);
      Serial.print(" ");
      Serial.print(tmYearToCalendar(te.Year));
      Serial.println();
    }
    
    //     ,     , ,        :
    //0 -  ,1 -   , 2 -    
    
    void SetShadowTime(int Hours, int Minutes, int Seconds, int param){   
      int h,hshift,m,s;
      for(int j = 0; j<8 ; j++) REG[j] = 0;
    
      if(Hours >= 12) Hours -= 12;
      h = Hours + 6;
      if(h >= 12) h -= 12;
        
      hshift = (int) Minutes / 12;
      
      REG[(int)(((h*5)+hshift)/8)] = REG[(int)(((h*5)+hshift)/8)] | 1<<(((h*5)+hshift)%8);
                 
       
      if(param == 1)
      {m = Minutes + 30;
       if(m >= 60) m -= 60;
       REG[(int)(m/8)] = REG[(int)(m/8)] | 1<<(m%8);
       }
    
      if(param == 2)
      {m = Minutes + 30;
       if(m >= 60) m -= 60;
       REG[(int)(m/8)] = REG[(int)(m/8)] | 1<<(m%8);
         
       s = Seconds + 30;
       if(s >= 60) s -= 60;
       REG[(int)(s/8)] = REG[(int)(s/8)] | 1<<(s%8);
      }
    
      for(int j = 0; j<8 ; j++) SetUpLightByMask(j,REG[j]);
      }
      
    void wait1() //    
    {for(int a = 0; a < 8; a++)
        {c=0;
         for(int b = 0; b < 8; b++)
          {c = c << 1;
           c = c | 1;
           SetUpLightByMask(a, c);  
           delay(10);   
          }
       }
      for(int a = 0; a < 8; a++)
        {c=255;
          for(int b = 0; b < 8; b++)
          {c = c << 1;
           SetUpLightByMask(a, c);
           delay(10);     
          }
        }  
    }
    



    . . (Arduino, RTC) . , . , «- ». — . :

    .



    , «»:



    , , :



    , , , .

    , , . , ? . : ( , , ..). , , , . . , .


    ?

    • , , .
    • .
    • La capacidad de cambiar fácilmente mediante programación la secuencia de LED parpadeantes, lo que proporciona una variedad infinita de combinaciones.

    No reclamamos la exactitud absoluta de nuestros circuitos y soluciones de software. Como ya se mencionó, la experiencia negativa también es experiencia. Quizás este artículo ayude a alguien a evitar nuestros errores.

    Gracias por su atencion!

Source: https://habr.com/ru/post/es394107/


All Articles