Ciao, e caldamente sia il benvenuto nella seconda parte di «fila di blog» di occhiali di discoteca.
In questa parte si estendono come già da molti di Lei aspetta, le funzionalità dei nostri occhiali, ma anche ci troveremo in questa parte su commenti dalla prima parte. Dunque, Le rendo disponibile un piano d'impianto elettrico aggiornato. Inoltre verrò esplicitamente a dettagli dell'impianto elettrico del WS1812b.
Inoltre, diamo al nostro hardware a piccolo Firmwareupgrade che permette per scegliere su una battuta sul proiettile tracciante da fino a 4 animazioni luminose diverse, emozionanti.
Per favore, i Suoi fili di hardware dopo questo aggiornato telegrafando il piano:
Perché a noi anche particolarmente le domande si sono estese all'impianto elettrico dettagliato degli anelli, qui qualche volta particolarmente questa parte enlargedly mostrato:
Uno vede nel quadro che diventa la linea di dati tra gli anelli «durchgeschliffen». Cioè l'uscita di uscita di dati D6 sul primo squillo formerà un'alleanza dal microcontrollore dopo TU (I dati in) e formerà un'alleanza allora da questo anello di nuovo dallo Spillo TH (i Dati Fuori) al secondo squillo dopo TU (I dati in). Questo genere di collegamento è necessario per via della funzionalità dell'allenatore di dati seriale.
Adesso possiamo avventurarci in Firmwareupgrade e il codice seguente secondo il nostro deposito di alto livello di Arduino:
#include <Adafruit_NeoPixel.H> #define BUTTON_CHANGEANIMATION 12 //Digitalmente lo spillo di IO si è connesso al distintivo. Questo vuole Essere //guidato con un resistore di tirata su così l'interruttore debba //trasporti lo spillo in barca per basarsi per un attimo. Su un alto -> in basso //la transizione che la logica di stampa di distintivo vuole esegue. #define PIXEL_PIN 6 //Digitalmente lo spillo di IO si è connesso al neopixel. #define PIXEL_COUNT 24 //Di tutto il pixel su Striscia #define MaxAninmationsAvail 4 Adafruit_NeoPixel striscia = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_RGB + NEO_KHZ800); può intervallo hueRedLow = 0; può intervallo hueRedHigh = 255; può intervallo hueBlue = 170; può intervallo angleMin = 0; può intervallo angleSector = 60; può intervallo angleMax = 360; può intervallo brightMin = 0; può intervallo brightMax = 255; byte perbacco su, splendore; //La saturazione è fissata A 255 (si riempiono) per togliere blead-attraverso di diversi //colori. //Poteva Esser collegato a di altro potentiometers se una dimostrazione di perbacco su //è desiderato. byte saturazione = 255; //Controllo d'intersolco bool A60telSecInterruptOccured = vero; byte A60telSeconds24 = 0; byte A4telSeconds24 = 0; //Contaminuti di variabile intervallo TimerSeconds = 0; //Banco intervallo Serie di allarme di contaminuti = 15; //15 secondi di contaminuti bool TimerStartFlagFlag = falso; bool Cima di contaminuti = vero; //Operazioni manuali bool ButtonAPress = falso; //Intenal ha CONDOTTO LightEffects (ha CONDOTTO 13) byte LedMode = 2; //AnimationControl intervallo ShouldAnimation = 0; intervallo IsAnimation = 0; intervallo OLDLightBorder = 0; bool GetONOFFStatus = falso; bool OLDONOFFStatus = falso; bool PlayIntro = falso; //Introduzione di giochi bool PlayOutro = falso; //Giochi Outro bool ChangeAnimation = falso; bool RunOnce = vero; //Per Auschalt Amation - Anmation 0 //universalmente la variabile byte a, C, d, e, e il seguente; non firmato intervallo r, g, B; //Ordinarie amministrazioni d'interruzione ISR(TIMER1_COMPA_vect) { bool LEDChange, PressedZ; //Domanda d'interruttore PressedZ = digitalRead(BUTTON_CHANGEANIMATION); se ((PressedZ == IN BASSO) e (ButtonAPress == falso)) { ButtonAPress = vero; } TCNT1 = 0; //I registri con 0 inizializzano } //Fini di interruzioni //cominci il programma vuoto situazione() { striscia.cominciare(); striscia.mostrare(); //Inizializzi di tutto il pixel a 'di vista' pinMode(BUTTON_CHANGEANIMATION, INPUT_PULLUP); randomSeed(analogRead(0)); noInterrupts(); //Tutte le Interruzioni spengono temporaneamente TCCR1A = 0x00; TCCR1B = 0x02; TCNT1 = 0; Registrare mit 0 initialisieren OCR1A = 33353; Output Compare Register vorbelegen TIMSK1 |= (1 << CIE1A); Timer Confronta Interrupt aktivieren Interrompe(); alle Interrupts scharf schalten Seriale.Iniziare(9600); Seriale.sciacquone(); } Hilfsfunktionen 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++; Seriale.println ("fase1"); Seriale.println (ShouldAnimation); ShouldAnimation : 1; } Altro { ShouldAnimation = 0; } Ritardo(700); 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(); } Loop principale ----------------------------------------------------------------------- Ende 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); } } } Outtro 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] ; 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(); Ritardo(500); } Vuoto Ani_Rainbow(Byte tempo di ritardo) { "Io non sono = 100; Int Colore arcobaleno = 0; Thu { Per (Int Ho. = 0; Ho. < Striscia.numPixel(); Ho.++) { Hue = Mappa(Ho. + Colore arcobaleno, angleMin, 60, tonalitàRedLow, hueRedHigh); HSBToRGB(Hue, Saturazione, "Io non sono, &R, &G, &B); Striscia.setPixelColor(Ho., R, G, B); } Striscia.Visualizza(); Mostra :) risultati Ritardo(tempo di ritardo); Colore arcobaleno++ ; } Mentre (Colore arcobaleno < 61); } Vuoto Ani_Two_Color () { segmenti di byte - PIXEL_COUNT / 5; Byte Divisore = Casuale (1, 10); Bool Colore; Int X = 1; B = 0; Per (Int S (in vi = 0; S (in vi > -1; S (in vi = S (in vi + 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 (in vi, 0); Verde } Se (!(Colore)) { Striscia.setPixelColor(Ho., S (in vi, 0, 0); Rosso } } Striscia.Visualizza(); Se (S (in vi == 255) { X = -1; Ritardo(2000); } Ritardo(10); } Striscia.Visualizza(); } Vuoto Ani_Halloween() { Un = -10; Per (Int Ho. = 0; Ho. < Striscia.numPixel(); Ho.++) { Striscia.setPixelColor(Ho., Casuale(1, 254), Casuale(1, 204), Casuale(1, 254)); E (in questo modo = E (in questo modo + Un; D = D + Un; Se (D <= 0) { Un = +10; } Se (D >= 60) { Un = -10; } } Striscia.Visualizza(); Mostra :) risultati Ritardo(300); } Vuoto Colore Dissolvenza () { Byte "Io non sono = 0; Byte Saturazione = 0; Int Colori = 49 ; Thu { Per (Int Ho. = 0; Ho. < Striscia.numPixel(); Ho.++) { wdt_reset(); HSBToRGB(Colori, Saturazione, "Io non sono, &R, &G, &B); Imposta colore Striscia.setPixelColor(Ho., R, G, B); Calulate Valori RGB per Pixel } "Io non sono ++; Striscia.Visualizza(); Mostra :) risultati Ritardo(40); } Mentre ("Io non sono < 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; } }
Come funziona: premendo il pulsante, le seguenti animazioni possono ora essere chiamate una dopo l'altra. Un
- Doccia stellare
- arcobaleno
- Movimento di due colori
- Halloween
Si noti che le animazioni non passano immediatamente all'animazione successiva, ma terminano sempre la sequenza corrente prima di avviare l'animazione successiva.
Ancora una volta, naturalmente, sei cordialmente invitato a programmare più sequenze di animazione, se il 4 non sono sufficienti per te. La procedura di base per questo può essere visto nel codice.
Nella prossima e ultima parte della serie avremo i nostri occhiali reagire a "stimoli ambientali".
Vi auguro un sacco di divertimento ricostruzione e fino alla prossima volta.
2 commenti
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
Hi,
ich möchte 5 von der 38mm Ringen nutzen. Wo genau muss ich denn die Anzahl der Ringe einstellen?