“Voodoo” maska s Neopixel RGB LED

Dneska se pochlubím s takovým konstrukčně lehce jednodušším dílkem. Kamarád mě poprosil, jestli bych mu nezabudovala barevná světýlka do jeho fejkové domorodé africké masky. Po kratší konverzaci o tom, co je možné a co ne jsem souhlasila, a výsledek můžete vidět tady dole 😀

Základ osvětlení tvoří 4 Neopixel RGB LED moduly s čipem WS2811 osazené na malých destičkách pro lepší montáž, které ovládá modul Arduino Nano. To také přijímá a interpretuje povely z infra ovladače přijaté skrze přijímač WS1838. Arduino dále pomocí fotorezistoru měří intenzitu osvětlení v místnosti, což slouží k tomu, aby se maska ve tmě sama zhasla a nerušila tak při spaní. Tuto funkci lze samozřejmě ovladačem vypnout. Jako IR ovladač posloužil generický typ zakoupený na Aliexpress.

Myslím, že zapojení je celkem jasné ze schématu. Tohle je tak jednoduché, že jsem to ani nekreslila v Eagle. K napájení slouží 5 AA článků o celkovém napětí 7,5 V. IR přijímač je zapojený na GPIO pin 2, ovládací pin Neopixel modulu na pin 3 a výstup fotorezistoru na pin A0. Mezi Neopixel a Arduino je vložen rezistor s odporem 470 ohmů, který pomáhá předcházet napěťovým špičkám, jenž by mohly zničit první Neopixel modul.
Fotorezistor o odporu 100 kiloohmů za plného světla  je zapojený v odporovém děliči s rezistorem 1 megaohm tak, aby výstupní napětí děliče se stoupající intenzitou osvětlení klesalo. Je to proto, že průběh závislosti odporu na intenzitě dopadajícího světla není u fotorezistoru lineární, a tato konfigurace lépe umožňuje lépe detekovat moment, kdy se setmí.
UPOZORNĚNÍ: IR ovladač ve schématu není ten, který jsem nakonec použila. Ten můj ma jiná tlačítka a vysílá jiné povely. Odkaz na mnou použitý ovladač je na konci článku v seznamu součástek.

Mechanická konstrukce také celkem zřejmá, menší výzvou bylo umístit vše do zádlabu v masce tak, aby při pověšení na zeď neodstávala. Modul Arduino Nano a rezistory jsou připájeny na univerzální destičce plošných spojů. Fotorezistor je zapuštěný nahoře. Povelový přijímač je vložen do úst masky. Bateriový držák je lehce atypický na 5 AA článků, ale dá se běžně koupit. Všechny použité vodiče jsou lanka o průřezu 0,22 mm2.

Níže naleznete kód pro Arduino. Barevné programy jsou víceméně základní, žádná divočina. Kamarád má epilepsii, takže nějaké blikání nebo tak nepřicházelo v úvahu. Celkově nejde o nic složitého, základem je dekódování IR povelů, mnohonásobný state machine pro každé tlačítko a pak pár podmínek. Žádný magic. Kód je komentovaný anglicky, protože prostě u programovaní myslím anglicky 😉

// Mask light v 0.8
// Creator: Gabriela Novotna / gabi@gabrielanovotna.cz / www.gabitech.cz
// This code is licensed under the Creative Commons 4.0 – Attribution – Non-Commercial – Share Alike license.

#include <Adafruit_NeoPixel.h>
#include <IRremote.h>

#define pinDI 3      // Set neopixel control pin
#define numLED 4     // Set number of LEDs
Adafruit_NeoPixel rgbWS = Adafruit_NeoPixel(numLED, pinDI, NEO_GRB + NEO_KHZ800);

int sen=A0;          // Light sensor
int recvIR = 2;      // IR sensor

int  light;          // Current light intensity level
int  limitL = 300;   // Limit for minimal light intensity level

int  Bright = 125;   // LED brightness
int  Speed = 2000;   // Color change speed (NOT used it this version)

const int timeoutDelay = 200;       // Timeout between button pushes

