Nos lunettes disco donnent du feedback!

Bonjour et bienvenue dans la dernière partie de notre gamme Disco Glasses.

Dans la partie d’aujourd’hui, nous allons une fois de plus résumer toutes les informations pertinentes pour la construction des lunettes, montrer quelques photos des séquences d’animation et bien sûr faire don d’une mise à niveau fonctionnelle de nos lunettes. La mise à niveau fonctionnelle de la partie d’aujourd’hui se compose d’un capteur de vibration, qui est activé par vos mouvements de danse dans la discothèque et donne ainsi à notre micro contrôleur des informations sur votre "comportement de danse" sur la piste de danse. A partir de cette information, les séquences lumineuses des lunettes sont contrôlées.

En d’autres termes, vos lunettes répondent à vos mouvements de danse rythmique! Comment ça marche techniquement ?

En tant qu’élément central, nous avons d’abord besoin d’un capteur de vibration. Cela peut être trouvé dans notre boutique en plusieurs versions. Chacun des capteurs mentionnés réagit légèrement différemment aux mouvements. Ainsi, le résultat final dépendra bien sûr également du capteur utilisé. Je recommande le Module de capteur KY-002n comme capteur de vibration. J’ai aussi fait cela dans ma propre configuration de testTet lors de l’élaboration du code. Il est important que le capteur passe activement au sol. Cela signifie qu’en cas de « choc », le capteur utilisé ferme brièvement le contact après GND.

Pointe: Essayez différents capteurs si nécessaire pour obtenir votre meilleur résultat. Une sélection de capteurs alternatifs se trouve à la fin de ce blog !

Le deuxième nouveau composant matériel est un commutateur plus simple. Ce commutateur est utilisé pour passer de l’ancien mode autosuffisant connu de la partie 2 au nouveau mode qui réagit aux mouvements. Le passage d’un mode à l’autre peut avoir lieu à tout moment. Aussi, par exemple, lors d’un programme en cours!

Mais passons au câblage des deux nouveaux composants de nos lunettes.

Comme on peut le voir sur le schéma, le capteur de vibration se trouve entre GND et le port 10 et le commutateur entre GND et le port 11 du processeur. Le câblage du bouton, d’autre part, n’a pas changé:

Partie 3: Fritzing Schematic

 

Aussi le câblage des deux anneaux WS2812 n’a pas changé par rapport à la partie précédente de la série:

 

Partie 3: Fritzing Detail

 

Veuillez télécharger le code mis à jour par les fonctionnalités suivant sur vos lunettes après la mise à jour matérielle :

 

 

#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 SHOCK_SENSOR 10               Choc / Capteur de vibration attaché
#define MODE_SWITCH 11                Mode Opération
#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
Octet Saturation = 255;
Contrôle interrut
Bool A60telSecInterruptOccured = Vrai;
Bool FunctionMode = Faux;
Octet A60telSecondes24 = 0;
Octet A4telSecondes24 = 0;
Variables de minuterie
Int TimerSeconds TimerSeconds = 0;  Counter
Int TimerAlarmSet (en anglais) = 15; 15 Deuxième minuterie
Bool TimerStartFlagFlagFlag = Faux;
Bool Timerstop = Vrai;
Opérations manuelles
Bool ButtonAPress (en)  = Faux;

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

Bool OLDONOFFStatus = Faux;
Bool PlayIntro = Faux; Jouer Intro
Bool PlayOutro PlayOutro = Faux; Jouer Outro
Bool ChangementAnimation = Faux;
Bool RunOnce (RunOnce) = Vrai;  Animation Power Off - Anmation 0

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

Interrompre les routines

ISR (ISR)(TIMER1_COMPA_vect)
{   Bool LEDChange (en), PressedZ (pressedZ);   PressedZ (pressedZ) = digitalRead (en)(BUTTON_CHANGEANIMATION); Lire bouton Push   FunctionMode = digitalRead (en)(MODE_SWITCH);   Si ((PressedZ (pressedZ) == Faible) Et (ButtonAPress (en) == Faux))   {     ButtonAPress (en) = Vrai;   }   TCNT1 (en) = 0;      Enregistrement de l’initialisation
}

Interrompre la fin Commence programme principal
Vide Configuration()
{   Bande.Commencer();   Bande.Montrer();   Initialiser tous les pixels à 'off'   pinMode(BUTTON_CHANGEANIMATION, INPUT_PULLUP);   pinMode(SHOCK_SENSOR, INPUT_PULLUP);   pinMode(MODE_SWITCH, INPUT_PULLUP);   randomSeed(analogRead (en)(0));   noInterrupts(); Désactiver tous les Interrrupts   TCCR1A (EN) = 0x00;   TCCR1B (EN) =  0x02;   TCNT1 (en) = 0;      Enregistrement de l’initialisation   OCR1A =  33353;      Charge de sortie Comparer registre   TIMSK1 (en) |= (1 << OCIE1A);  Activer la minuterie Comparer l’interruption   Interrompt();   Activer toutes les interruptions
}


