adresovatelný led pásek, změna efektů
Úvodní stránka › Fórum › Vaše projekty › Arduino › adresovatelný led pásek, změna efektů
- Toto téma obsahuje celkem 10 odpovědí. Do diskuze (2 diskutující) se naposledy zapojil uživatel Vojtěch Vosáhlo a poslední změna proběhla před 7 roky a 10 měsíci.
-
AutorPříspěvky
-
15.2.2017 v 11:59 #10481HintÚč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); }
15.2.2017 v 15:06 #10483Vojtěch VosáhloÚčastníkMě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 taktowhile(!(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 😉
15.2.2017 v 15:44 #10484HintÚčastníkDí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ě.15.2.2017 v 16:10 #10485Vojtěch VosáhloÚčastníkZkuste 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ší.15.2.2017 v 17:05 #10489HintÚčastníkbohuž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.
15.2.2017 v 18:26 #10493HintÚčastníkomlouvám se zde přikládám zdroje knihovny
knihovna ledpaskuknihovnu na IR ovladač jsem stahl tady
IR remote
možná by pomohlo tohle
IR remote wiki15.2.2017 v 19:40 #10498Vojtěch VosáhloÚčastníkOzvu 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.
15.2.2017 v 20:00 #10499HintÚčastníkDěkuji moc za pomoc a váš čas. zkusím něco sepsat.
16.2.2017 v 17:53 #10508Vojtěch VosáhloÚčastníkZkuste 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); } }
16.2.2017 v 20:13 #10509HintÚčastníkTak 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); } }
17.2.2017 v 12:19 #10513Vojtěch VosáhloÚčastníkPokud 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 taktovoid 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.
-
AutorPříspěvky
- Pro reakci na toto téma se musíte přihlásit.