Mehrere „Programme“ für unsere Discobrille mit den WS2812b RGB LED Ring - AZ-Delivery

Bonjour et bienvenue à la deuxième partie de la série de blogs "Discobrille".

Dans cette partie, comme beaucoup d’entre vous s’y attendaient, élargir les fonctionnalités de nos lunettes, mais nous répondrons également aux commentaires de la première partie de cette partie. Je vais donc vous fournir un plan de câblage mis à jour. Je vais également discuter explicitement des détails du câblage de la WS1812b.
En outre, nous faisons don d’une petite mise à niveau du firmware à notre matériel, qui vous permet de sélectionner jusqu’à 4 différentes animations d’éclairage passionnantes à la simple pression d’un bouton sur le bouton.

S’il vous plaît filer votre matériel selon ce plan de câblage mis à jour:

Disco brilles - Fritzing Plan

Puisque nous avons également reçu des questions spéciales sur le câblage détaillé des anneaux, ici en particulier cette partie est montrée agrandie :

Disco brilles - Fritzing - Détail

 

On peut voir sur l’image que la ligne de données entre les anneaux est «sol». Cela signifie que le microcontrôleur a relié la sortie de données D6 au premier anneau après DI (données dans), puis de cet anneau à nouveau de la broche DO (Data Out) au deuxième anneau après DI (Data in). Ce type de connexion est nécessaire en raison de l’exploitation du bus de données en série. 


Maintenant, nous pouvons oser mettre à niveau le firmware et télécharger le code suivant à notre Arduino:

 

 

#include <Adafruit_NeoPixel.H (en)>

#define BUTTON_CHANGEANIMATION  12    Épingle IO numérique connectée au bouton.  Ce sera
conduit avec une résistance pull-up de sorte que le commutateur devrait
Tirez la broche au sol momentanément.  Sur un haut - bas
transition de la logique de bouton appuyez sur s’exécutera.
#define PIXEL_PIN    6    Épingle IO numérique connectée aux NeoPixels.
#define PIXEL_COUNT 24   Tous les pixels sur bande
#define MaxAninmationsAvail 4

Adafruit_NeoPixel Bande = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_RGB + NEO_KHZ800);

Const Int hueRedLow = 0;
Const Int hueRedHigh = 255;
Const Int hueBlue = 170;
Const Int angleMin = 0;
Const Int angleSector = 60;
Const Int angleMax = 360;
Const Int brightMin = 0;
Const Int brightMax (en) = 255;

Octet Teinte, "Je ne suis pas;
La saturation est fixée à 255 (plein) pour enlever le blead-through de différents
"Je ne suis pas
Il pourrait être lié à un autre potentiomètre si une démonstration de teinte
Est désiré.
Octet Saturation = 255;

Contrôle interrut
Bool A60telSecInterruptOccured = Vrai;
Octet A60telSecondes24 = 0;
Octet A4telSecondes24 = 0;

Variables de minuterie
Int TimerSeconds TimerSeconds = 0;  Counter
Int TimerAlarmSet (en anglais) = 15; Minuterie de 15 secondes
Bool TimerStartFlagFlagFlag = Faux;
Bool Timerstop = Vrai;

Opérations manuelles
Bool ButtonAPress (en)  = Faux;

Intenal LED LightEffects (LED 13)
Octet LedMode (en) = 2;

AnimationControl
Int DevraitAnimation  = 0;
Int IsAnimation  = 0;
Int OLDLightBorder (en) = 0;
Bool GetONOFFStatus GetONOFFStatus = Faux;

Bool OLDONOFFStatus = Faux;
Bool PlayIntro = Faux; Matchs d’intro
Bool PlayOutro PlayOutro = Faux; Matchs Outro
Bool ChangementAnimation = Faux;
Bool Runonce (Runonce) = Vrai;  Pour Switch-Off Amation - Anmation 0

variables universelles
Octet Un, C, D, E, Q;
Unsigned Int R, G, B;

Interrompre les routines

Isr (Isr)(TIMER1_COMPA_vect)
{   Bool LEDChange (en), PressedZ (pressedZ);   Requête de commutateur   PressedZ (pressedZ) = digitalRead (en)(BUTTON_CHANGEANIMATION);   Si ((PressedZ (pressedZ) == Faible) Et (ButtonAPress (en) == Faux))   {     ButtonAPress (en) = Vrai;   }   TCNT1 (en) = 0;      Inscription initiale avec 0
}

Interrompre la fin
commencer le programme

Vide Configuration()
{   Bande.Commencer();   Bande.Montrer();   Initialiser tous les pixels à 'off'   pinMode(BUTTON_CHANGEANIMATION, INPUT_PULLUP);   randomSeed(analogRead (en)(0));   noInterrupts(); Éteignez temporairement toutes les interruptions   TCCR1A (EN) = 0x00;   TCCR1B (EN) =  0x02;   TCNT1 (en) = 0;      // S'inscrire avec 0 initialisieren   OCR1A =  33353;      // Output Compare Register vorbelegen   TIMSK1 |= (1 << OCIE1A);  // Timer Compare Interrupt aktivieren   interrompt();   // alle Interrupts scharf schalten   En série.commencer(9600);   En série.affleurer();
}


// Hilfsfunktionen


néant HSBToRGB(   non signé int inHue, non signé int inSaturation, non signé int inBrightness,   non signé int *ou, non signé int *oG, non signé int *oB )
{   si (inSaturation == 0)   {     // achromatique (gris)     *ou = *oG = *oB = inBrightness;   }   autre   {     non signé int scaledHue = (inHue * 6);     non signé int secteur = scaledHue >> 8; // secteur 0 à 5 autour de la roue chromatique     non signé int offsetInSector = scaledHue - (secteur << 8);  // position dans le secteur     non signé int p = (inBrightness * ( 255 - inSaturation )) >> 8;     non signé int q = (inBrightness * ( 255 - ((inSaturation * offsetInSector) >> 8) )) >> 8;     non signé int t = (inBrightness * ( 255 - ((inSaturation * ( 255 - offsetInSector )) >> 8) )) >> 8;     commutateur ( secteur ) {       Cas 0:         *ou = inBrightness;         *oG = t;         *oB = p;         Pause;       Cas 1:         *ou = q;         *oG = inBrightness;         *oB = p;         Pause;       Cas 2:         *ou = p;         *oG = inBrightness;         *oB = t;         Pause;       Cas 3:         *ou = p;         *oG = q;         *oB = inBrightness;         Pause;       Cas 4:         *ou = t;         *oG = p;         *oB = inBrightness;         Pause;       défaut:    // cas 5:         *ou = inBrightness;         *oG = p;         *oB = q;         Pause;     }   }
}

néant CheckConfigButtons ()    // InterruptRoutine
{   bool PressedZ;   si (ButtonAPress == vrai)   {     si (ShouldAnimation < MaxAninmationsAvail )     {       ShouldAnimation++;       En série.println ("la phase 1");       En série.println (ShouldAnimation);       // ShouldAnimation = 1;     } autre     {       ShouldAnimation = 0;     }     retard(700);     ButtonAPress = faux;   }
}

néant AnimationControl ()
{   int GetSelAnimation = 0;   si (GetONOFFStatus != OLDONOFFStatus)   {     OLDONOFFStatus = GetONOFFStatus;     si (GetONOFFStatus)     {       ShouldAnimation = 1;     } autre     {       ShouldAnimation = 0;     }   }
}

// Boucle principale  ---------------------------------------------- -------------------------

néant boucle()
{   AnimationControl();   RunAnimations();   CheckConfigButtons();
}
// Boucle principale  ---------------------------------------------- ------------------------- Ende
// Intros

néant Intro_CountUp (octet r, octet g, octet b, int temporisation, bool dir)
{   si (dir)   {     pour ( int je = 0; je < bande.numPixels(); je++)     {       bande.setPixelColor(je, r, g, b);    // Calcul des valeurs RVB pour le pixel       bande.spectacle();   // Montrer les résultats :)       retard(temporisation);     }   } autre   {     pour ( int je = 0; je < bande.numPixels() + 1; je++)     {       octet pos = bande.numPixels() - je;       bande.setPixelColor(pos, r, g, b);    // Calcul des valeurs RVB pour le pixel       bande.spectacle();   // Montrer les résultats :)       retard(temporisation);     }   }
}


néant Intro_RaiseRainbow(bool montée)
{   luminosité = 255;   int Rainbowcolor = 0;   si (montée)   {     pour (int je = 0; je < bande.numPixels(); je++)     {       teinte = carte(je + Rainbowcolor, angleMin, 60, hueRedLow, hueRedHigh); // Définir la couleur       HSBToRGB(teinte, saturation, luminosité, &r, &g, &b); // Définir la couleur       bande.setPixelColor(je, r, g, b);     // Calcul des valeurs RVB pour le pixel       bande.spectacle();       retard(40);     }   } autre   {     pour (int je = 0; je < bande.numPixels(); je++)     {       bande.setPixelColor(je, 0, 0, 0);       bande.spectacle();       retard(40);     }   }
}


// Outtros



// Animations

néant Ani_AllOff ()
{   pour ( int je = 0; je < bande.numPixels(); je++)   {     bande.setPixelColor(je, 0, 0, 0);     // tout est éteint   }   bande.spectacle();
}


néant Ani_AllOn (octet r, octet g, octet b)
{   pour ( int je = 0; je < bande.numPixels(); je++)   {     bande.setPixelColor(je, r, g, b);     // tout allumé   }   bande.spectacle();
}

néant Ani_Starshower ()
{   int tableau[10] ;   pour ( int je = 0; je < bande.numPixels(); je++)   {     bande.setPixelColor(je, 0, 0, 15);     // tout en bleu   }   pour (int je = 0; je < 10; je++)   {     int choisi = Aléatoire(bande.numPixels());     bande.setPixelColor(choisi, 255, 255, 255); // Blanc   }   bande.spectacle();   retard(100);   pour ( int je = 0; je < bande.numPixels(); je++)   {     bande.setPixelColor(je, 0, 0, 15);     // tout en bleu   }   bande.spectacle();   retard(500);
}

néant Ani_Rainbow(octet temporisation)
{   luminosité = 100;   int Rainbowcolor = 0;   faire   {     pour (int je = 0; je < bande.numPixels(); je++)     {       teinte = carte(je + Rainbowcolor, angleMin, 60, hueRedLow, hueRedHigh);       HSBToRGB(teinte, saturation, luminosité, &r, &g, &b);       bande.setPixelColor(je, r, g, b);     }     bande.spectacle();   // Montrer les résultats :)     retard(temporisation);     Rainbowcolor++ ;   } tandis que (Rainbowcolor < 61);
}

néant Ani_Two_Color ()
{   // Segments d'octets = PIXEL_COUNT / 5;   octet Séparateur = Aléatoire (1, 10);   bool Couleur;   int X = 1;   b = 0;   pour (int s = 0; s > -1; s = s + X)   {     Couleur = faux;     pour ( int je = 0; je < bande.numPixels(); je++)     {       une = je / Séparateur;       si (!(une == b))       {         b = une;         Couleur = !Couleur;       }       si (Couleur) {         bande.setPixelColor(je, 0, s, 0);  // grün       }       si (!(Couleur)) {         bande.setPixelColor(je, s, 0, 0);  //pourrir       }     }     bande.spectacle();     si (s == 255)     {       X = -1;       retard(2000);     }     retard(10);   }   bande.spectacle();
}

néant Ani_Halloween()
{   une = -10;   pour (int je = 0; je < bande.numPixels(); je++)   {     bande.setPixelColor(je, Aléatoire(1, 254), Aléatoire(1, 204), Aléatoire(1, 254));     e = e + une;     F = F + une;     si (F <= 0)     {       une = +10;     }     si (F >= 60)     {       une = -10;     }   }   bande.spectacle();   // Montrer les résultats :)   retard(300);
}

néant FadeColor ()
{   octet luminosité = 0;   octet saturation = 0;   int Colori = 49 ;   faire   {     pour (int je = 0; je < bande.numPixels(); je++)     {       // wdt_reset ();       HSBToRGB(Colori, saturation, luminosité, &r, &g, &b); // Définir la couleur       bande.setPixelColor(je, r, g, b);     // Calcul des valeurs RVB pour le pixel     }     luminosité ++;     bande.spectacle();   // Montrer les résultats :)     retard(40);   } tandis que (luminosité < 50);
}

néant RunAnimations()
{   si (!(ShouldAnimation == IsAnimation))   {     PlayOutro = vrai;     ChangeAnimation = vrai;   }   commutateur (IsAnimation)   {     Cas 0:                                    // tous les LedsOFF       si (PlayIntro)       {         PlayIntro = faux;         Exécuter une fois = vrai;       }       si   ((!(PlayIntro)) &&  (!(PlayOutro)))       {         si (Exécuter une fois) {           Ani_AllOff ();         }         Exécuter une fois = faux;       }       si  (PlayOutro)       {         PlayOutro  = faux;         PlayIntro = vrai;         Exécuter une fois = vrai;         IsAnimation = ShouldAnimation;       }       Pause;     Cas 1:       si (PlayIntro)       {         Intro_CountUp (0, 0, 15, 100, vrai);         PlayIntro = faux;       }       si  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Starshower();       }       si  (PlayOutro)       {         Intro_CountUp (0, 0, 0, 100, faux);         PlayOutro  = faux;         PlayIntro = vrai;         IsAnimation =  ShouldAnimation;       }       Pause;     Cas 2:       si (PlayIntro)       {         Intro_RaiseRainbow(vrai);         PlayIntro = faux;       }       si  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Rainbow(20);       }       si  (PlayOutro)       {         Intro_RaiseRainbow(faux);         PlayOutro  = faux;         PlayIntro = vrai;         IsAnimation =  ShouldAnimation;       }       Pause;     Cas 3:       si (PlayIntro)       {         Ani_AllOff ();         PlayIntro = faux;       }       si  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Two_Color (); // Ani_Two_Color (teinte octet, queue octet, luminosité octet, délai d'octet)       }       si  (PlayOutro)       {         PlayOutro  = faux;         PlayIntro = vrai;         IsAnimation =  ShouldAnimation;       }       Pause;     Cas 4:       si (PlayIntro)       {         Ani_AllOff ();         PlayIntro = faux;       }       si  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Halloween (); //       }       si  (PlayOutro)       {         PlayOutro  = faux;         PlayIntro = vrai;         IsAnimation =  ShouldAnimation;       }       Pause;   }
}

 

Funktionsweise: Durch kurzen Druck auf den Taster können jetzt folgende Animationen nacheinander aufgerufen werden. Ein

  • Starshower
  • arc en ciel
  • Mouvement de deux couleurs
  • Halloween


Bitte beachtet, dass die Animationen nicht sofort auf die nächste Animation umschalten, sondern immer erst die aktuelle Sequenz beenden, bevor die nächste Animation gestartet werden.


Auch hier seid ihr natürlich herzlich eingeladen, weitere Animationssequenzen zu programmieren, falls euch die 4 nicht ausreichen sollten. Die prinzipielle Vorgehensweise dazu ist aus dem Code ersichtlich.
Im nächsten und letzten Teil der Reihe werden wir unsere Brille auf „Umweltreize“ reagieren lassen.


Ich wünsche viel Spaß beim Nachbauen und bis zum nächsten mal.

Für arduinoProjekte für anfänger

2 commentaires

Andreas Wolter

Andreas Wolter

@Sebastian: zu Beginn des Codes wird mit der Zeile
#define PIXEL_COUNT 24
die Anzahl aller Pixel festgelegt (hier zwei Ringe je 12 Pixel, also 24). Diese Konstante wird dann später verwendet, wenn das Neopixelsobjekt instanziiert wird.
Wenn Sie fünf Ringe verwenden, müssten Sie dort statt 24 dann 5x 12 = 60 eintragen. Dann sollte überall dort, wo mit der for-Schleife bis strip.numPixels() gezählt wird, jeder der Neopixel angesprochen werden.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Sebastian

Sebastian

Hi,
ich möchte 5 von der 38mm Ringen nutzen. Wo genau muss ich denn die Anzahl der Ringe einstellen?

Laisser un commentaire

Tous les commentaires sont modérés avant d'être publiés

Articles de blog recommandés

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery