• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
FastLed/NeoPixel Pomoc na napisaniu programu
#1
Witam,
Potrzebuje napisać program który będzie zmieniał animacje na ledach WS2812B przez wciśnięcie przycisku,biblioteka dowolna (nie ma dla mnie znaczenia). Szukałem takich programów w internecie ale niczego fajnego nie znalazłem. Program który jest example'm z biblioteki NeoPixel (buttoncycler) nie działa poprawie gdyż animacja nie jest zapętlana a można ją dopiero zmienić po jej ukończeniu. Ostatnio znalazłem stronę na której jest cała masa efektów. Chciałbym zrobić coś abym mógł te efekty implementować do swojego programu. 
https://www.tweaking4all.com/hardware/ar...p-effects/
Próbowałem już wcześniej zaimplementować te animacje do programu który działał poprawie lecz animacji było mało i były mało ciekawe. Program działa na case'ach. Umiem już coś tam prostego napisać ale to mnie troche przerosło bo za każdym razem wyskakiwał jakiś błąd w kompilacji np po dodaniu następnego case'a. Program daje niżej, jeżeli ktoś mógłby mi pomóc ~ byłbym wdzięczny. Pozdrawiam.
Kod:
/*
 Modified by combining these tutorials
   Blink without Delay  http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
   State change detection (edge detection) http://arduino.cc/en/Tutorial/ButtonStateChange
   Adafruit Strandtest https://github.com/adafruit/Adafruit_NeoPixel
   http://www.arduino.cc/en/Tutorial/Debounce
   https://github.com/EternalCore/NeoPixel_Cylon_Scrolling_Eye
*/
#include <Adafruit_NeoPixel.h>

// constants won't change.
const int buttonPin = 4; // the number of the pushbutton pin
#define PIN 0 //the number of the neopixel pic
#define numPixelsInStrip 21
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPixelsInStrip, PIN, NEO_GRB + NEO_KHZ800);

// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
int programState = 0; // current program seleted -- buttonpresses rotate between programs
int numOfPrograms = 7; // how many programs are there total, not including the off state

//unsigned long currentMillis = 0;  //for programs
long previousMillis = 0;        // will store last time LED was updated
int neoPixelToChange = 0; //track which neoPixel to change
int neoPixel_j = 0; //stores values for program cycles
int defaultBrightness = 64;

//cylon variables
int fadeDirection = -1;//change sigen to fade up or down
boolean cylonDirection = true; //keeps track of the direction the pixels should swipe
boolean cylonPause = false; //keeps track of the pause inbetween swipes
long delayMillis = 0; // will store the last time the cylon swipe was paused

void setup() {
 pinMode(buttonPin, INPUT);
 strip.begin();
 strip.show(); // Initialize all pixels to 'off'
 strip.setBrightness(defaultBrightness); // initialize brightness
}

void loop() {
 
 // read the state of the switch into a local variable:
 int reading = digitalRead(buttonPin);

 // check to see if you just pressed the button  

 // If the switch changed, due to noise or pressing:
 if (reading != lastButtonState) {
   // reset the debouncing timer
   lastDebounceTime = millis();
 }
 
 if ((millis() - lastDebounceTime) > debounceDelay) {

   // if the button state has changed:
   if (reading != buttonState) {
     buttonState = reading;
     
     // only toggle the LED if the new button state is HIGH
     if (buttonState == HIGH) {        
       //change the program
       programState = (programState + 1) % (numOfPrograms + 1); //include numOfPrograms + 1, since there is an off state
     }
   }
 }

 // save the reading.  Next time through the loop
 lastButtonState = reading;
 
 //run the chosen program
 switch (programState) {
   case 0:
     allColor(strip.Color(0,255,0)); //off
     break;
   case 1:
     blinkColor(strip.Color(255,255,255),100); // red
     break;        
   case 2:
     colorWipeCycle(strip.Color(255,255,255),500); // green
     break;
   case 3:
     softBlink(strip.Color(255,255,255),defaultBrightness, 50); // blue
     break;
   case 4:
     strip.setBrightness(defaultBrightness); // initialize brightness
     rainbow(20);
     break;
   case 5:
     rainbowCycle(5);
     break;
   case 6:
     cylonEye(40, 500); //not sure the pause time is actually working ???????????????????????
     break;
   default:
     // if nothing else matches, do the default
     allColor(strip.Color(0,0,0)); //off
 } //NOTE if you change the number of programs in the switch statement above, be sure to change the variable numOfPrograms at the top
}

