Hola y bienvenidos a la segunda parte de la serie de blogs de "gafas".
En esta parte, como muchos de ustedes esperan, se amplían las funcionalidades de nuestras gafas, pero también en esta parte, comentaremos los comentarios de la primera parte. Por lo tanto, les proporcionaré un plan de cableado actualizado. También me referiré explícitamente a los detalles del cableado de la WS1812b.
Además, estamos donando a nuestro Hardware un pequeño ajuste de imagen del firmware que permite seleccionar hasta cuatro animaciones de luz diferentes y emocionantes a través de una pulsación de tecla en el teclado.
Por favor, cableen su Hardware según este plan de cableado actualizado:
Dado que también hemos recibido preguntas específicas sobre el cableado de detalle de los anillos, esta parte en particular se ha ampliado.:
Se puede ver en la imagen que "pule" la línea de datos entre los anillos. Es decir, desde el microcontrolador de la salida de datos D6 se conecta al primer anillo a DI (Data in) y, a continuación, de este anillo a DI (Data in), del Pin DO (Data Out) al segundo anillo. Este tipo de conexión es necesario debido al funcionamiento del bus de datos serie.
Ahora podemos ir al primer paso del Firmwarpeum y subir el siguiente código a nuestro Arduino.:
# include <Adafruit_NeoPixel.h> # define BUTTON_CHANGEANIMACIÓN 12 // Digital IO pin connected to the button. Esto va a ser / driven with a pull-up resistor so the switch should / pull the pin to ground momentarily. On a high - > low // transition the button press logic will execute. # define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels. # define PIXEL_COUNT 24 // All Pixels on Strip # define MaxAninmationsAvail 4 Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_RGB + NEO_KHZ800); const int hueRedLow = 0; const int hueRedHigh = 255; const int hueBlue = 170; const int anglemina = 0; const int angleSector = 60; const int angleMax = 360; const int brightMin = 0; const int brightMax = 255; bytes hue, brightness; // The saturation is fixed at 255 (full) to remove blead-through of different / colours. // It could be linked to another potentiómetro if a demonstration of hue / desired. bytes saturation = 255; // interrut Control bool A60telSecInterruptOccured = true; bytes A60telSeconds24 = 0; bytes A4telSeconds24 = 0; // Temporizador Variable int TimerSeconds = 0; // Numerador int Equipo de alarma de temporizador = 15; / Temporizador 15 Segundos bool TimerStartFlagFlag = false; bool Temporizador = true; // Manual Operations bool ButtonAPress = false; //Intental LED LightEffects (LED 13)) bytes LedMode = 2; //AnimationControl int Animación de inmersión = 0; int Isanimación = 0; int OLDLightBorder = 0; bool Estado de getonoff = false; bool Estado oldonoff = false; bool PlayIntro = false; // Juegos Introducción bool PlayOutro = false; // Juego Outro bool Animación de cambio = false; bool RunOnce = true; // Para Selección Desactivada 0 // universal variable variable bytes a, c, d, e, f; sin firma int r, g, b; // Interrupción De Rutina ISR(TIMER1_COMPA_vect) { bool LEDChange, PressedZ; // Consulta Switch PressedZ = digitalRead(BUTTON_CHANGEANIMACIÓN); if ((PressedZ == LOW) and (ButtonAPress == false)) { ButtonAPress = true; } TCNT1 = 0; // Iniciar la ficha con 0 } // Interrupción final // begin Program void setup() { strip.begin(); strip.show(); // Initialize all pixels to 'off' pinMode(BUTTON_CHANGEANIMACIÓN, INPUT_PULUP); randomSeed(analogRead(0)); noInterrupts(); // Desactivar temporalmente todos los interruptores TCCR1A = 0x00; TCCR1B = 0x02; TCNT1 = 0; // Iniciar la ficha con 0 OCR1A = 33353; // Output Compare Register TIMSK1 |= (1 << OCIE1A); // Temporizador Compare interface interrupts(); // activar todos los interruptores Serial.begin(9600); Serial.rubor(); } // Funciones auxiliares void HSBToRGB( sin firma int inHue, sin firma int reclusión, sin firma int inBrightness, sin firma int *oR, sin firma int *oG, sin firma int *oB ) { if (reclusión == 0) { // acromatic (grey) *oR = *oG = *oB = inBrightness; } else { sin firma int scaledHue = (inHue * 6); sin firma int sector = scaledHue >> 8; // sector 0 to 5 around the color wheel sin firma int vector offsético = scaledHue - (sector << 8); // position within the sector sin firma int p = (inBrightness * ( 255 - reclusión )) >> 8; sin firma int q = (inBrightness * ( 255 - ((reclusión * vector offsético) >> 8) )) >> 8; sin firma int t = (inBrightness * ( 255 - ((reclusión * ( 255 - vector offsético )) >> 8) )) >> 8; switch ( sector ) { case 0: *oR = inBrightness; *oG = t; *oB = p; break; case 1: *oR = q; *oG = inBrightness; *oB = p; break; case 2: *oR = p; *oG = inBrightness; *oB = t; break; case 3: *oR = p; *oG = q; *oB = inBrightness; break; case 4: *oR = t; *oG = p; *oB = inBrightness; break; default: // case 5: *oR = inBrightness; *oG = p; *oB = q; break; } } } void CheckConfigButtons () // Interruptroutinas { bool PressedZ; if (ButtonAPress == true) { if (Animación de inmersión < MaxAninmationsAvail ) { Animación de inmersión++; Serial.println ("phase1"); Serial.println (Animación de inmersión); // Animación = 1; } else { Animación de inmersión = 0; } delay(700); ButtonAPress = false; } } void Control de animación () { int Animación = 0; if (Estado de getonoff != Estado oldonoff) { Estado oldonoff = Estado de getonoff; if (Estado de getonoff) { Animación de inmersión = 1; } else { Animación de inmersión = 0; } } } // Main Loop ----------------------------------------------------------------------- void loop() { Control de animación(); RunAnimations(); CheckConfigButtons(); } // Main Loop ----------------------------------------------------------------------- A Finales De // Introducciones void Intro_CountUp (bytes r, bytes g, bytes b, int delaytime, bool a ti) { if (a ti) { for ( int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, r, g, b); //Calulate RGB Values for Pixel strip.show(); // Show results :) delay(delaytime); } } else { for ( int i = 0; i < strip.numPixels() + 1; i++) { bytes pos = strip.numPixels() - i; strip.setPixelColor(pos, r, g, b); //Calulate RGB Values for Pixel strip.show(); // Show results :) delay(delaytime); } } } void Intro_RaiseRainbow(bool caso de riesgo) { brightness = 255; int Rainbowcolor = 0; if (caso de riesgo) { for (int i = 0; i < strip.numPixels(); i++) { hue = mapa(i + Rainbowcolor, anglemina, 60, hueRedLow, hueRedHigh); // Set Color HSBToRGB(hue, saturation, brightness, &r, &g, &b); // Set Color strip.setPixelColor(i, r, g, b); //Calulate RGB Values for Pixel strip.show(); delay(40); } } else { for (int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 0, 0); strip.show(); delay(40); } } } // Outtros // Animations void Ani_AllOff () { for ( int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 0, 0); // all off } strip.show(); } void Ani_AllOn (bytes r, bytes g, bytes b) { for ( int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, r, g, b); // all on } strip.show(); } void Ani_Starshower () { int array[10] ; for ( int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 0, 15); // all blue based } for (int i = 0; i < 10; i++) { int selected = random(strip.numPixels()); strip.setPixelColor(selected, 255, 255, 255); // White } strip.show(); delay(100); for ( int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, 0, 0, 15); // all blue based } strip.show(); delay(500); } void Ani_Rainbow(bytes delaytime) { brightness = 100; int Rainbowcolor = 0; do { for (int i = 0; i < strip.numPixels(); i++) { hue = mapa(i + Rainbowcolor, anglemina, 60, hueRedLow, hueRedHigh); HSBToRGB(hue, saturation, brightness, &r, &g, &b); strip.setPixelColor(i, r, g, b); } strip.show(); // Show results :) delay(delaytime); Rainbowcolor++ ; } while (Rainbowcolor < 61); } void Ani_Two_Color () { // byte Segments = PIXEL_COUNT / 5; bytes Divider = random (1, 10); bool color; int x = 1; b = 0; for (int s = 0; s > -1; s = s + x) { color = false; for ( int i = 0; i < strip.numPixels(); i++) { a = i / Divider; if (!(a == b)) { b = a; color = !color; } if (color) { strip.setPixelColor(i, 0, s, 0); // Verde } if (!(color)) { strip.setPixelColor(i, s, 0, 0); // rojo } } strip.show(); if (s == 255) { x = -1; delay(2000); } delay(10); } strip.show(); } void Ani_Halloween() { a = -10; for (int i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, random(1, 254), random(1, 204), random(1, 254)); e = e + a; f = f + a; if (f <= 0) { a = +10; } if (f >= 60) { a = -10; } } strip.show(); // Show results :) delay(300); } void FadeColor () { bytes brightness = 0; bytes saturation = 0; int Colori = 49 ; do { for (int i = 0; i < strip.numPixels(); i++) { // wdt_reset(); HSBToRGB(Colori, saturation, brightness, &r, &g, &b); // Set Color strip.setPixelColor(i, r, g, b); //Calulate RGB Values for Pixel } brightness ++; strip.show(); // Show results :) delay(40); } while (brightness < 50); } void RunAnimations() { if (!(Animación de inmersión == Isanimación)) { PlayOutro = true; Animación de cambio = true; } switch (Isanimación) { case 0: // all LedsOFF if (PlayIntro) { PlayIntro = false; RunOnce = true; } if ((!(PlayIntro)) && (!(PlayOutro))) { if (RunOnce) { Ani_AllOff (); } RunOnce = false; } if (PlayOutro) { PlayOutro = false; PlayIntro = true; RunOnce = true; Isanimación = Animación de inmersión; } break; case 1: if (PlayIntro) { Intro_CountUp (0, 0, 15, 100, true); PlayIntro = false; } if ((!(PlayIntro)) && (!(PlayOutro))) { Ani_Starshower(); } if (PlayOutro) { Intro_CountUp (0, 0, 0, 100, false); PlayOutro = false; PlayIntro = true; Isanimación = Animación de inmersión; } break; case 2: if (PlayIntro) { Intro_RaiseRainbow(true); PlayIntro = false; } if ((!(PlayIntro)) && (!(PlayOutro))) { Ani_Rainbow(20); } if (PlayOutro) { Intro_RaiseRainbow(false); PlayOutro = false; PlayIntro = true; Isanimación = Animación de inmersión; } break; case 3: if (PlayIntro) { Ani_AllOff (); PlayIntro = false; } if ((!(PlayIntro)) && (!(PlayOutro))) { Ani_Two_Color (); // Ani_Two_Color (byte hue, byte tail, byte brightness,byte delaytime) } if (PlayOutro) { PlayOutro = false; PlayIntro = true; Isanimación = Animación de inmersión; } break; case 4: if (PlayIntro) { Ani_AllOff (); PlayIntro = false; } if ((!(PlayIntro)) && (!(PlayOutro))) { Ani_Halloween (); // } if (PlayOutro) { PlayOutro = false; PlayIntro = true; Isanimación = Animación de inmersión; } break; } }
Funcionamiento: mediante una breve presión en el teclado se pueden activar las siguientes animaciones una tras otra. Un
- Starshower
- Rainbow
- Motion of Two color
- Halloween
Tenga en cuenta que las animaciones no pasan inmediatamente a la siguiente animación, sino que siempre terminan la secuencia actual antes de iniciar la siguiente animación.
También en este caso, por supuesto, están invitados a programar más secuencias de animación en caso de que los cuatro no sean suficientes. El código indica el enfoque de principio.
En la siguiente y última parte de la serie, haremos que nuestros lentes reaccionen a los "estímulos ambientales".
Que te diviertas reconstruyendo y hasta la próxima vez.
2 comentarios
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?