Close

adresovatelný led pásek, změna efektů

Úvodní stránka Fórum Vaše projekty Arduino adresovatelný led pásek, změna efektů

Aktuálně je na stránce zobrazeno 11 příspěvků - 1. až 11. (celkem z 11)
  • Autor
    Příspěvky
  • #10481
    Hint
    Účastník

    Zdravím, chtěl bych vás požádat o radu, v programovaní jsem úplný amatér a zatím funguji na principu, najdi, zkopíruj a uprav podle potřeby. Mám adresovatelný led pásek který bych rád ovládal přes arduino, našel jsem pár efektu a ty jsem vlozil do jednoho projektu a mezi nimi bych chtěl přepínat, zatím pomocí seriové linky z pc a přes IR přijímač.
    problém mám v tom, že když chci aby se efekt opakoval, použil jsem příkaz while a podminku příjem po seriové lince, která smyčku vypne, ale v top případě nejde přepínat programy pomocí dalkoveho IR ovladače. Nevím jak udělat aby se efekty pořád opakovaly, ale já je mohl přepínat více způsoby.
    Děkuji za případné rady

    
    #include <Adafruit_NeoPixel.h>
    #include"IRremote2.h"
    
    #define pinIN 4
    #define PIN   6
    // Parametr 1 = počet pixelů (LED diod) na pásek
    // Parametr 2 = číslo PINu Arduina
    // Parametr 3 = pixel type flags, add together as needed:
    // NEO_KHZ800  800 KHz kmitočet pro pásky s WS2812 LED diodami)
    // NEO_GRB  Pixely jsou zasílány ve formátu GRB 
    Adafruit_NeoPixel pixels = Adafruit_NeoPixel(36, 6, NEO_GRB + NEO_KHZ800);
    IRrecv dalkoveOvl(pinIN);
    decode_results vysledek;
    char pozice;
    int delayval = 30; // 500ms
    int delayval1 = 10;
    int delayval2 = 10;
    
    void setup() {
      pixels.begin();
      Serial.begin(9600);
      pixels.show();
      int delayval = 300;
      delay(250);
      dalkoveOvl.enableIRIn();
    }
    
    void loop()
    {
      if (dalkoveOvl.decode(&vysledek)) 
      {
        detekceKlaves();
        dalkoveOvl.resume();
      } 
      if (Serial.available() > 0)
      {
      pozice = Serial.read();
      switch (pozice)
        {
        case 'p': 
        knightrider();
        break;
      
        case 'o': 
        kazdadruha();
        break;
      
        case 'i': 
        beziciled();
        break;
      
        case 'u': 
        duha2();
        break;
        
        case 'z': 
        menicibarvy();
        break;
    
        
        case 't': 
        rychleled();
        break;
    
        
        case 'r': 
         
        break;
        
      
        case 'e': 
        
        break;
       
        
        case 'w': 
         
        break;
    
        case 'q': 
         
        break;
            
        }
      }
    }
    
    void knightrider() 
    {
     while (Serial.read() < 0)
     {
      for(int i=0;i<36;i++)
        {
        pixels.setPixelColor(i, pixels.Color(20,0,0)); 
        pixels.setPixelColor(i+1, pixels.Color(50,0,0)); 
        pixels.setPixelColor(i+2, pixels.Color(100,0,0)); 
        pixels.setPixelColor(i+3, pixels.Color(250,0,0)); 
        pixels.setPixelColor(i+4, pixels.Color(100,0,0)); 
        pixels.setPixelColor(i+5, pixels.Color(50,0,0)); 
        pixels.setPixelColor(i+6, pixels.Color(20,0,0)); 
           
        pixels.show(); 
        delay(delayval); 
        pixels.setPixelColor(i, pixels.Color(0,0,0)); 
        }
       for(int i=35;i>0;i--)
        {
        pixels.setPixelColor(i, pixels.Color(20,0,0)); 
        pixels.setPixelColor(i-1, pixels.Color(50,0,0)); 
        pixels.setPixelColor(i-2, pixels.Color(100,0,0)); 
        pixels.setPixelColor(i-3, pixels.Color(250,0,0)); 
        pixels.setPixelColor(i-4, pixels.Color(100,0,0)); 
        pixels.setPixelColor(i-5, pixels.Color(50,0,0)); 
        pixels.setPixelColor(i-6, pixels.Color(20,0,0)); 
        
        pixels.show(); 
        delay(delayval); 
        pixels.setPixelColor(i, pixels.Color(0,0,0)); 
       }
      }
    }
      
    void kazdadruha() 
    
    {
      while (Serial.read() < 0)
     {
     // bílá, červená, modrá
     utikej(pixels.Color(127, 127, 127), 50); // Bílá
     utikej(pixels.Color(127,   0,   0), 50); // Červená
     utikej(pixels.Color(  0,   0, 127), 50); // Modrá
     }
    }
    //Běžící bílá, červená, modrá
    void utikej(uint32_t c, uint8_t wait)
    {
      for (int j=0; j<10; j++) 
      {  
        for (int q=0; q < 3; q++) 
        {
          for (int i=0; i < pixels.numPixels(); i=i+3) 
          {
            pixels.setPixelColor(i+q, c);    //zapínání všech pixelů najednou
          }
          pixels.show();
         
          delay(40);
         
          for (int i=0; i < pixels.numPixels(); i=i+3) 
          {
            pixels.setPixelColor(i+q, 0);        //vypínání všech pixelů najednou
          }
        }
      }
    }
    
    void beziciled()
    {
     while (Serial.read() < 0)
    {
       
      for(int i=0;i<10;i++){
        pixels.setPixelColor(0+i, pixels.Color(100,0,0));
        pixels.setPixelColor(10+i, pixels.Color(100,0,0)); 
        pixels.setPixelColor(20+i, pixels.Color(100,0,0));
        pixels.setPixelColor(30+i, pixels.Color(100,0,0));
        pixels.setPixelColor(40+i, pixels.Color(100,0,0));
        pixels.setPixelColor(50+i, pixels.Color(100,0,0));
         
        pixels.show(); 
          delay(delayval1);
        pixels.setPixelColor(0+i, pixels.Color(0,0,0));
        pixels.setPixelColor(10+i, pixels.Color(0,0,0)); 
        pixels.setPixelColor(20+i, pixels.Color(0,0,0));
        pixels.setPixelColor(30+i, pixels.Color(0,0,0));
        pixels.setPixelColor(40+i, pixels.Color(0,0,0));
        pixels.setPixelColor(50+i, pixels.Color(0,0,0));
       pixels.show(); 
          delay(delayval1);
         
      }  
       
    }
    }
    
    void duha2(){
       while (Serial.read() < 0)
    {
    
      duha(20);   //zadáním čísla do závorky udáváme rychlost změny barev
    
    }
    }
    void duha(uint8_t wait) {
      uint16_t i, j;
    
      for(j=0; j<256; j++) {
        for(i=0; i<pixels.numPixels(); i++) {
          pixels.setPixelColor(i, Wheel((i+j) & 255));
        }
        pixels.show();
        delay(wait);             
      }
    }
    
    // Barvy přecházejí v pořadí R - G - B a zpět k R.
    uint32_t Wheel(byte WheelPos) {
      if(WheelPos < 85) {
       return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
      } else if(WheelPos < 170) {
       WheelPos -= 85;
       return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
      } else {
       WheelPos -= 170;
       return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
    }
    
    void menicibarvy() 
    {
       while (Serial.read() < 0)
    
      {
      
      vymaluj(pixels.Color(255, 0, 0), 50); // Červená
      vymaluj(pixels.Color(0, 255, 0), 50); // Zelená
      vymaluj(pixels.Color(0, 0, 255), 50); // Modrá
      }
    }
    // Vyplní postupně pásek základními barvami
    void vymaluj(uint32_t c, uint8_t wait) 
    {
      for(uint16_t i=0; i<pixels.numPixels(); i++) 
      {
          pixels.setPixelColor(i, c);
          pixels.show();
          delay(5);
      }
    
    }
    
    void rychleled()
    {
      while (Serial.read() < 0)
     {
      // První pixel na LED pásku má adresu "0", druhý pixel "1" atd. 
      // 1m pásku který má 60pixelů (LED diod) se adresuje 0-59
      
     for(int i=0;i<36;i++)
      {
        pixels.setPixelColor(i, pixels.Color(200,0,0)); 
        pixels.show(); 
        delay(delayval2); 
        pixels.setPixelColor(i, pixels.Color(0,0,0)); 
      }
    
     }
    }
    void detekceKlaves() {
      switch(vysledek.value) {
        // u každé stisknuté klávesy se vždy vypíše
        // její název po sériové lince
        case 0xFFA25D:  
          Serial.println("Stisknuto CH-");
          break;
        case 0xFF629D:  
          Serial.println("Stisknuto CH");
          break;
        case 0xFFE21D:  
          Serial.println("Stisknuto CH+");
          break;
        case 0xFF22DD:  
          Serial.println("Stisknuto PREV");
          break;
        case 0xFF02FD:  
          Serial.println("Stisknuto NEXT");
          break;
        case 0xFFC23D:  
          Serial.println("Stisknuto PLAY/PAUSE");
          break;
        case 0xFFE01F:  
          Serial.println("Stisknuto VOL-");
          break;
        case 0xFFA857:  
          Serial.println("Stisknuto VOL+");
          break;
        case 0xFF906F:  
          Serial.println("Stisknuto EQ");
          break;
        case 0xFF6897:  
          Serial.println("Stisknuto 0");
          break;
        case 0xFF9867:  
          Serial.println("Stisknuto 100+");
          break;
        case 0xFFB04F:  
          Serial.println("Stisknuto 200+");
          break;
        case 0xFF30CF:  
          Serial.println("Stisknuto 1");
          knightrider();
          break;
        case 0xFF18E7:  
          Serial.println("Stisknuto 2");
          beziciled();
          kazdadruha();
          break;
        case 0xFF7A85:  
          Serial.println("Stisknuto 3");
          duha2();
          break;
        case 0xFF10EF:  
          Serial.println("Stisknuto 4");
          menicibarvy();
          break;
        case 0xFF38C7:  
          Serial.println("Stisknuto 5");
          rychleled();
          break;
        case 0xFF5AA5:  
          Serial.println("Stisknuto 6");
          break;
        case 0xFF42BD:  
          Serial.println("Stisknuto 7");
          break;
        case 0xFF4AB5:  
          Serial.println("Stisknuto 8");
          break;
        case 0xFF52AD:  
          Serial.println("Stisknuto 9");
          break;
        default: 
          Serial.println("Stisknuta jina klavesa");
      }
      // pauza pro přehlednější výpis
      delay(500);
    }
    
    #10483
    Vojtěch Vosáhlo
    Účastník

    Mělo by stačit přidat k přerušení seriovou linkou i přerušení IR příjmem. Na začátku kódu máte v podmínce if toto: „dalkoveOvl.decode(&vysledek)“
    Vzhledem k tomu že je v podmínce, nejspíše vrátí 1/true/pravda pokud něco přijme a zvládne dekódovat a 0/false/nepravda pokud nic nepřijme nebo nedekóduje.
    Do vašeho while by tedy stačilo přidat logický operátor OR v arduinu jako ||. Ten vám dá 1 pokud alespoň jedna vstupní hodnota je 1. Smyčka by tedy vypadala asi takto while(!(Serial.available() || dalkoveOvl.decode(&vysledek)))...
    Serial.available() se podívá jestli je něco dostupného na sériové lince a dalkoveOvl.decode() zjistí zda něco přijímáme. Pokud nic z tohoto neplatí dostaneme 0 která je vykřičníkem znegovaná na 1 a smyčka běží. Pokud bude ale jedna z možností 1, smyčka se zastaví.

    Mimo tohle by se dal kód ještě různě optimalizovat ale o tom kdyžtak jindy 😉

    #10484
    Hint
    Účastník

    Díky moc, hned jsem vaši radu vyzkoušel a opravdu teď mohu vypnout smyčku i pomoci ovladače a sepnutí nového efektu přes seriovou linku pracuje ještě lépe než předtím, bohužel ale nevím proč, přestal program přijímat sepnutí smyček efektů, pouze ukončí smyčku. Ovladačem nejde spustit efekt ani po resetu arduina, když ještě nic neběží.
    Omlouvám se snad jsem to napsal srozumitelně.

    #10485
    Vojtěch Vosáhlo
    Účastník

    Zkuste za while vložit dalkoveOvl.resume(); tzn bude to vypadat asi takto: `void nejakyefekt(){
    while(neco){
    }
    dalkoveOvl.resume();
    }
    `
    Pokud to nepojede tak se ozvěte. Zkuste taky poslat odkaz na knihovnu kterou přesně máte, jestli existuje dokumentace, bude to jednoduší.

    #10489
    Hint
    Účastník

    bohužel se mi nepovedlo to nějak rozběhat, ovladač pouze vypne probýhající smyčku, ale nespustí žádnou a přitom po seriové lince vypisuje stisknuté klavesy.

    #10493
    Hint
    Účastník

    omlouvám se zde přikládám zdroje knihovny
    knihovna ledpasku

    github knihovna ledpasku

    knihovnu na IR ovladač jsem stahl tady
    IR remote
    možná by pomohlo tohle
    IR remote wiki

    #10498
    Vojtěch Vosáhlo
    Účastník

    Ozvu se zase zítra, možná si najde čas i někdo z ostatních a dřív, uvidíte. Já bych asi doporučil jednu věc. Udělejte čistý nový projekt pouze s nejnutnějšími funkcemi na přijímání z IR a Serial a spuštění nějaké jednoduché funkce. Omezte to na co nejmenčí kód, klidně jen něco jako po stisknutí ON na ovladači nebo poslání 1 na port rosviť ledky. Na tomhle zkusíme jak by se mělo postupovat s přerušením smyčky a bude to přehlednější než ten kód co máme teď. Zmenšením kódu taky omezíme prostor na chybu. Držím palce.

    #10499
    Hint
    Účastník

    Děkuji moc za pomoc a váš čas. zkusím něco sepsat.

    #10508
    Vojtěch Vosáhlo
    Účastník

    Zkuste něco takového jako zjednodušený kód. Mělo by to blikat s prvním pixelem pokud zmáčknete CH- nebo pošlete 1. Pokud přijde něco jiného, smyčka by se měla přerušit.

    #include <Adafruit_NeoPixel.h>
    #include"IRremote2.h"
    
    #define pinIN 4
    #define PIN   6
    // Parametr 1 = počet pixelů (LED diod) na pásek
    // Parametr 2 = číslo PINu Arduina
    // Parametr 3 = pixel type flags, add together as needed:
    // NEO_KHZ800  800 KHz kmitočet pro pásky s WS2812 LED diodami)
    // NEO_GRB  Pixely jsou zasílány ve formátu GRB 
    Adafruit_NeoPixel pixels = Adafruit_NeoPixel(36, 6, NEO_GRB + NEO_KHZ800);
    IRrecv dalkoveOvl(pinIN);
    decode_results vysledek;
    char pozice;
    
    void setup() {
      pixels.begin();
      Serial.begin(9600);
      pixels.show();
      int delayval = 300;
      delay(250);
      dalkoveOvl.enableIRIn();
    }
    
    void loop()
    {
      if (dalkoveOvl.decode(&vysledek)) 
      {
        detekceKlaves();
        dalkoveOvl.resume();
      } 
      if (Serial.available() > 0)
      {
      pozice = Serial.read();
        if(pozice == 1) blikejLed();
      }
    }
    
    void detekceKlaves() {
      if(vysledek.value == 0xFFA25D) {
    
          Serial.println("Stisknuto CH-");
          blikejLed();
    
      // pauza pro přehlednější výpis
      delay(500);
    }
    
    void blikejLed(){
     dalkoveOvl.resume();
    
      while(!(Serial.available() || dalkoveOvl.decode(&vysledek))){
    
        pixels.setPixelColor(1, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(1, pixels.Color(0,0,0));
        pixels.show();
        delay(1000);
    
      }
     
    }
    
    
    #10509
    Hint
    Účastník

    Tak po menší úpravě vašeho návrhu už zřejmě funguje jak má, přepíná po sériové lince i přes IR. Pokud to tedy chápu správně, místo použití příkazu switch mám použít vypsaní všech možností podmínkou if
    a zárověň mě napadlo zda jde ještě nějak zapsat podmínka, když nepřijme data která má v podmínkach, neudělá nic a bude pokračovat v předchozím efektu. Uvědomil jsem si totiž že při ovladaní TV bude IR ovlivňovat i arduino přijímač a vypínat efekty.

    
    #include <Adafruit_NeoPixel.h>
    #include"IRremote2.h"
    
    #define pinIN 4
    #define PIN   6
    // Parametr 1 = počet pixelů (LED diod) na pásek
    // Parametr 2 = číslo PINu Arduina
    // Parametr 3 = pixel type flags, add together as needed:
    // NEO_KHZ800  800 KHz kmitočet pro pásky s WS2812 LED diodami)
    // NEO_GRB  Pixely jsou zasílány ve formátu GRB 
    Adafruit_NeoPixel pixels = Adafruit_NeoPixel(36, 6, NEO_GRB + NEO_KHZ800);
    IRrecv dalkoveOvl(pinIN);
    decode_results vysledek;
    char pozice;
    
    void setup() {
      pixels.begin();
      Serial.begin(9600);
      pixels.show();
      delay(250);
      dalkoveOvl.enableIRIn();
    }
    
    void loop()
    {
      if (dalkoveOvl.decode(&vysledek)) 
      {
        detekceKlaves();
        dalkoveOvl.resume();
      }
      if (Serial.available() > 0)
      {
        pozice = Serial.read();
        if(pozice == '1') blika();
        if(pozice == '2') blika1();
      }
    }
    
    void detekceKlaves() 
    {
      if(vysledek.value == 0xFFA25D) 
      {
    
          Serial.println("Stisknuto CH-");
          blika();
    
      // pauza pro přehlednější výpis
      delay(500);
      }
      if(vysledek.value == 0xFFE21D) 
      {
    
          Serial.println("Stisknuto CH-");
          blika1();
    
      // pauza pro přehlednější výpis
      delay(500);
      }
      
    }
    
    void blika()
    {
     dalkoveOvl.resume();
    
      while(!(Serial.available() || dalkoveOvl.decode(&vysledek)))
      {
        pixels.setPixelColor(6, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(6, pixels.Color(0,0,0));
        pixels.show();
        delay(200);    
        pixels.setPixelColor(6, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(6, pixels.Color(0,0,0));
        pixels.show();
        delay(200);
      }
    }
    
    void blika1()
    {
     dalkoveOvl.resume();
    
      while(!(Serial.available() || dalkoveOvl.decode(&vysledek)))
      {
        pixels.setPixelColor(16, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(16, pixels.Color(0,0,0));
        pixels.show();
        delay(200);    
        pixels.setPixelColor(16, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(16, pixels.Color(0,0,0));
        pixels.show();
        delay(200);
      }
    }
    
    #10513
    Vojtěch Vosáhlo
    Účastník

    Pokud to tedy chápu správně, místo použití příkazu switch mám použít vypsaní všech možností podmínkou if

    To úplně neříkám. Já použil if pouze protože jsem volal jen jednu funkci, jen kvůli jednoduchosti. Vy můžete nadále používat switch case. Pokud byste chtěl mít kód optimalizovaný na max, dá se použít něco takového:

    
    #include <Adafruit_NeoPixel.h>
    #include"IRremote2.h"
    
    ///Deklarace pouzitych funci
    void funkce1();
    void funkce2();
    
    #define pinIN 4
    #define PIN   6
    // Parametr 1 = počet pixelů (LED diod) na pásek
    // Parametr 2 = číslo PINu Arduina
    // Parametr 3 = pixel type flags, add together as needed:
    // NEO_KHZ800  800 KHz kmitočet pro pásky s WS2812 LED diodami)
    // NEO_GRB  Pixely jsou zasílány ve formátu GRB 
    Adafruit_NeoPixel pixels = Adafruit_NeoPixel(36, 6, NEO_GRB + NEO_KHZ800);
    IRrecv dalkoveOvl(pinIN);
    decode_results vysledek;
    char pozice;
    
    typedef void (* Caller)();
    Caller funkce[] = {&funkce1, &funkce2}; ///FUNKCE KTERE CHCETE VOLAT
    char serial_prikazy[] = {'1', '2'}; ///PRIKAZY KORESPONDUJICI S FUNKCEMI tzn. 1 vola funkce1
    int32_t ir_prikazy[] = {0x00FFA25D, 0xFFE21D};
    char data;
    
    void setup(){
      pixels.begin();
      Serial.begin(9600);
      pixels.show();
      delay(250);
      dalkoveOvl.enableIRIn();
    }
    
    ///////////////////////////////////////////////////////////////////////
    //////////////FUNKCE KTERE BUDOU VOLANE PRIKAZY //////////////////////
    void funkce1(){
      dalkoveOvl.resume();
    
      while(!(Serial.available() || dalkoveOvl.decode(&vysledek)))
      {
        pixels.setPixelColor(6, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(6, pixels.Color(0,0,0));
        pixels.show();
        delay(200);    
        pixels.setPixelColor(6, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(6, pixels.Color(0,0,0));
        pixels.show();
        delay(200);
      }
    }
    
    void funkce2(){
      dalkoveOvl.resume();
    
      while(!(Serial.available() || dalkoveOvl.decode(&vysledek)))
      {
        pixels.setPixelColor(16, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(16, pixels.Color(0,0,0));
        pixels.show();
        delay(200);    
        pixels.setPixelColor(16, pixels.Color(255,255,255));
        pixels.show();
        delay(1000);
        pixels.setPixelColor(16, pixels.Color(0,0,0));
        pixels.show();
        delay(200);
      }
    }
    
    /////////////////////////////////////////////////////////////////////
    
    void loop(){
      
        if(Serial.available() || dalkoveOvl.decode(&vysledek)){
          
        data = Serial.read();
        
            for(int i = 0; i < sizeof(funkce); i++){
                if(data == serial_prikazy[i] || vysledek.value == ir_prikazy[i]){
                  
                    funkce[i]();
                  
                  }
              
              }
              
        }
    }
    
    

    Prakticky si na začátku zapíšete všechny různé funkce a pak už se jen volají podle příkazů. Je to kratší a nemusíte používat switch case.
    Nejdůležitější je deklarovat si na začátku všechny „blikací a svítící“ funkce asi takto

    void funkce1();
    void funkce2();

    Těch tam může být kolik chce.
    Poté si zapíšete příkazy které funkce spouští jako tady: `Caller funkce[] = {&funkce1, &funkce2}; ///FUNKCE KTERE CHCETE VOLAT
    char serial_prikazy[] = {‚1‘, ‚2‘}; ///PRIKAZY KORESPONDUJICI S FUNKCEMI tzn. 1 vola funkce1
    int32_t ir_prikazy[] = {0x00FFA25D, 0xFFE21D};`

    V Caller funkce[] jsou zapsány samotné funkce které se budou volat, zapisujete je jako &nazevfunkce. V serial_prikazy[] jsou sériové příkazy které spouští dané funkce tzn. příkaz na 1. pozici spustí funkci na 1. pozici v tom Caller funkce[]. V poli ir_prikazy[] jsou opět korespondující příkazy které spouští funkce. Musí být zapsány jako 0x00vasirkod. Ten kód co jsem přihodil by měl fungovat jako ten váš se switch case nebo if. Schválně zkuste a uvidíme.

    Obnovení předešlé animace kdyžtak vyřešíme jestli tohle bude fungovat.

Aktuálně je na stránce zobrazeno 11 příspěvků - 1. až 11. (celkem z 11)
  • Pro reakci na toto téma se musíte přihlásit.