Montre LED Shadowplay sur la plate-forme Arduino Uno

Au lieu de rejoindre




Notre équipe de trois personnes a donc eu la tâche de monter un petit projet matériel en très peu de temps, de préférence sur la plateforme Arduino. Il convient de mentionner que jusqu'à ce moment, nous étions familiers avec les circuits, pour la plupart, en théorie. Et cela signifie - ni expérience avec un fer à souder (pratiquement), ni, surtout, expérience avec Arduino.

Soudain, nous sommes tombés sur un articledédié au projet Shadowplay Clock. Il s'agit d'une horloge murale conçue par une équipe de designers viennois, le temps par lequel vous pouvez voir en touchant un doigt vers leur centre. Les LED s'allument de telle sorte que l'ombre du doigt au centre indique l'heure. Il a été décidé de créer le même (ou très similaire), mais à la maison. L'article ci-dessus, comme vous pouvez le voir, ne contient pas de description détaillée du projet. De tout cela, il s'ensuit que nous-mêmes avons dû comprendre comment cet appareil fonctionne et lui donner vie. En fait, ce que nous avons fait.

Matériaux


Pour créer une montre dont vous avez besoin:

  • Ă©bauches de panneaux de fibres
  • Bande de diodes 60 LED
  • Arduino uno
  • Module d'horloge en temps rĂ©el RTC DS1307
  • bouton
  • planche Ă  pain
  • registre Ă  dĂ©calage 74HC595 (x2)
  • Verrou de registre 8 bits 74HC573N (x8)
  • dĂ©codeur 4-16 K155ID3
  • onduleur Ă  drain ouvert IN74HC05AN (x10)
  • unitĂ© de puissance

Commençons


