Bit cogner étape par étape : Arduino contrôle de WS2811, WS2812 et LED RGB WS2812B (5 / 5 étapes)

Étape 5: Bitbanging une vague d’impulsion sur un microcontrôleur ATMega328p

L’un des avantages d’utiliser un microcontrôleur par opposition à, disons un ordinateur du CPU, c’est que nous avons un contrôle très serré sur le moment des instructions nous programmer dans elle.  En fait, pour montrer comment précise que le contrôle peut être, nous allons utiliser instructions d’assemblage au lieu des fonctions classiques de haut niveau tels que digitalWrite.  L’utilisation d’assemblage nous permet de savoir exactement combien cycles d’horloge sont absorbés lors de l’exécution de chaque instruction.

Étant donné que le Conseil de développement Arduino Uno R3 conserve un signal d’horloge externe 16MHz sur le ATMega328p à bord, le microcontrôleur exécute une instruction de cycle d’horloge 1 exactement 62.5ns (1/16 MHz = 62.5ns).  Étant donné que nous pouvons savoir combien chaque instruction prend les cycles d’horloge, nous pouvons contrôler précisément les instructions combien nous devons génèrent notre signal.

Comme nous l’avons vu précédemment, afin de transmettre un 1 à la puce WS281X nous devons émettre un signal qui reste à une valeur maximale (haute) pour 0.8μs et puis reste à une valeur minimale de (faible) pour 0.45μs.  Ainsi, nous voulons écrire une liste d’instructions qui :

-Mettre broche numérique à haute
-Attendre 0.8μs
-Définit la broche numérique à faible
-Attend 0.45μs

En langage assembleur, ceci peut être réalisé par le code suivant :

(volatile) ASM
Instruction horloge Description Phase Bit transmis
« sbi %0, %1\n\t » / / 2 broches haute (T = 2)
"rjmp. + 0\n\t" / / 2 nop nop (T = 4)
"rjmp. + 0\n\t" / / 2 nop nop (T = 6)
"rjmp. + 0\n\t" / / 2 nop nop (T = 8)
"rjmp. + 0\n\t" / / 2 nop nop (T = 10)
"rjmp. + 0\n\t" / / 2 nop nop (T = 12)
"nop\n\t"               // 1      nop                (T = 13)
« cbi %0, %1\n\t » / / 2 broches faible (T = 15)
"rjmp. + 0\n\t" / / 2 nop nop (T = 17)
"rjmp. + 0\n\t" / / 2 nop nop (T = 19)
"nop\n\t"               // 1      nop                (T = 20)      1
::
Opérandes d’entrée
« I » (_SFR_IO_ADDR(PORT)), //%0
"I" (PORT_PIN) //%1
);

Instruction
La première colonne contient les instructions d’assemblage, suivie d’un saut de ligne et onglet caractères, qui font de l’assembleur final listing généré par le compilateur plus lisible.

Horloge
La deuxième colonne indique le nombre de cycles d’horloge que prend de chaque instruction.  Pour cet ensemble d’instructions simples il y a qu’une seule valeur possible, nous verrons plus tard comment quelques instructions (par exemple, conditionnel) peuvent avoir 1, 2 ou 3 valeurs possibles.  N’oubliez pas que chaque cycle d’horloge sur les 16 MHz Arduino Uno prend 62.5ns.

Description
La troisième colonne montre une très brève description de ce que fait chaque opération.

Phase de
En utilisant le terme un peu lâche, nous l’utilisons pour indiquer la somme cumulée de cycles d’horloge prise par les instructions qui ont été exécutées jusqu'à présent.

Afin d’envoyer une seule valeur 255 — 11111111 en binaire — à la WS281X nous devons répéter ce jeu d’instructions 8 fois.  En outre, si nous insérons un 50μs (ou plus) pause entre les transmissions de la séquence de 8 bits, la WS281X s’enclenche les données transmises à son registre de sortie.  Une fois que les données sont verrouillées, la première LED (vert) de la WS281X devrait s’allumer à un niveau de luminosité maximale.  Le sketch Arduino à l’intérieur de bitbang_255.zip illustre cette opération.