IRrecv irrecv(recvIR);              // Initialize IR receiver
decode_results results;             // Set variable for IR receiver results

int  buttonONPushCounter = 0;       // button MAIN counter
int  buttonONState = 0;             // state of MAIN button
int  prevButtonONState = 0;         // previous state of MAIN button

int  buttonLsenPushCounter = 0;     // button LIGHT sensor counter
int  buttonLsenState = 0;           // state of LIGHT sensor button
int  prevButtonLsenState = 0;       // previous state of LIGHT sensor button

long lastButtonTimeON;        // Last time MAIN button button was on
int stateON = 0;              // Current state of MAIN button state machine
int outON = 0;                // MAIN button state machine output

long lastButtonTimeLsen;      // Last time LIGHT sensor button button was on
int stateLsen = 0;            // Current state of LIGHT sensor button state machine
int outLsen = 0;              // LIGHT sensor button state machine output

long lastButtonTimeBrightUp;  // Last time BRIGHTNESS UP button was on
int stateBrightUp = 0;        // Current state of BRIGHTNESS UP button state machine
int outBrightUp = 0;          // BRIGHTNESS UP button state machine output

long lastButtonTimeBrightDn;  // Last time BRIGHTNESS DOWN button was on
int stateBrightDn = 0;        // Current state of BRIGHTNESS DOWN button state machine
int outBrightDn = 0;          // BRIGHTNESS DOWN button state machine output

long lastButtonTimeSpeedUp;   // Last time SPEED UP button was on
int stateSpeedUp = 0;         // Current state of SPEED UP button state machine
int outSpeedUp = 0;           // SPEED UP button state machine output

long lastButtonTimeSpeedDn;   // Last time SPEED DOWN button was on
int stateSpeedDn = 0;         // Current state of SPEED DOWN button state machine
int outSpeedDn = 0;           // SPEED DOWN button state machine output

long lastButtonTimeProg0;     // Last time PROGRAM 0 button was on
int stateProg0 = 0;           // Current state of PROGRAM 0 button state machine

long lastButtonTimeProg1;     // Last time PROGRAM 1 button was on
int stateProg1 = 0;           // Current state of PROGRAM 1 button state machine

long lastButtonTimeProg2;     // Last time PROGRAM 2 button was on
int stateProg2 = 0;           // Current state of PROGRAM 2 button state machine

long lastButtonTimeProg3;     // Last time PROGRAM 3 button was on
int stateProg3 = 0;           // Current state of PROGRAM 3 button state machine

long lastButtonTimeProg4;     // Last time PROGRAM 4 button was on
int stateProg4 = 0;           // Current state of PROGRAM 4 button state machine

long lastButtonTimeProg5;     // Last time PROGRAM 5 button was on
int stateProg5 = 0;           // Current state of PROGRAM 5 button state machine

long lastButtonTimeProg6;     // Last time PROGRAM 6 button was on
int stateProg6 = 0;           // Current state of PROGRAM 6 button state machine

long lastButtonTimeProg7;     // Last time PROGRAM 7 button was on
int stateProg7 = 0;           // Current state of PROGRAM 7 button state machine

long lastButtonTimeProg8;     // Last time PROGRAM 8 button was on
int stateProg8 = 0;           // Current state of PROGRAM 8 button state machine

long lastButtonTimeProg9;     // Last time PROGRAM 9 button was on
int stateProg9 = 0;           // Current state of PROGRAM 9 button state machine

int outColorProg = 0;         //Common state machine output for all color PROGRAM numbers

void setup(){
   
rgbWS.begin();             // Start WS2812
irrecv.enableIRIn();       // Start IR receiver
Serial.begin(9600);        // Serial comm for light level andjustment
 }

void loop() {
 
    Serial.println(analogRead(sen));
    
 IRdec();                  //Read and decode IR commands function
 
  
 if(outBrightUp == 1){         //Brightness UP by 10%
     if(Bright <= 225){
       Bright = Bright + 25;
       delay(timeoutDelay);      
     }
    }
 
 if(outBrightDn == 1){         //Brightness DOWN by 10%
     if(Bright >= 50){
      Bright = Bright 25;
      delay(timeoutDelay);            
     }
 }
 
 if(outSpeedUp == 1){          //Speed of color change UP by 200 ms
     if(Speed >= 400){
       Speed = Speed 200;
       delay(timeoutDelay);      
     }
    }
 
 if(outSpeedDn == 1){          //Speed of color change DOWN by 200 ms
     if(Speed <= 4800){
      Speed = Speed + 200;
      delay(timeoutDelay);            
     }
 }
 
 
 if(outLsen == 1){            //LIGHT sensor button state counter
   buttonLsenState = 1;
 }
   else {
     buttonLsenState =0;
 }
                 
 if(buttonLsenState != prevButtonLsenState) {   
     if(buttonLsenState == 0) {
     buttonLsenPushCounter++;
   }
  
 }
   prevButtonLsenState = buttonLsenState;
 
  if (buttonLsenPushCounter % 2 == 0) {      //Switch LIGHT sensor on or off
     light = analogRead(sen);
 }
   else {
       light = 1;
 }

 
 if(outON == 1){               //MAIN button state counter
   buttonONState = 1;
 }
   else {
     buttonONState =0;
 }
                 
 if(buttonONState != prevButtonONState) {   
     if(buttonONState == 0) {
     buttonONPushCounter++;
   }
  
 }
   prevButtonONState = buttonONState;
 
 if ((buttonONPushCounter % 2 == 0) || light > limitL) {   //Switch on/off function
   
           setRGB(0, 0, 0, 1);             //Set all LEDs to off
           setRGB(0, 0, 0, 2);
           setRGB(0, 0, 0, 3);
           setRGB(0, 0, 0, 4);
        delay(200);
     
   }
 
   else {
       Color();    //Select color program function
 }
}

void Color(){
  switch(outColorProg)   {
   
 case 1:    setRGB(255, 0, 0, 1);        //RED color program full brightness
            setRGB(255, 0, 0, 2);
            setRGB(255, 0, 0, 3);
            setRGB(255, 0, 0, 4);
   delay(200);               break;
   
 case 2:    setRGB(0, 255, 0, 1);        //GREEN color program full brightness
            setRGB(0, 255, 0, 2);
            setRGB(0, 255, 0, 3);
            setRGB(0, 255, 0, 4);    
   delay(200);               break;
   
 case 3:    setRGB(0, 0, 255, 1);        //BLUE color program full brightness
            setRGB(0, 0, 255, 2);
            setRGB(0, 0, 255, 3);
            setRGB(0, 0, 255, 4);    
   delay(200);               break;
   
 case 4:    setRGB(0,255,255, 1);        //CYAN color program full brightness
            setRGB(0,255,255, 2);
            setRGB(0,255,255, 3);
            setRGB(0,255,255, 4);    
   delay(200);               break;
        
 case 5:    setRGB(255,165,0, 1);        //ORANGE color program full brightness
            setRGB(255,165,0, 2);
            setRGB(255,165,0, 3);
            setRGB(255,165,0, 4);    
   delay(200);               break;
        
 case 6:    setRGB(255, 0, 255, 1);      //FUCHSIA color program full brightness
            setRGB(255, 0, 255, 2);
            setRGB(255, 0, 255, 3);
            setRGB(255, 0, 255, 4);    
   delay(200);               break;
        
 case 7:    setRGB(255, 0, 0, 1);        //COMBO RED+GREEN color program full brightness
            setRGB(255, 0, 0, 2);
            setRGB(0, 255, 0, 3);
            setRGB(0, 255, 0, 4);    
   delay(200);               break;
    
 case 8:    setRGB(0, 0, 255, 1);        //COMBO BLUE+GREEN color program full brightness
            setRGB(0, 0, 255, 2);
            setRGB(0, 255, 0, 3);
            setRGB(0, 255, 0, 4);    
   delay(200);               break;
    
 case 9:    setRGB(255,165,0,   1);      //COMBO ORANGE+FUCHSIA color program full brightness
            setRGB(255,165,0,   2);
            setRGB(255, 0, 255, 3);
            setRGB(255, 0, 255, 4);    
   delay(200);               break;
   
 case 0:    setRGB(255, 255, 255, 1);    //WHITE color full brightness
            setRGB(255, 255, 255, 2);
            setRGB(255, 255, 255, 3);
            setRGB(255, 255, 255, 4);    
   delay(200);               break;
    
   
 default: ;
  }
}

 
void IRdec(){
 
 if(irrecv.decode(&results)) {
   
   if(results.value == 0xFF38C7){  // MAIN ON ("OK" button)
     outON = 1;
       stateON = 1;
       lastButtonTimeON = millis();
    }
 else if (results.value == 0xFFFFFFFF && stateON == 1){
       lastButtonTimeON = millis();  // update the time-out
   }
   
   if(results.value == 0xFF6897){  // LIGHT sensor ON ("STAR" button)
     outLsen = 1;
       stateLsen = 1;
       lastButtonTimeLsen = millis();
    }
 else if (results.value == 0xFFFFFFFF && stateLsen == 1){
       lastButtonTimeLsen = millis();  // update the time-out
   }
   
  if(results.value == 0xFF18E7){ // BRIGHTNESS UP ON ("ARROW UP" button)
     outBrightUp = 1;
       stateBrightUp = 1;
       lastButtonTimeBrightUp = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateBrightUp == 1){
       lastButtonTimeBrightUp = millis();  // update the time-out
     }
   
  if(results.value == 0xFF4AB5){ // BRIGHTNESS DOWN ON ("ARROW DOWN" button)
     outBrightDn = 1;
       stateBrightDn = 1;
       lastButtonTimeBrightDn = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateBrightDn == 1){
       lastButtonTimeBrightDn = millis();  // update the time-out
   }
   
   if(results.value == 0xFF10EF){  // SPEED UP ON ("ARROW LEFT" button)
     outSpeedUp = 1;
       stateSpeedUp = 1;
       lastButtonTimeSpeedUp = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateSpeedUp == 1){
       lastButtonTimeSpeedUp = millis();  // update the time-out
     }
   
  if(results.value == 0xFF5AA5){ // SPEED DOWN ON ("ARROW RIGHT" button)
     outSpeedDn = 1;
       stateSpeedDn = 1;
       lastButtonTimeSpeedDn = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateSpeedDn == 1){
       lastButtonTimeSpeedDn = millis();  // update the time-out
   }
   
   
   if(results.value == 0xFF9867){  // COLOR PROGRAM 0 ("0" button)
     outColorProg = 0;
       stateProg0 = 1;
       lastButtonTimeProg0 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg0 == 1){
       lastButtonTimeProg0 = millis();  // update the time-out
   }
   
   if(results.value == 0xFFA25D){  // COLOR PROGRAM 1 ("1" button)
     outColorProg = 1;
       stateProg1 = 1;
       lastButtonTimeProg1 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg1 == 1){
       lastButtonTimeProg1 = millis();  // update the time-out
   }
   
   if(results.value == 0xFF629D){  // COLOR PROGRAM 2 ("2" button)
     outColorProg = 2;
       stateProg2 = 1;
       lastButtonTimeProg2 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg2 == 1){
       lastButtonTimeProg2 = millis();  // update the time-out
   }
  
   if(results.value == 0xFFE21D){  // COLOR PROGRAM 3 ("3" button)
     outColorProg = 3;
       stateProg3 = 1;
       lastButtonTimeProg3 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg3 == 1){
       lastButtonTimeProg3 = millis();  // update the time-out
   }
   
   if(results.value == 0xFF22DD){  // COLOR PROGRAM 4 ("4" button)
     outColorProg = 4;
       stateProg4 = 1;
       lastButtonTimeProg4 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg4 == 1){
       lastButtonTimeProg4 = millis();  // update the time-out
   }
     
 if(results.value == 0xFF02FD){  // COLOR PROGRAM 5 ("5" button)
     outColorProg = 5;
       stateProg5 = 1;
       lastButtonTimeProg5 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg5 == 1){
       lastButtonTimeProg5 = millis();  // update the time-out
   }
 
 if(results.value == 0xFFC23D){  // COLOR PROGRAM 6 ("6" button)
     outColorProg = 6;
       stateProg6 = 1;
       lastButtonTimeProg6 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg6 == 1){
       lastButtonTimeProg6 = millis();  // update the time-out
   }
 
 if(results.value == 0xFFE01F){  // COLOR PROGRAM 7 ("7" button)
     outColorProg = 7;
       stateProg7 = 1;
       lastButtonTimeProg7 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg7 == 1){
       lastButtonTimeProg7 = millis();  // update the time-out
   }
 
 if(results.value == 0xFFA857){  // COLOR PROGRAM 8 ("8" button)
     outColorProg = 8;
       stateProg8 = 1;
       lastButtonTimeProg8 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg8 == 1){
       lastButtonTimeProg8 = millis();  // update the time-out
   }
 
 if(results.value == 0xFF906F){  // COLOR PROGRAM 9 ("9" button)
     outColorProg = 9;
       stateProg9 = 1;
       lastButtonTimeProg9 = millis();
       }
 else if (results.value == 0xFFFFFFFF && stateProg9 == 1){
       lastButtonTimeProg9 = millis();  // update the time-out
   }
       
 irrecv.resume(); // Restart IR receiver
   
 }
 if((millis() lastButtonTimeON > timeoutDelay) && stateON == 1){ // MAIN button OFF
     outON = 0;
     stateON = 0;
 }
 
 if((millis() lastButtonTimeLsen > timeoutDelay) && stateLsen == 1){ // LIGHT sensor button OFF
     outLsen = 0;
     stateLsen = 0;
 }
 
 if((millis() lastButtonTimeBrightUp > timeoutDelay) && stateBrightUp == 1){ // BRIGHTNESS UP button OFF
     outBrightUp = 0;
     stateBrightUp = 0;
 }
 
 if((millis() lastButtonTimeBrightDn > timeoutDelay) && stateBrightDn == 1){ // BRIGHTNESS DOWN button OFF
     outBrightDn = 0;
     stateBrightDn = 0;
 }
 
 if((millis() lastButtonTimeSpeedUp > timeoutDelay) && stateSpeedUp == 1){ // SPEED UP button OFF
     outSpeedUp = 0;
     stateSpeedUp = 0;
 }
 
 if((millis() lastButtonTimeSpeedDn > timeoutDelay) && stateSpeedDn == 1){ // SPEED DOWN button OFF
     outSpeedDn = 0;
     stateSpeedDn = 0;
 }
}
  
   
void setRGB (byte r, byte g, byte b, int number) {
 uint32_t color;                               //Color variable
 color = rgbWS.Color(r, g, b);                 //Set color
 rgbWS.setPixelColor(number1, color);         //Refresh all LEDs with color
 rgbWS.setBrightness(Bright);                  //Set LEDs brightness
 rgbWS.show();
}

 

Seznam součástek: 

4 ks   Neopixel modul RGB LED 5050 s čipem wS2811 na destičce plošných spojů

1ks     Arduino Nano (můj modul je od RobotDyn)

1ks     IR ovladač TENSTAR ROBOT 

1ks     Přijímač IR povelů WS1838

1ks     Fotorezistor LDR5549

1ks     Rezistor 470 ohmů, 0204, 0,4 W

1ks     Rezistor 1 megaohm, 0204, 0,4 W

1ks     Univerzální destička plošných spojů rozteč 2,54 mm, pásové spoje tři body

1ks     Držák pro 5 ks AA článků Comf BH-351A

1ks     Páčkový spínač MTS-202

4ks     Držák kabelů na přišroubování Richco SRCC-2

Příspěvek byl publikován v rubrice Bastlení. Můžete si uložit jeho odkaz mezi své oblíbené záložky.

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *