I nostri occhiali da discoteca danno un feedback!

Salve e benvenuti nell'ultima parte della nostra gamma Disco Glasses.

Nella parte di oggi riassumeremo ancora una volta tutte le informazioni rilevanti per la costruzione degli occhiali, mostreremo alcune immagini delle sequenze di animazione e, naturalmente, doneremo un aggiornamento funzionale ai nostri occhiali. L'aggiornamento funzionale nella parte di oggi è costituito da un sensore di vibrazione, che viene attivato dai tuoi movimenti di danza in discoteca e quindi fornisce al nostro micro controller informazioni sul tuo "comportamento di danza" sulla pista da ballo. Da queste informazioni, le sequenze luminose degli occhiali sono controllate.

In altre parole, i tuoi occhiali rispondono alle tue mosse di danza ritmica! Beh, come funziona tutto tecnicamente?

Come elemento centrale, abbiamo bisogno di un sensore di vibrazione. Questo può essere trovato nel nostro negozio in diverse versioni. Ognuno dei sensori menzionati reagisce in modo leggermente diverso ai movimenti. Pertanto, il risultato finale dipenderà ovviamente anche dal sensore utilizzato. Raccomando il Modulo sensore KY-002n come sensore di vibrazione. Ho anche fatto questo nella mia configurazione di provaTe durante lo sviluppo del codice. È importante che il sensore passi attivamente a terra. Ciò significa che in caso di "shock", il sensore utilizzato chiude brevemente il contatto dopo la GND.

mancia: Provare diversi sensori, se necessario, per ottenere il miglior risultato. Una selezione di sensori alternativi può essere trovato alla fine di questo blog!

Il secondo nuovo componente hardware è uno switch più semplice. Questo interruttore viene utilizzato per passare dalla vecchia modalità autosufficiente nota dalla Parte 2 alla nuova modalità che reagisce ai movimenti. Il passaggio da una modalità all'altra può avvenire in qualsiasi momento. Inoltre, per esempio, durante un programma in corso!

Ma passiamo al cablaggio dei due nuovi componenti nei nostri occhiali.

Come si può vedere sullo schema, il sensore di vibrazione si trova tra GND e porta 10 e il passaggio tra GND e porta 11 del processore. Il cablaggio del pulsante, d'altra parte, non è cambiato:

Parte 3: Schema di Fritzing

 

Anche il cablaggio dei due anelli WS2812 non è cambiato rispetto alla parte precedente della serie:

 

Parte 3: Dettaglio Fritzing

 

Si prega di caricare il seguente codice aggiornato alle funzionalità per gli occhiali dopo l'aggiornamento hardware:

 

 

#include <Adafruit_NeoPixel.H>

# define BUTTON_CHANGEANIMATION  12    Pin I/O digitale collegato al pulsante.  Questo sarà
guidato con un resistore pull-up in modo che l'interruttore dovrebbe
Tirare il perno a terra momentaneamente.  Su un alto -> basso
transizione verrà eseguita la logica di pressione del pulsante.
# define PIXEL_PIN    6                Pin I/O digitale connesso a NeoPixels.
# define SHOCK_SENSOR 10               Sensore d'urto/vibrazione collegato
# define MODE_SWITCH 11                Modalità operativa
# define PIXEL_COUNT 24                Tutti i pixel sulla striscia
# define MaxAninmationsAvail 4

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

Const Int tonalitàRedLow = 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 = 255;

Byte Hue, "Io non sono;
La saturazione è fissata a 255 (completa) per rimuovere la
"Io non sono
Byte Saturazione = 255;
Controllo interrut
Bool A60telSecInterruptOccured = Vero;
Bool Modalità Funzione = False;
Byte A60telSeconds24 = 0;
Byte A4telSeconds24 = 0;
Variabili timer
Int TimerSecondi = 0;  Contatore
Int TimerAlarmSet = 15; Timer di 15 secondi
Bool TimerStartFlagFlagFlag = False;
Bool TimerStop = Vero;
Operazioni manuali
Bool ButtonAPress  = False;