Pour envoyer un 0, il faut modifier le code qui produit un 1 en réduisant le temps pendant lequel le signal a une valeur élevée (maximum) et en augmentant le temps pendant lequel le signal est faible (minimale).  En outre, on notera que les valeurs pour chaque LED doivent toujours être spécifiés à l’aide de 8 bits.  Par exemple, si nous voulions envoyer une valeur de 105 — 1101001 en binaire, il faudrait envoyer les 8 bits 01101001 y compris le 0.  Le code qui génère un 0 ressemble à :

(volatile) ASM
Instruction horloge Description Phase Bit transmis
« sbi %0, %1\n\t » / / 2 broches haute (T = 2)
"rjmp. + 0\n\t" / / 2 nop nop (T = 4)
"rjmp. + 0\n\t" / / 2 nop nop (T = 6)
« cbi %0, %1\n\t » / / 2 broches faible (T = 8)
"rjmp. + 0\n\t" / / 2 nop nop (T = 10)
"rjmp. + 0\n\t" / / 2 nop nop (T = 12)
"rjmp. + 0\n\t" / / 2 nop nop (T = 14)
"rjmp. + 0\n\t" / / 2 nop nop (T = 16)
"rjmp. + 0\n\t" / / 2 nop nop (T = 18)
"rjmp. + 0\n\t" / / 2 nop nop (T = 20) 0
::
Opérandes d’entrée
« I » (_SFR_IO_ADDR(PORT)), //%0
"I" (PORT_PIN) //%1
);

Nous pouvons utiliser le sketch Arduino à l’intérieur de la bitbang_105.zip pour générer le signal dont l’image peut être vu sur les captures d’écran d’oscilloscope attachés à cette étape.

Maintenant, pour la WS281X afficher la couleur blanchâtre, nous voulons, nous devons envoyer non pas une mais trois 255 valeurs — auquel cas notre signal se compose des 24 — avant d’attendre le 50μs pour les données de verrouillage.  Nous pourrions faire cela par copier-coller les instructions d’onze assemblage au-dessus de 23 fois (vous pouvez lui donner un essai modifiant l’esquisse de bitbang_255.ino).  Mais le code ne serait pas pratique pour l’envoi des valeurs à plus d’un WS281X puces.  Une meilleure solution serait d’écrire une boucle qui pourrait parcourir les valeurs 8 bits jusqu'à ce que tous les trois d'entre eux ont été envoyés.

L’esquisse à l’intérieur de le bitbang_whitish.zip comprend une description claire des mesures prises pour atteindre le résultat souhaité.  La section principale, écrite en Assemblée à la suite de la logique décrite plus haut, se présente comme suit :

(volatile) ASM
Phase de l’instruction horloge Description
"nextbit:\n\t"              // -    label                                     (T =  0)
« sbi %0, %1\n\t » / / 2 signal haute (T = 2)
« sbrc %4, 7\n\t » / / 1-2 si la valeur de MSB (T =?)
"mov %6, %3\n\t" / / 0-1 tmp définirai signal haute (T = 4)
« dec %5\n\t » / / 1 diminution bitcount (T = 5)
« nop\n\t » / / 1 nop (cycle de 1 horloge inactif) (T = 6)
"st % a2, %6\n\t" / / 2 PORT pour tmp (T = 8)
"mov %6, %7\n\t" / / 1 reset tmp à bas (par défaut) (T = 9)
« breq nextbyte\n\t » / / 1-2 si bitcount == 0 -> nextbyte (T =?)
« rol %4\n\t » / / 1 shift MSB vers la gauche (T = 11)
"rjmp. + 0\n\t" / / 2 nop nop (T = 13)
« cbi %0, %1\n\t » / / 2 signal faible (T = 15)
"rjmp. + 0\n\t" / / 2 nop nop (T = 17)
"nop\n\t"                  // 1    nop                                        (T = 18)
« rjmp nextbit\n\t » / / 2 bitcount! = 0 -> nextbit (T = 20)
"nextbyte:\n\t"          // -    label                                       -
« ldi 5 %, 8\n\t » / / 1 reset bitcount (T = 11)
"ld   %4, %a8+\n\t" // 2    val = *p++                             (T = 13)
« cbi %0, %1\n\t » / / 2 signal faible (T = 15)
"rjmp. + 0\n\t" / / 2 nop nop (T = 17)
"nop\n\t"                 // 1    nop                                        (T = 18)
« dec %9\n\t » / / 1 diminution bytecount (T = 19)
« brne nextbit\n\t » / / 2 si bytecount! = 0 -> nextbit (T = 20)
::
);

La meilleure façon de comprendre le fonctionnement de cette section est d’examiner différents scénarios et suivre le code assembleur en ligne.  Par exemple, nous savons que pour envoyer une valeur de 255, nous devons envoyer 8 bits avec un calendrier qui correspond à un 1.  En d’autres termes, la broche numérique connecté à le WS281X devrait rester élevée pour 13 cycles (0.8125μs) et faible pour 7 (0.4375μs).  Le code ci-dessus parvenir ?  Nous allons voir ce qui arrive quand on commence tout d’abord à transmettre :

(volatile) ASM
"nextbit:\n\t" / / il s’agit d’une étiquette uniquement pour diriger les sauts ci-dessous.
« sbi %0, %1\n\t "/ / le signal est défini sur Elevé, instruction utilise 2 cycles.
« sbrc %4, 7\n\t » / / True. Envoi de 255 implique MSB actuel est « set » (= 1).
"mov %6, %3\n\t » / / ceci est exécuté. « tmp » est réglé sur haut.
« dec %5\n\t » / / Bit est transmis, décrémenter compteur de bit.
« nop\n\t » / / besoin de tourner au ralenti pour obtenir les cycles de 13 horloge.
"st % a2, %6\n\t" / / écrire la valeur de « tmp » dans le PORT (broche encore élevé).
"mov %6, %7\n\t » / / Set « tmp » au plus bas pour le prochain passage dans la boucle.
« breq nextbyte\n\t » / / False. Compteur de bit n’est pas 0, utiliser 1 cycle et continuer.
« rol %4\n\t » / / décalage de la valeur d’octet MSB vers la gauche.
"rjmp. + 0\n\t" / / inactifs pendant 2 cycles d’horloge. Phase atteinte T = 13.
« cbi %0, %1\n\t » / / la valeur signal faible.
"rjmp. + 0\n\t" / / inactifs pendant 2 cycles d’horloge.
« nop\n\t » / / ralenti pendant le cycle de 1 horloge.
« rjmp nextbit\n\t » / / compteur bits n’a pas été 0 alors sauter à bit suivant. T = 20.
);

Si les instructions qui effectivement exécutées de générer un signal sur la broche de données qui est 13 cycles haute (0.8125μs) et 7 LOW (0.4375μs), envoyant ainsi un peu avec la valeur 1 à la WS281X.  Si nous continuons à étudier ce que le code fait quand le reste des bits sont envoyés et ce qu’il fait, lorsqu’on utilise des valeurs autres que 255, nous aurons une meilleure compréhension de cette implémentation particulière de bitbanging.

Personnellement, j’espère que vous trouverez ce tutoriel utile pour débuter avec bitbanging protocoles de votre propre communication chaque fois qu’il est nécessaire !

Articles Liés

Arduino contrôlée Président de LED et de système de jeu

Arduino contrôlée Président de LED et de système de jeu

L'objectif de ce projet a été d'apprendre à utiliser les outils et mettre en œuvre de logiciels avec qui. Ceci a été divisé en trois parties principales : le Strip LED contrôlé par un Arduino, le système Rasberry PI connecté à un moniteur et le bâtim
Commander une LED RGB avec le HC-06 Bluetooth Module utilisant Android OS(Arduino)

Commander une LED RGB avec le HC-06 Bluetooth Module utilisant Android OS(Arduino)

Ce tutoriel vous expliquera le processus de connexion d'un Bluetooth Module de HC-06 à un Arduino et contrôler la couleur d'une LED RGB à l'aide de l'application ArduDroid sur le système d'exploitation Android. Cette configuration très probablement c
Autocollant de fenêtre numérique (Arduino contrôlée)

Autocollant de fenêtre numérique (Arduino contrôlée)