Ainsi, l'algorithme de l'appareil:

  1. Lorsque l'alimentation est appliquée, les LED s'allument selon une combinaison prédéterminée. Dans le Shadowplay original, toutes les LEDs se sont allumées, mais il nous a semblé qu'il serait plus intéressant de lancer une combinaison comme économiseur d'écran.
  2. Lorsque le bouton est enfoncé (oui, nous nous sommes également éloignés de l'original et inséré un petit bouton au centre), l'heure est lue depuis le module RTC.
  3. Le temps de lecture est converti en code binaire (masque) et entré dans des registres.
  4. Selon le masque, la diode requise est allumée.

Matériel informatique


Lorsque nous avons finalement décidé de l'idée du projet, la première chose que nous avons essayée a été de dessiner mentalement des versions approximatives des schémas pour sa mise en œuvre. La principale question était de savoir comment traiter 60 LED. En fait, la réponse à cette question a déterminé la méthode de construction de presque tout le schéma.

La première option qui m'est venue à l'esprit était l'utilisation de décodeurs. Le circuit compilé était une cascade de quatre décodeurs 4-16 et d'un décodeur 2-4, tous deux avec des entrées d'activation de déchiffrement. Une telle cascade a permis d'adresser à 64 sorties, ce qui était plus que suffisant pour connecter 60 LED.

Cependant, la question s'est posée de savoir comment faire fonctionner plus d'une LED (adresse) en même temps (après tout, nous devions fournir à l'horloge au moins les minutes et les aiguilles). Ici, le principal inconvénient de ce schéma s'est manifesté - le décodeur ne peut, par définition, pas adresser plus d'une sortie à la fois.

Cette faille nous a obligés à abandonner l'idée avec une cascade de décodeurs. De plus, nous avons maintenant une autre exigence pour le futur circuit: la prise en charge du fonctionnement simultané d'un nombre différent de LED.

Pour satisfaire cette exigence, nous avons pensé qu'il était possible de permettre à chaque LED de stocker son état. Les registres sont bien adaptés à cet effet, où chaque décharge individuelle correspond à l'état de l'une des LED. Nous avons décidé d'utiliser des registres 8 bits, car ils sont plus courants et plus pratiques. Par conséquent, dans notre circuit, nous aurons besoin de 8 registres de ce type pour prendre en charge 60 LED.

Ensuite, nous avons réfléchi à la façon de contrôler l'état des LED avec Arduino via des registres. Chaque registre pour un fonctionnement normal devrait recevoir les 8 bits dans leur intégralité. Arduino Uno, bien sûr, fournit suffisamment de sorties pour transmettre plusieurs bits à la fois, mais cette approche ne sera pas rationnelle. De plus, le schéma ne contient que 8 registres, ce qui signifie que vous devez en quelque sorte les adresser. A cet effet, nous avons ajouté un décodeur et deux registres à décalage 8 bits connectés en cascade au circuit. Un registre à décalage stocke un masque d'état à 8 bits, qui sera chargé dans l'un des 8 registres réguliers, dont le nombre est stocké dans le deuxième registre à décalage. Par conséquent, un décodeur est connecté au deuxième registre à décalage. À ces fins, un décodeur 3 x 8 est tout à fait suffisant.

Pour supprimer l'inversion du nombre de sorties requis, nous avons utilisé deux circuits onduleurs KR1533LN1. Bien sûr, cela compliquait quelque peu le schéma.

Une autre tâche était la tension de travail des LED égale à 12 volts contre 5 volts de circuits logiques. La solution proposée consistait à utiliser un onduleur à drain ouvert. Un tel microcircuit joue le rôle d'une touche qui ferme (avec 1 logique) ou ouvre (avec 0 logique) l'un des contacts de la LED avec le sol, allumant ou éteignant ainsi la LED. Le circuit suppose un fonctionnement à partir de 12 volts, conformément à la tension de fonctionnement des LED, donc afin d'obtenir 5 volts pour les circuits logiques, le stabilisateur KR142EN5A avec deux condensateurs a été ajouté au circuit.

Certaines entrées de certains microcircuits impliquent une valeur constante à l'entrée, elles étaient donc connectées à la terre ou à une source d'alimentation. Dans ce cas, ce sont les entrées suivantes:

  • L'entrĂ©e de rĂ©initialisation MR inverse dans les deux registres Ă  dĂ©calage est connectĂ©e via le registre de charge Ă  la sortie du stabilisateur Ă  5 volts.
  • L'entrĂ©e de validation de sortie OE inverse dans les deux registres Ă  dĂ©calage est directement connectĂ©e Ă  la masse.
  • DĂ©codeur inverse permettant l'entrĂ©e E0 connectĂ©e Ă  la masse




Le circuit est contrôlé par quatre entrées (E1, SH, ST, DS). Le but et les niveaux de signal de chacun d'eux sont discutés plus en détail ci-dessous:

L'entrée E1 est conçue pour activer le décodeur. Dans notre cas, initialement sur le décodeur, il y a deux entrées de commande E1, E0, et les deux sont inverses. Il y aura suffisamment d'une sortie, de sorte que la seconde (E0) puisse être amenée au sol. L'état de décodeur «par défaut» est opérationnel jusqu'à ce qu'un niveau de signal élevé soit appliqué à E1. Pour faire le contraire, nous avons connecté cette entrée à l'onduleur. Sans cela, le décodeur peut donner des signaux de commande incorrects aux registres, par exemple, au moment de la mise à jour des données dans le registre à décalage. Comme déjà mentionné, un décodeur 3 x 8 peut être utilisé dans le circuit, qui peut avoir une entrée de commande non inverse, ce qui permettra de résoudre facilement tous les problèmes décrits ci-dessus sans fils supplémentaires et sans fer à souder.

Lorsqu'un seul niveau de signal est appliqué à E1, le décodeur décode l'adresse de registre située dans le registre à décalage correspondant et envoie un signal à la sortie souhaitée. Après cela, le décodeur s'éteint à nouveau en appliquant un niveau de signal faible à E1. Un tel commutateur du décodeur génère un signal à la sortie souhaitée, dont le front et la décroissance servent d'impulsion d'horloge de registre pour capturer en soi les données stockées sur le bus.

Les trois entrées suivantes sont déjà destinées au contrôle des registres à décalage. Cela vaut la peine de commencer par la chose la plus simple: la saisie de données DS. Cette entrée, comme son nom l'indique, est destinée à la transmission de données. Les registres à décalage du circuit étant connectés en cascade, le DS représente la sortie correspondante de l'un d'entre eux. L'entrée du deuxième registre à décalage est connectée à la sortie du dernier bit du premier registre. Le résultat est un registre à décalage pour 16 bits, dont seulement 12 bits sont utilisés.

L'entrée SH est une entrée d'horloge. Une onde carrée est envoyée à cette entrée, qui est responsable du chargement et du décalage des données dans chacun des registres, respectivement, ce contact du circuit est connecté aux broches SHCP des deux registres.

La dernière broche ST sert de verrou de données sur les sorties du registre. Une impulsion est donnée à cette entrée, cependant, elle n'est fournie que lorsque les données dans le registre à décalage sont finalement chargées et il est nécessaire de les fixer à la sortie des registres. Ce n'est qu'après avoir donné ce signal que les données téléchargées à l'intérieur du registre sur la première rangée de déclencheurs arrivent sur la deuxième rangée de déclencheurs et deviennent disponibles sur le bus. ST est une broche connectée aux broches STcp des deux registres.

Reste à expliquer le câblage des deux broches des registres à décalage MR et OE. La première entrée (MR) est responsable du dumping des données dans le registre. Dans ce circuit, une telle opportunité n'est pas requise, par conséquent, un niveau de signal élevé est fourni à cette sortie via la charge.

La deuxième entrée de registre (OE) est chargée de déconnecter la deuxième rangée de déclencheurs à l'intérieur du registre à décalage du bus, c'est-à-dire l'entrée de validation. Cette fonction n'est également pas requise, par conséquent, la sortie est enroulée à la terre.

Un autre contact non décrit ci-dessus est conçu pour supprimer le niveau du signal du bouton au centre de la montre, le schéma des boutons est typique et représente une charge et une clé, selon la position dont un niveau de signal bas ou élevé est envoyé à l'Arduino. Selon l'état du bouton, la montre fonctionne soit en mode économiseur d'écran, soit en mode affichage de l'heure.
La connexion à l'Arduino n'a pas de caractéristiques spéciales, sauf que la broche SH est idéalement connectée à la broche numérique SCK. Le reste des sorties du circuit peut être connecté à n'importe laquelle des entrées numériques à usage général disponibles. Dans notre cas, la connexion a la forme suivante:

  • 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 possibilitĂ© de modifier facilement par programmation la sĂ©quence des LED clignotantes, ce qui donne une variĂ©tĂ© infinie de combinaisons.

    Nous ne revendiquons pas l'exactitude absolue de nos circuits et solutions logicielles. Comme déjà mentionné, l'expérience négative est également une expérience. Peut-être que cet article aidera quelqu'un à éviter nos erreurs.

    Merci de votre attention!

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


All Articles