AnimazioneControllo
Int ShouldAnimation  = 0;
Int IsAnimation  = 0;
Int OLDLightBorder = 0;
Bool GetONOFFStatus (Stato) GetONOFF = False;

Bool OLDONOFFStatus = False;
Bool PlayIntro = False; Riproduci Introduzione
Bool PlayOutro = False; Gioca Outro
Bool ModificaAnimazione = False;
Bool Runonce = Vero;  Animazione di Spegnimento - Anmation 0

variabili universali
byte Un, C, D, e, F;
Unsigned Int R, G, B;

Routine di interrupt

Pvr(TIMER1_COMPA_vect)
{   Bool LEDCambia, Premuto;   Premuto = digitalRead (Lettura digitale)(BUTTON_CHANGEANIMATION); Pulsante Leggi Push   Modalità Funzione = digitalRead (Lettura digitale)(MODE_SWITCH);   Se ((Premuto == Basso) E (ButtonAPress == False))   {     ButtonAPress = Vero;   }   TCNT1 (in questo stato in stato di = 0;      Inizializzazione del registro
}

Gli interrupt terminano Inizio Programma Principale
Vuoto Installazione()
{   Striscia.Iniziare();   Striscia.Visualizza();   Inizializzare tutti i pixel su 'off'   PinMode (Modalità pin)(BUTTON_CHANGEANIMATION, INPUT_PULLUP);   PinMode (Modalità pin)(SHOCK_SENSOR, INPUT_PULLUP);   PinMode (Modalità pin)(MODE_SWITCH, INPUT_PULLUP);   randomSeed (Seed randomse)(analogicOLettura(0));   noInterruzioni(); Disattiva tutti gli interrrupt   TCCR1A = 0x00 (in questo 0x00);   TCCR1B =  0x02 (in tissuta 0x0;   TCNT1 (in questo stato in stato di = 0;      Inizializzazione del registro   OCR1A =  33353;      Registro di confronto dell'output del caricoLoad Output Compare Register   TIMSK1 |= (1 << CIE1A);  Attiva interruzione confronto timer   Interrompe();   Abilita tutti gli interrupt
}


Funzioni di supporto

Vuoto HSBToRGB
(   Unsigned Int inHue, Unsigned Int inSaturazione, Unsigned Int inLuminosità,   Unsigned Int *O, Unsigned Int *Og, Unsigned Int *Ob )
{   Se (inSaturazione == 0)   {     acromatico (grigio)     *O = *Og = *Ob = inLuminosità;   }   Altro   {     Unsigned Int scaledHue = (inHue * 6);     Unsigned Int Settore = scaledHue >> 8; settore da 0 a 5 intorno alla ruota dei colori     Unsigned Int offsetInSector = scaledHue - (Settore << 8);  posizione all'interno del settore     Unsigned Int P = (inLuminosità * ( 255 - inSaturazione )) >> 8;     Unsigned Int D = (inLuminosità * ( 255 - ((inSaturazione * offsetInSector) >> 8) )) >> 8;     Unsigned Int T = (inLuminosità * ( 255 - ((inSaturazione * ( 255 - offsetInSector )) >> 8) )) >> 8;     Interruttore ( Settore ) {       Caso 0:         *O = inLuminosità;         *Og = T;         *Ob = P;         Pausa;       Caso 1:         *O = D;         *Og = inLuminosità;         *Ob = P;         Pausa;       Caso 2:         *O = P;         *Og = inLuminosità;         *Ob = T;         Pausa;       Caso 3:         *O = P;         *Og = D;         *Ob = inLuminosità;         Pausa;       Caso 4:         *O = T;         *Og = P;         *Ob = inLuminosità;         Pausa;       Predefinito:    caso 5:         *O = inLuminosità;         *Og = P;         *Ob = D;         Pausa;     }   }
}

Vuoto CheckConfigButtons ()    InterruptRoutine
{   Bool Premuto;   Se (ButtonAPress == Vero)   {     Se (ShouldAnimation < MaxAninmationsAvail )     {       ShouldAnimation++;     } Altro     {       ShouldAnimation = 0;     }     Ritardo(400);     ButtonAPress = False;   }
}

Vuoto AnimazioneControllo ()
{   Int GetSelAnimation = 0;   Se (GetONOFFStatus (Stato) GetONOFF != OLDONOFFStatus)   {     OLDONOFFStatus = GetONOFFStatus (Stato) GetONOFF;     Se (GetONOFFStatus (Stato) GetONOFF)     {       ShouldAnimation = 1;     } Altro     {       ShouldAnimation = 0;     }   }
}

----------------------------------------------------------------------- loop principale

Vuoto Ciclo()
{   AnimazioneControllo();   Animazioni RunAnimations();   CheckConfigButtons();
}
Fine ----------------------------------------------------------------------- loop principale
Intros

Vuoto Intro_CountUp (byte R, byte G, byte B, Int tempo di ritardo, Bool Dir)
{   Se (Dir)   {     Per ( Int Ho = 0; Ho < Striscia.numPixel(); Ho++)     {       Striscia.setPixelColor(Ho, R, G, B);    Calulate Valori RGB per Pixel       Striscia.Visualizza();   Mostra :) risultati       Ritardo(tempo di ritardo);     }   } Altro   {     Per ( Int Ho = 0; Ho < Striscia.numPixel() + 1; Ho++)     {       byte Pos = Striscia.numPixel() - Ho;       Striscia.setPixelColor(Pos, R, G, B);    Calulate Valori RGB per Pixel       Striscia.Visualizza();   Mostra :) risultati       Ritardo(tempo di ritardo);     }   }
}

Vuoto Intro_RaiseRainbow(Bool risefall)
{   Luminosità = 255;   Int Colore arcobaleno = 0;   Se (risefall)   {     Per (Int Ho = 0; Ho < Striscia.numPixel(); Ho++)     {       Hue = Mappa(Ho + Colore arcobaleno, angleMin, 60, tonalitàRedLow, hueRedHigh); Imposta colore       HSBToRGB(Hue, Saturazione, Luminosità, &R, &G, &B); Imposta colore       Striscia.setPixelColor(Ho, R, G, B);     Calulate Valori RGB per Pixel       Striscia.Visualizza();       Ritardo(40);     }   } Altro   {     Per (Int Ho = 0; Ho < Striscia.numPixel(); Ho++)     {       Striscia.setPixelColor(Ho, 0, 0, 0);       Striscia.Visualizza();       Ritardo(40);     }   }
}

Estruzioni animazioni
Vuoto Ani_AllOff ()
{   Per ( Int Ho = 0; Ho < Striscia.numPixel(); Ho++)   {     Striscia.setPixelColor(Ho, 0, 0, 0);     tutto fuori   }   Striscia.Visualizza();
}

Vuoto Ani_AllOn (byte R, byte G, byte B)
{   Per ( Int Ho = 0; Ho < Striscia.numPixel(); Ho++)   {     Striscia.setPixelColor(Ho, R, G, B);     tutto il   }   Striscia.Visualizza();
}

Vuoto Ani_Starshower ()
{   Int Matrice[10] ;   Bool shockValue = Vero;   Bool Premuto =  Vero;   Per ( Int Ho = 0; Ho < Striscia.numPixel(); Ho++)   {     Striscia.setPixelColor(Ho, 0, 0, 15);     tutti a base blu   }   Per (Int Ho = 0; Ho < 10; Ho++)   {     Int Selezionato = Casuale(Striscia.numPixel());     Striscia.setPixelColor(Selezionato, 255, 255, 255); Bianco   }   Striscia.Visualizza();   Ritardo(100);   Per ( Int Ho = 0; Ho < Striscia.numPixel(); Ho++)   {     Striscia.setPixelColor(Ho, 0, 0, 15);     tutti a base blu   }   Striscia.Visualizza();   Se (Modalità Funzione)   {     Ritardo(500);   } Altro   {     fare     {       shockValue = digitalRead (Lettura digitale)(SHOCK_SENSOR);       Premuto = digitalRead (Lettura digitale)(BUTTON_CHANGEANIMATION);       Modalità Funzione = digitalRead (Lettura digitale)(MODE_SWITCH);     } Mentre ((shockValue) && (!Modalità Funzione) && ( Premuto))  ;   }
}

Vuoto Ani_Rainbow(byte tempo di ritardo)
{   Luminosità = 100;   Int Colore arcobaleno = 0;   Bool shockValue = Vero;   Bool Premuto =  Vero;   fare   {     Per (Int Ho = 0; Ho < Striscia.numPixel(); Ho++)     {       Hue = Mappa(Ho + Colore arcobaleno, angleMin, 60, tonalitàRedLow, hueRedHigh);       HSBToRGB(Hue, Saturazione, Luminosità, &R, &G, &B);       Striscia.setPixelColor(Ho, R, G, B);     }     Striscia.Visualizza();   Mostra :) risultati     Se (Modalità Funzione)     {       Ritardo(tempo di ritardo);     } Altro     {       fare       {         shockValue = digitalRead (Lettura digitale)(SHOCK_SENSOR);         Premuto = digitalRead (Lettura digitale)(BUTTON_CHANGEANIMATION);         Modalità Funzione = digitalRead (Lettura digitale)(MODE_SWITCH);       } Mentre ((shockValue) && (!Modalità Funzione) && ( Premuto))  ;     }     Colore arcobaleno++ ;   } Mentre (Colore arcobaleno < 61);
}

Vuoto Ani_Two_Color ()
{   Bool shockValue = Vero;   Bool Premuto =  Vero;   byte Divisore = Casuale (1, 10);   Bool Colore;   Int X = 1;   B = 0;   Per (Int s = 0; s > -1; s = s + X)   {     Colore = False;     Per ( Int Ho = 0; Ho < Striscia.numPixel(); Ho++)     {       Un = Ho / Divisore;       Se (!(Un == B))       {         B = Un;         Colore = !Colore;       }       Se (Colore) {         Striscia.setPixelColor(Ho, 0, s, 0);  Grün       }       Se (!(Colore)) {         Striscia.setPixelColor(Ho, s, 0, 0);  Rot       }     }     Striscia.Visualizza();     Se (s == 255)     {       Se (Modalità Funzione)       {         X = -1;         Ritardo(200);       } Altro       {         fare         {           shockValue = digitalRead (Lettura digitale)(SHOCK_SENSOR);           Premuto = digitalRead (Lettura digitale)(BUTTON_CHANGEANIMATION);           Modalità Funzione = digitalRead (Lettura digitale)(MODE_SWITCH);         } Mentre ((shockValue) && (!Modalità Funzione) && ( Premuto)) ;         X = -1;       }     }     Ritardo(10);   }   Striscia.Visualizza();
}

Vuoto Ani_Halloween()
{   Bool shockValue = Vero;   Bool Premuto =  Vero;   Un = -10;   Per (Int Ho = 0; Ho < Striscia.numPixel(); Ho++)   {     Striscia.setPixelColor(Ho, Casuale(1, 254), Casuale(1, 204), Casuale(1, 254));     e = e + Un;     F = F + Un;     Se (F <= 0)     {       Un = +10;     }     Se (F >= 60)     {       Un = -10;     }   }   Striscia.Visualizza();   Mostra :) risultati   Se (Modalità Funzione)   {     Ritardo(300);   } Altro   {     fare     {       shockValue = digitalRead (Lettura digitale)(SHOCK_SENSOR);       Premuto = digitalRead (Lettura digitale)(BUTTON_CHANGEANIMATION);       Modalità Funzione = digitalRead (Lettura digitale)(MODE_SWITCH);     } Mentre ((shockValue) && (!Modalità Funzione) && ( Premuto))  ;   }
}