un autocollant de taille matrice de LED qui affiche des images en séquence à partir d'une carte SD, pour produire une animation signe ou « vitrophanie ». Arduino contrôlée ! Inclut également le code de Windows, Mac et Linux pour la conversion des fic
Arduino contrôlées Animatronic squelette Rock Band - en cours

Arduino contrôlées Animatronic squelette Rock Band - en cours

Pour l'Halloween cette année, j'ai décidé de construire un animatronic squelette Rock. C'est un travail en cours à ce stade, mais je suis assez content de comment il est à venir le long. Presque tout est fait de matériaux que j'avais sur la main (je
Arduino contrôlée animatronique tête en bois (lampe de lecture)

Arduino contrôlée animatronique tête en bois (lampe de lecture)

cette tête est une lampe de lecture qui peut être ajustée pour la direction de l'éclairage et estompée au besoin.Ce Instructable combine Arduino programmation, certains électronique simple, sculpture avec des outils manuels et électriques, contrôle m
Lampe à LED RGB Arduino + 4 bit écran LCD

Lampe à LED RGB Arduino + 4 bit écran LCD

c'est mon premier instructable!!! Yay...Avant de continuer. Je ne pas entrer dans les détails de la façon de couper le bois, ou tout reconstituer. J'ai chorégraphié le processus de génération entière, quelle que soit venu à l'esprit est ce que j'ai r
Arduino - contrôle de points/turnout

Arduino - contrôle de points/turnout

Mise à jour 28 avril 2016Les points / contrôleur de taux de participation est construit et installé dans ma mise en page du chemin de fer.Le système fini contrôle 16 points et 15 accessoires tels que les lumières, sons, platine, etc.Le circuit est in
Arduino contrôlée hélicoptère

Arduino contrôlée hélicoptère

Cette instructable a été créée dans l'accomplissement de l'exigence de projet de la Makecourse à l'Université de Floride du Sud (www.makecourse.com). L'objectif de ce cours était pour nous enseigner la créativité, l'ingéniosité et l'application prati
Laser Galvo - Arduino contrôlée

Laser Galvo - Arduino contrôlée

Arduino contrôlée laser galvo. La servocommande de miroirs diriger le laser UV laissant une traînée phosphorescente sur la feuille de vinyle glow-in-the-dark.Posté sur notes.robives.comÉtape 1 :À partir d'une feuille de vinyle lumineux d'eBay et poin
Arduino contrôlée ruche spécialiste / désodorisant

Arduino contrôlée ruche spécialiste / désodorisant

Dans le chaos relatif de mes arrangements domestiques, j'ai une petite oasis d'un ordre parfait. Une chose que je peux appeler « organisé » et « pleinement fonctionnelle ». Une chose que je peux toucher et savons qu'il est fiable et prêt pour l'actio
Arduino contrôlée de fenêtre pour chat

Arduino contrôlée de fenêtre pour chat

je soumets cette instructable le défi de l'Arduino. N'oubliez pas de voter !Mon voisin a eu un petit problème avec son chat. Il veulent de sortir et de revenir trop souvent à l'intérieur. Habituellement, il ouvre juste la fenêtre de sa cuisine et nou
Arduino contrôlée Rotary Stewart Platform

Arduino contrôlée Rotary Stewart Platform

Cette instructable est sur la génération d'une rotative Plate-forme de Stewart. Il permet de positionner sa plateforme de mouvement à six degrés de liberté. Cette plateforme spécifique est conçue pour pouvoir positionner un reflex numérique ou tout a
Arduino contrôlée CNC / 3D imprimante hybride

Arduino contrôlée CNC / 3D imprimante hybride

Dame Nature fait... Nous construisons des.BuildersBot fusibles impression 3D & fraisage CNC dans rêve d'un générateur "3dprintingindustry.com"Le BuilderBot est une machine de conception ouverte, qui utilise OpenLogiciels et matériels ouvert.
Arduino contrôlée coaster smart

Arduino contrôlée coaster smart

Le Coaster Smart est un coaster intelligent pour vos boissons. Il reconnaît que les différents types de boissons placé dessus, avec un cocktail le Coaster Smart s'illumine dans quelques couleurs atmosphériques et variation lente. Si vous placez une t