// Fill all the dots with one color
void allColor(uint32_t c) {
 for(uint16_t i=0; i<strip.numPixels(); i++) {
     strip.setPixelColor(i, c);
     strip.show();
 }
} // note for a random color, use:
 // allColor((unsigned long)random(0x01000000)); // random color
 
void blinkColor(uint32_t c, uint8_t wait) {
 unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > wait) {
   // save the last time you blinked the LED
   previousMillis = currentMillis;  

   // if the LED is off turn it on and vice-versa:
   if (ledState == LOW){
     ledState = HIGH;
     allColor(c);
   } else {
     ledState = LOW;
     allColor(strip.Color(0,0,0)); // off
   }
 }
}  
 
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
 
 unsigned long currentMillis = millis();
 
 //only do this if some of the pixels still need to be lit
 if (neoPixelToChange <= strip.numPixels()){
   
   if(currentMillis - previousMillis > wait) {
     
     // save the last time you changed a NeoPixel
     previousMillis = currentMillis;  
   
     //change a pixel
     strip.setPixelColor(neoPixelToChange, c);
     strip.show();
     neoPixelToChange++;
   }
 }
}

// Fill the dots one after the other with a color
void colorWipeCycle(uint32_t c, uint8_t wait) {
 
 unsigned long currentMillis = millis();
 
 //only do this if some of the pixels still need to be lit
 if (neoPixelToChange <= strip.numPixels()){
   
   if(currentMillis - previousMillis > wait) {
     
     // save the last time you changed a NeoPixel
     previousMillis = currentMillis;  
   
     //change a pixel
     strip.setPixelColor(neoPixelToChange, c);
     strip.show();
     neoPixelToChange++;
     
   }
   
 } else {
   // reset the cycle
   previousMillis = 0;  
   neoPixelToChange = 0;
   allColor(strip.Color(0,0,0));
 }
}

void rainbow(uint8_t wait) {
   
 unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > wait) {
   
   // save the last time you changed a NeoPixel
   previousMillis = currentMillis;

   //change the colors of the pixels
   uint16_t i;

   for(i=0; i<strip.numPixels(); i++) {
     strip.setPixelColor(i, Wheel((i+neoPixel_j) & 255));
   }
   strip.show();
   neoPixel_j = (neoPixel_j + 1) % 255; //increment j until all colors are used, then start over
 }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
 
 unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > wait) {
   
   // save the last time you changed a NeoPixel
   previousMillis = currentMillis;

   //change the colors of the pixels
   uint16_t i;

   for(i=0; i<strip.numPixels(); i++) {
     strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + neoPixel_j) & 255));
   }
   strip.show();
   neoPixel_j = (neoPixel_j + 1) % 1279; // 5 cycles of all colors on wheel, then start over
 }
}

void softBlink(uint32_t c, uint8_t brightness, uint8_t wait) {
 
 unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > wait) {
 
   //set the color of all pixels
   allColor(c); // is there a way to set this only once per program ????????????????????
   
   // save the last time you changed a NeoPixel
   previousMillis = currentMillis;
   
   uint16_t i;
   int b = (neoPixel_j * brightness) / brightness;
   strip.setBrightness(b);
   strip.show();
   // sometime figure out how to get this to fade down too instead of just restarting //////////////////////
   neoPixel_j = (neoPixel_j + 1) % brightness;
 }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
 if(WheelPos < 85) {
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
 } else if(WheelPos < 170) {
  WheelPos -= 85;
  return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
 } else {
  WheelPos -= 170;
  return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
 }
}