Vuoto Colore Dissolvenza ()
{   byte Luminosità = 0;   byte Saturazione = 0;   Int Colori = 49 ;   fare   {     Per (Int Ho = 0; Ho < Striscia.numPixel(); Ho++)     {       HSBToRGB(Colori, Saturazione, Luminosità, &R, &G, &B); Imposta colore       Striscia.setPixelColor(Ho, R, G, B);     Calulate Valori RGB per Pixel     }     Luminosità ++;     Striscia.Visualizza();   Mostra :) risultati     Ritardo(40);   } Mentre (Luminosità < 50);
}

Vuoto Animazioni RunAnimations()
{   Se (!(ShouldAnimation == IsAnimation))   {     PlayOutro = Vero;     ModificaAnimazione = Vero;   }   Interruttore (IsAnimation)   {     Caso 0:                                    tutti i LedOFF       Se (PlayIntro)       {         PlayIntro = False;         Runonce = Vero;       }       Se   ((!(PlayIntro)) &&  (!(PlayOutro)))       {         Se (Runonce) {           Ani_AllOff ();         }         Runonce = False;       }       Se  (PlayOutro)       {         PlayOutro  = False;         PlayIntro = Vero;         Runonce = Vero;         IsAnimation = ShouldAnimation;       }       Pausa;     Caso 1:       Se (PlayIntro)       {         Intro_CountUp (0, 0, 15, 100, Vero);         PlayIntro = False;       }       Se  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Starshower();       }       Se  (PlayOutro)       {         Intro_CountUp (0, 0, 0, 100, False);         PlayOutro  = False;         PlayIntro = Vero;         IsAnimation =  ShouldAnimation;       }       Pausa;     Caso 2:       Se (PlayIntro)       {         Intro_RaiseRainbow(Vero);         PlayIntro = False;       }       Se  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Rainbow(20);       }       Se  (PlayOutro)       {         Intro_RaiseRainbow(False);         PlayOutro  = False;         PlayIntro = Vero;         IsAnimation =  ShouldAnimation;       }       Pausa;     Caso 3:       Se (PlayIntro)       {         Ani_AllOff ();         PlayIntro = False;       }       Se  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Two_Color (); Ani_Two_Color (coda byte,coda byte,luminosità byte,byte delaytime)       }       Se  (PlayOutro)       {         PlayOutro  = False;         PlayIntro = Vero;         IsAnimation =  ShouldAnimation;       }       Pausa;     Caso 4:       Se (PlayIntro)       {         Ani_AllOff ();         PlayIntro = False;       }       Se  ((!(PlayIntro)) && (!(PlayOutro)))       {         Ani_Halloween (); //       }       Se  (PlayOutro)       {         PlayOutro  = False;         PlayIntro = Vero;         IsAnimation =  ShouldAnimation;       }       Pausa;   }
}

 