Fonctions d’aide

Vide HSBToRGB
(   Unsigned Int inHue, Unsigned Int inSaturation, Unsigned Int inBrightness,   Unsigned Int *Ou, Unsigned Int *Og, Unsigned Int *Ob )
{   Si (inSaturation == 0)   {     achromatique (gris)     *Ou = *Og = *Ob = inBrightness;   }   Autre   {     Unsigned Int scaledHue = (inHue * 6);     Unsigned Int Secteur = scaledHue >> 8; secteur 0 à 5 autour de la roue de couleur     Unsigned Int offsetInSector = scaledHue - (Secteur << 8);  position au sein du secteur     Unsigned Int P = (inBrightness * ( 255 - inSaturation )) >> 8;     Unsigned Int Q = (inBrightness * ( 255 - ((inSaturation * offsetInSector) >> 8) )) >> 8;     Unsigned Int T = (inBrightness * ( 255 - ((inSaturation * ( 255 - offsetInSector )) >> 8) )) >> 8;     Interrupteur ( 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;       Par défaut:    cas 5:         *Ou = inBrightness;         *Og = P;         *Ob = Q;         Pause;     }   }
}

Vide CheckConfigButtons ()    InterruptRoutine
{   Bool PressedZ (pressedZ);   Si (ButtonAPress (en) == Vrai)   {     Si (DevraitAnimation < MaxAninmationsAvail )     {       DevraitAnimation++;     } Autre     {       DevraitAnimation = 0;     }     Retard(400);     ButtonAPress (en) = Faux;   }
}

Vide AnimationControl ()
{   Int GetSelAnimation (en) = 0;   Si (GetONOFFStatus GetONOFFStatus != OLDONOFFStatus)   {     OLDONOFFStatus = GetONOFFStatus GetONOFFStatus;     Si (GetONOFFStatus GetONOFFStatus)     {       DevraitAnimation = 1;     } Autre     {       DevraitAnimation = 0;     }   }
}

----------------------------------------------------------------------- de la boucle principale

Vide Boucle()
{   AnimationControl();   RunAnimations();   CheckConfigButtons();
}
Boucle principale ----------------------------------------------------------------------- fin
Intros

Vide Intro_CountUp (Octet R, Octet G, Octet B, Int retard, Bool Dir)
{   Si (Dir)   {     Pour ( Int  = 0;  < Bande.numPixels (numPixels)(); ++)     {       Bande.setPixelColor(, R, G, B);    Valeurs Calulate RGB pour Pixel       Bande.Montrer();   Afficher les résultats :)       Retard(retard);     }   } Autre   {     Pour ( Int  = 0;  < Bande.numPixels (numPixels)() + 1; ++)     {       Octet Pos = Bande.numPixels (numPixels)() - ;       Bande.setPixelColor(Pos, R, G, B);    Valeurs Calulate RGB pour Pixel       Bande.Montrer();   Afficher les résultats :)       Retard(retard);     }   }
}

Vide Intro_RaiseRainbow(Bool hausse)
{   Luminosité = 255;   Int Rainbowcolor (Rainbowcolor) = 0;   Si (hausse)   {     Pour (Int  = 0;  < Bande.numPixels (numPixels)(); ++)     {       Teinte = Carte( + Rainbowcolor (Rainbowcolor), angleMin, 60, hueRedLow, hueRedHigh); Définir la couleur       HSBToRGB(Teinte, Saturation, Luminosité, &R, &G, &B); Définir la couleur       Bande.setPixelColor(, R, G, B);     Valeurs Calulate RGB pour Pixel       Bande.Montrer();       Retard(40);     }   } Autre   {     Pour (Int  = 0;  < Bande.numPixels (numPixels)(); ++)     {       Bande.setPixelColor(, 0, 0, 0);       Bande.Montrer();       Retard(40);     }   }
}

Animations Outtros
Vide Ani_AllOff ()
{   Pour ( Int  = 0;  < Bande.numPixels (numPixels)(); ++)   {     Bande.setPixelColor(, 0, 0, 0);     tous hors tension   }   Bande.Montrer();
}

Vide Ani_AllOn (Octet R, Octet G, Octet B)
{   Pour ( Int  = 0;  < Bande.numPixels (numPixels)(); ++)   {     Bande.setPixelColor(, R, G, B);     tous sur   }   Bande.Montrer();
}

Vide Ani_Starshower ()
{   Int Array[10] ;   Bool chocValue = Vrai;   Bool Pressé =  Vrai;   Pour ( Int  = 0;  < Bande.numPixels (numPixels)(); ++)   {     Bande.setPixelColor(, 0, 0, 15);     tous bleus à base   }   Pour (Int  = 0;  < 10; ++)   {     Int Sélectionné = Aléatoire(Bande.numPixels (numPixels)());     Bande.setPixelColor(Sélectionné, 255, 255, 255); Blanc   }   Bande.Montrer();   Retard(100);   Pour ( Int  = 0;  < Bande.numPixels (numPixels)(); ++)   {     Bande.setPixelColor(, 0, 0, 15);     tous bleus à base   }   Bande.Montrer();   Si (FunctionMode)   {     Retard(500);   } Autre   {     faire     {       chocValue = digitalRead (en)(SHOCK_SENSOR);       Pressé = digitalRead (en)(BUTTON_CHANGEANIMATION);       FunctionMode = digitalRead (en)(MODE_SWITCH);     } Tandis que ((chocValue) && (!FunctionMode) && ( Pressé))  ;   }
}

Vide Ani_Rainbow(Octet retard)
{   Luminosité = 100;   Int Rainbowcolor (Rainbowcolor) = 0;   Bool chocValue = Vrai;   Bool Pressé =  Vrai;   faire   {     Pour (Int  = 0;  < Bande.numPixels (numPixels)(); ++)     {       Teinte = Carte( + Rainbowcolor (Rainbowcolor), angleMin, 60, hueRedLow, hueRedHigh);       HSBToRGB(Teinte, Saturation, Luminosité, &R, &G, &B);       Bande.setPixelColor(, R, G, B);     }     Bande.Montrer();   Afficher les résultats :)     Si (FunctionMode)     {       Retard(retard);     } Autre     {       faire       {         chocValue = digitalRead (en)(SHOCK_SENSOR);         Pressé = digitalRead (en)(BUTTON_CHANGEANIMATION);         FunctionMode = digitalRead (en)(MODE_SWITCH);       } Tandis que ((chocValue) && (!FunctionMode) && ( Pressé))  ;     }     Rainbowcolor (Rainbowcolor)++ ;   } Tandis que (Rainbowcolor (Rainbowcolor) < 61);
}

Vide Ani_Two_Color ()
{   Bool chocValue = Vrai;   Bool Pressé =  Vrai;   Octet Diviseur = Aléatoire (1, 10);   Bool Couleur;   Int X = 1;   B = 0;   Pour (Int s = 0; s > -1; s = s + X)   {     Couleur = Faux;     Pour ( Int  = 0;  < Bande.numPixels (numPixels)(); ++)     {       Un =  / Diviseur;       Si (!(Un == B))       {         B = Un;         Couleur = !Couleur;       }       Si (Couleur) {         Bande.setPixelColor(, 0, s, 0);  Grün       }       Si (!(Couleur)) {         Bande.setPixelColor(, s, 0, 0);  Pourrir       }     }     Bande.Montrer();     Si (s == 255)     {       Si (FunctionMode)       {         X = -1;         Retard(200);       } Autre       {         faire         {           chocValue = digitalRead (en)(SHOCK_SENSOR);           Pressé = digitalRead (en)(BUTTON_CHANGEANIMATION);           FunctionMode = digitalRead (en)(MODE_SWITCH);         } Tandis que ((chocValue) && (!FunctionMode) && ( Pressé)) ;         X = -1;       }     }     Retard(10);   }   Bande.Montrer();
}

Vide Ani_Halloween()
{   Bool chocValue = Vrai;   Bool Pressé =  Vrai;   Un = -10;   Pour (Int  = 0;  < Bande.numPixels (numPixels)(); ++)   {     Bande.setPixelColor(, Aléatoire(1, 254), Aléatoire(1, 204), Aléatoire(1, 254));     E = E + Un;     F = F + Un;     Si (F <= 0)     {       Un = +10;     }     Si (F >= 60)     {       Un = -10;     }   }   Bande.Montrer();   Afficher les résultats :)   Si (FunctionMode)   {     Retard(300);   } Autre   {     faire     {       chocValue = digitalRead (en)(SHOCK_SENSOR);       Pressé = digitalRead (en)(BUTTON_CHANGEANIMATION);       FunctionMode = digitalRead (en)(MODE_SWITCH);     } Tandis que ((chocValue) && (!FunctionMode) && ( Pressé))  ;   }
}

Vide FadeColor (FadeColor) ()
{   Octet Luminosité = 0;   Octet Saturation = 0;   Int Colori = 49 ;   faire   {     Pour (Int  = 0;  < Bande.numPixels (numPixels)(); ++)     {       HSBToRGB(Colori, Saturation, Luminosité, &R, &G, &B); Définir la couleur       Bande.setPixelColor(, R, G, B);     Valeurs Calulate RGB pour Pixel     }     Luminosité ++;     Bande.Montrer();   Afficher les résultats :)     Retard(40);   } Tandis que (Luminosité < 50);
}

Vide RunAnimations()
{   Si (!(DevraitAnimation == IsAnimation))   {     PlayOutro PlayOutro = Vrai;     ChangementAnimation = Vrai;   }   Interrupteur (IsAnimation)   {     Cas 0:                                    tous LedsOFF       Si (PlayIntro)       {         PlayIntro = Faux;         Runonce (Runonce) = Vrai;       }       Si   ((!(PlayIntro)) &&  (!(PlayOutro PlayOutro)))       {         Si (Runonce (Runonce)) {           Ani_AllOff ();         }         Runonce (Runonce) = Faux;       }       Si  (PlayOutro PlayOutro)       {         PlayOutro PlayOutro  = Faux;         PlayIntro = Vrai;         Runonce (Runonce) = Vrai;         IsAnimation = DevraitAnimation;       }       Pause;     Cas 1:       Si (PlayIntro)       {         Intro_CountUp (0, 0, 15, 100, Vrai);         PlayIntro = Faux;       }       Si  ((!(PlayIntro)) && (!(PlayOutro PlayOutro)))       {         Ani_Starshower();       }       Si  (PlayOutro PlayOutro)       {         Intro_CountUp (0, 0, 0, 100, Faux);         PlayOutro PlayOutro  = Faux;         PlayIntro = Vrai;         IsAnimation =  DevraitAnimation;       }       Pause;     Cas 2:       Si (PlayIntro)       {         Intro_RaiseRainbow(Vrai);         PlayIntro = Faux;       }       Si  ((!(PlayIntro)) && (!(PlayOutro PlayOutro)))       {         Ani_Rainbow(20);       }       Si  (PlayOutro PlayOutro)       {         Intro_RaiseRainbow(Faux);         PlayOutro PlayOutro  = Faux;         PlayIntro = Vrai;         IsAnimation =  DevraitAnimation;       }       Pause;     Cas 3:       Si (PlayIntro)       {         Ani_AllOff ();         PlayIntro = Faux;       }       Si  ((!(PlayIntro)) && (!(PlayOutro PlayOutro)))       {         Ani_Two_Color (); Ani_Two_Color (tote hue, byte tail,byte brightness,byte delaytime)       }       Si  (PlayOutro PlayOutro)       {         PlayOutro PlayOutro  = Faux;         PlayIntro = Vrai;         IsAnimation =  DevraitAnimation;       }       Pause;     Cas 4:       Si (PlayIntro)       {         Ani_AllOff ();         PlayIntro = Faux;       }       Si  ((!(PlayIntro)) && (!(PlayOutro PlayOutro)))       {         Ani_Halloween (); //       }       Si  (PlayOutro PlayOutro)       {         PlayOutro PlayOutro  = Faux;         PlayIntro = Vrai;         IsAnimation =  DevraitAnimation;       }       Pause;   }
}

 

En appuyant sur le bouton, les animations peuvent maintenant être appelées l’une après l’autre. Ce qui est nouveau, c’est qu’il peut maintenant être commuté entre les modes de fonction autonome et de rétroaction en appuyant simplement sur le commutateur.

Tout le monde réagit ! des quatre animations légèrement différentes sur le capteur de vibration si le mode "Feedback" est sélectionné.

En tant que petite aide à la performance, j’ai déjà photographié les 4 animations différentes :

 

Starshower:

Effet: Starshower

Arc-en-ciel:

Partie 3 - Effet arc-en-ciel

Mouvement de deux couleurs:

Partie 3: Mouvement de deux couleurs

 

Halloween:

Partie 3 - Effet halloween

 

S’il vous plaît noter que dans les deux! Ne passe pas les animations à l’animation suivante immédiatement, mais toujours sortir de la séquence en cours avant le début de la prochaine animation.


Je vous souhaite beaucoup de plaisir à recréer les lunettes disco. Peut-être que vous voulez programmer plus de séquences d’animation si les 4 existantes ne sont pas assez pour vous?

Essayez d’autres capteurs, tels que :

Ou vous pouvez essayer d’utiliser un capteur des différents

 

Écrivez vos idées ou vos questions dans les commentaires.

 

Pour arduinoProjets pour les débutants

Laisser un commentaire

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

Messages de blogs recommandés

  1. Installez maintenant ESP32 via l'administrateur de la carte
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA-Over the Air-ESP Programmation par WiFi