void cylonEye(uint8_t swipeSpeed, uint8_t pauseTime) {

 if (cylonPause) { //we are on a pause break from swipes

   unsigned long currentPauseMillis = millis();

   //check to see if we've waited long enough
   if ((currentPauseMillis - delayMillis) > pauseTime) { /////////////////////////////// this is not getting called. Why????????????????
     // save the last time you checked the pause
     delayMillis = currentPauseMillis;
     cylonPause = false; //end the pause
   }

 } else {

   //if needed, change directions
   if (neoPixelToChange > numPixelsInStrip) {
     cylonDirection = false;
   }
   if (neoPixelToChange < 0) {
     cylonDirection = true;
     cylonPause = true; //take a break from the swipe
     //turn all pixels off
     for (uint16_t i = 0; i < strip.numPixels(); i++) {
       strip.setPixelColor(i, strip.Color(0, 0, 0));
     }
     strip.show();
     delayMillis = millis();
   }

   //run the swipe
   if (cylonDirection) {
     cylonUp(strip.Color(255, 0, 0), strip.Color(72, 0, 0), swipeSpeed); // red
   } else {
     cylonDown(strip.Color(255, 0, 0), strip.Color(72, 0, 0), swipeSpeed); // red
   }
 }
}

void cylonUp(uint32_t c0, uint32_t c1, uint8_t wait) {

 unsigned long currentMillis = millis();

 //neoPixelToChange * wait
 if (currentMillis - previousMillis > wait) {

   //turn all pixels off
   for (uint16_t i = 0; i < strip.numPixels(); i++) {
     strip.setPixelColor(i, strip.Color(0, 0, 0));
   }

   // save the last time you changed a NeoPixel
   previousMillis = currentMillis;

   //change a pixel
   strip.setPixelColor(neoPixelToChange, c0); //primary color
   strip.setPixelColor(neoPixelToChange - 1, c1); //secondary color
   strip.setPixelColor(neoPixelToChange + 1, c1); //secondary color
   strip.show();
   neoPixelToChange++;
 }
}

void cylonDown(uint32_t c0, uint32_t c1, uint8_t wait) {

 unsigned long currentMillis = millis();

 //neoPixelToChange * wait
 if (currentMillis - previousMillis > wait) {

   //turn all pixels off
   for (uint16_t i = 0; i < strip.numPixels(); i++) {
     strip.setPixelColor(i, strip.Color(0, 0, 0));
   }

   // save the last time you changed a NeoPixel
   previousMillis = currentMillis;

   //change a pixel
   strip.setPixelColor(neoPixelToChange, c0); //primary color
   strip.setPixelColor(neoPixelToChange - 1, c1); //secondary color
   strip.setPixelColor(neoPixelToChange + 1, c1); //secondary color
   strip.show();
   neoPixelToChange--; //is there any way to combine this with cylonUp, since this is the only line that is different?
 }
}
 
Odpowiedź
#2
Po prostu masz za mało wiedzy i doświadczenia by zastosować bardziej zaawansowane elementy. Czytaj inne programy, przejdź kurs Arduino na Forbocie, nawet jeśli wydaje Ci się mało interesujący lub nawet nie masz do tego sprzętu - ale poznasz triki.
Nawet nie tylko ten jeden, jest ich pińcet w Internecie i na Youtubie.
Po kilkuset "gotowcach" odtworzonych ze zrozumieniem każdej linijki kodu wszystko zacznie się układać w przejrzystą całość - jak z nauką języka obcego, trzeba mieć znajomość zasad i zasób 1000+ słów by móc zrobić wszystko.
Jak ustawisz sobie efekt w funkcji, albo w pętli to można to przerwać stosując return lub break. Poznaj obsługę przerwań zewnętrznych, przycisk można odczytać w dowolnym momencie i przejść do innego punktu programu stosując te elementy razem.
 