Premendo il pulsante, le animazioni possono ora essere richiamate una dopo l'altra. La novità è che ora può essere commutata tra le modalità autonome e le modalità di funzione di feedback semplicemente premendo l'interruttore.

Tutti reagiscono! delle quattro animazioni leggermente diverse sul sensore di vibrazione se è selezionata la modalità "Feedback".

Come un piccolo aiuto di prestazioni una volta ho fotografato tutte e 4 le diverse animazioni:

 

Doccia stellare:

Effetto: Starshower

arcobaleno:

Parte 3 - Effetto Arcobaleno

Movimento di due colori:

Parte 3: Movimento di due colori

 

Halloween:

Parte 3 - Effetto halloween

 

Si prega di notare che in entrambi! Non passa immediatamente le animazioni all'animazione successiva, ma esce sempre dalla sequenza corrente prima dell'inizio dell'animazione successiva.


Vi auguro un sacco di divertimento ricreando gli occhiali da discoteca. Forse si desidera programmare più sequenze di animazione se i 4 esistenti non sono sufficienti per voi?

Provare altri sensori, ad esempio:

Oppure si può provare a utilizzare un sensore dei vari

 

Scrivi le tue idee o domande nei commenti.

 

Für arduinoProjekte für anfänger

Einen Kommentar hinterlassen

Alle Kommentare werden vor der Veröffentlichung moderiert

Post di blog consigliati

  1. Installa ESP32 ora dal gestore del consiglio di amministrazione
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - Programmazione ESP tramite WLAN

Prodotti consigliati