Odpowiedź
#3
AVR + WS281x + animacje to nie zbyt dobry pomysł gdy ma być dużo led. Nie to że się nie da:
https://www.youtube.com/watch?v=aM9hy4Ep...sQ&index=3
https://www.youtube.com/watch?v=h2RKAJZd...sQ&index=4
https://www.youtube.com/watch?v=hBovo7Y0...sQ&index=2
Musisz jednak zapomnieć o bibliotekach Arduino. One blokują program w czasie transmisji do led. Trzeba użyć przerwań. Użyłem USART, bo nie ma problemu z zbyt długim poziomem H gdy pomiędzy transmisja wystąpi inne przerwanie. W Przypadku USART przedłużony zostanie poziom L co nie jest problemem. Ponadto USART ma 2 bajty FIFO, więc przerwania można wywoływać ok 130'000razy na sekundę a nie 260'000. Ponadto, na jedną led potrzeba 8 a nie 9 bajtów. Aby uC był mniej obciążony trzeba go taktować 20 a nie 16MHz. uC musi mieć dużo RAM, 100led to 800 bajtów czyli prawie połowa tego co oferuje Mega328. Użyj Mega1284 z 16kB RAM. Mega 2560/1280 z 8kB odpada, bo Fclk max to 16MHz.
Jak widzisz dużo problemów. Najlepiej uzyć ARM ostatecznie Xmega. One mają DMA, dużo RAM, szybki zegar. Tam problemów ze sterowaniem WS281x nie ma.
- uC: ARM Angel , AVR, Z8, PIC, 8051 / CPU: MC680x0  , Z-80, 6502
- CPLD, FPGA, GAL
- GSM, ISDN, ETH, USB, RS232C/485/422
- C, ASM, CUPL, PHP, BASIC C-64

http://er-mik.prv.pl/projekty_avt.php * http://er-mik.prv.pl/ * http://kolejki.prv.pl/

KA-NUCLEO-F411CE Idea , ESP32, Mega2560, UNO PLUS
 
Odpowiedź
#4
To zapytałbym się czy ktoś ma jakiś prosty program na różne animacje na arduino do WS2812B i mógłby użyczyć?
 
Odpowiedź
#5
Ile tych ledów?
Ułożone w węża czy matrycę?
Jeśli matryca to jaka?

Najlepiej pokaż przykład w necie, łatwo znajdziesz na YouTube pod hasłem WS2812, WS2811, WS2813
- uC: ARM Angel , AVR, Z8, PIC, 8051 / CPU: MC680x0  , Z-80, 6502
- CPLD, FPGA, GAL
- GSM, ISDN, ETH, USB, RS232C/485/422
- C, ASM, CUPL, PHP, BASIC C-64

http://er-mik.prv.pl/projekty_avt.php * http://er-mik.prv.pl/ * http://kolejki.prv.pl/

KA-NUCLEO-F411CE Idea , ESP32, Mega2560, UNO PLUS
 
Odpowiedź
#6
Pasek led ws2812b żadna matryca ani nic najlepiej program w którym będę mógł zmieniać animacje na swoje kontrolowane przyciskiem. Z tego co wiem w fastledzie wybiera się ilość ledow na starcie programu bo ilość u mnie będzie się zmieniać bo chce zrobić to w kilku miejscach. Stronę z animacjami dałem powyżej.
 
Odpowiedź
#7
Myślę, że nawet jak dam gotowca to nie zrobisz z nim nic, bo nie potrafisz nawet zrozumiale napisać jednego zdania.

(08-08-2018, 12:51)Kumak napisał(a): Pasek led ws2812b żądny
Żądny czego? Przygód?

(08-08-2018, 12:51)Kumak napisał(a): Mateusz ani nic
Jaki Mateusz? O.Mateusz z Sandomierza?

(08-08-2018, 12:51)Kumak napisał(a): najlepiej program w którym będę mógł zmieniać animacje na swoje kontrolowane przyciskiem w fastledzie wybiera się ilość ledow na starcie programu bo ilość u mnie będzie się zmieniać bo chce zrobić to w kilku miejscach.
Interpunkcja kolego, interpunkcja. Trzeba się domyślać co napisałeś.

(08-08-2018, 12:51)Kumak napisał(a): Stronę z animacjami dałem powyżej.
Gdzie powyżej? Znów trzeba się domyślać, że pewnie w pierwszym poście. Daj konkretne linki bo Twoje odpowiedzi się tak "precyzyjne" jak będzie moja: Program, którego szukasz jest w Internecie.
- uC: ARM Angel , AVR, Z8, PIC, 8051 / CPU: MC680x0  , Z-80, 6502
- CPLD, FPGA, GAL
- GSM, ISDN, ETH, USB, RS232C/485/422
- C, ASM, CUPL, PHP, BASIC C-64

http://er-mik.prv.pl/projekty_avt.php * http://er-mik.prv.pl/ * http://kolejki.prv.pl/

KA-NUCLEO-F411CE Idea , ESP32, Mega2560, UNO PLUS
 
Odpowiedź
#8
Autokorekta...
 
Odpowiedź
#9
(08-08-2018, 13:40)Kumak napisał(a): Autokorekta...

Po auokorekcie jest lepiej (interpunkcja nadal jest czymś strasznym), linków nadal nie ma a co do
(08-08-2018, 13:40)Kumak napisał(a): Stronę z animacjami dałem powyżej.

to powyżej znalazłem
(08-08-2018, 13:40)Kumak napisał(a): To zapytałbym się czy ktoś ma jakiś prosty program na różne animacje na arduino do WS2812B i mógłby użyczyć? "
- uC: ARM Angel , AVR, Z8, PIC, 8051 / CPU: MC680x0  , Z-80, 6502
- CPLD, FPGA, GAL
- GSM, ISDN, ETH, USB, RS232C/485/422
- C, ASM, CUPL, PHP, BASIC C-64

http://er-mik.prv.pl/projekty_avt.php * http://er-mik.prv.pl/ * http://kolejki.prv.pl/

KA-NUCLEO-F411CE Idea , ESP32, Mega2560, UNO PLUS
 
Odpowiedź
#10
Oczywiście szukaj gotowca, na świecie jest kilkaset milionów programistów, może akurat znajdziesz dokładnie taki program jak chcesz, broń bosze nie próbuj się czegoś nauczyć. Po wpisaniu w google "arduino external interrupt return" z pierwszych dwóch trafień można zrobić taki przykład: 
Kod:
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
 // put your setup code here, to run once:
 pinMode(ledPin, OUTPUT);
 pinMode(interruptPin, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(interruptPin), blink, LOW);
}

void loop() {
 // put your main code here, to run repeatedly:
led100();
led200();
led500();
}

void blink() {//funkcja użyta w przerwaniu
 state = HIGH;
}


//jakies funkcje do testu

void led100()
{
 while(1)//petla nieskonczona
 {
   if(state)
   {
     state=0;
   return;
   }
   digitalWrite(ledPin,!digitalRead(ledPin));
   delay(100);
 }
 
}

void led200()
{
 while(1)//petla nieskonczona
 {
   if(state)
   {
     state=0;
   return;
   }
   digitalWrite(ledPin,!digitalRead(ledPin));
   delay(200);
 }
 
}

void led500()
{
 while(1)//petla nieskonczona
 {
   if(state)
   {
     state=0;
   return;
   }
   digitalWrite(ledPin,!digitalRead(ledPin));
   delay(500);
 }
}
Funkcje działają blokując pętlę główną aż do wciśnięcia przycisku na pinie 2.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości