• 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
WS2812b im więcej tym wolniej
#1
Cześć,
buduję oświetlenie świąteczne bazujące na taśmach led ws2812b. Problem w tym, że kompiluję szkic nawet taki przykładowy z bibliotek dla np 150led to jest płynnie a gdy zwiększę go do 600 led to już jest sporo wolniej. Wynika to z ograniczeń arduino czy sposobu sterowania diodami? Jest jakieś na to rozwiązanie? Obecnie używam Arduino UNO, przesiadka na Mega coś pomoże?
Pozdrawiam
 
Odpowiedź
#2
Pokaż kod i bibliotekę pewnie sporo błędów...
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#3
Kod:
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 600
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// *** REPLACE FROM HERE ***
void loop() {
  // Slower:
  // Strobe(0xff, 0x77, 0x00, 10, 100, 1000);
  // Fast:
  Strobe(0xff, 0xff, 0xff, 100, 10, 5000);
}

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
  for(int j = 0; j < StrobeCount; j++) {
    setAll(red,green,blue);
    showStrip();
    delay(FlashDelay);
    setAll(0,0,0);
    showStrip();
    delay(FlashDelay);
  }

delay(EndPause);
}
// *** REPLACE TO HERE ***

void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
#endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
#endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

Jest to przykład z biblioteki FastLED, taki sam przykład z biblioteki NeoPixel ma ten sam problem, dla 100led jeden okres migania trwa 3s, a dla 600 10s a wolniej, zależy mi aby niezależnie od ilości diod tempo było takie samo. Może być to spowodowane małą ilością RAM?
 
Odpowiedź
#4
To jest demo do migania led. Jak chcesz użyć tego w swoim programie, który ma coś wyświetlać, obsługiwać przyciski, czujniki, to wywalasz delay, a zamiany stanu led wywołujesz co określony czas wyznaczony przez millis lub timer.
Jeden komplet danych też oczywiście jest inny dla 10/100/600 led, dla jednej led to 3 bajty, 24 bity, wysyłane z prędkością 800kHz, to jak sobie policzysz od strony LEDdla 600 da się zrobić 55FPS, i przy tej prędkości to już będzie tylko i wyłączenie cały czas wysyłanie informacji do LED, chcesz coś jeszcze zrobić w LOOP to OK, ale już FPSów będzie mniej. A jak jeszcze piny Arduino nie są w stanie ogarnąć takiej prędkości to FPS spadają odpowiednio.
Jak zmieniasz barwę 150-siątej led to nie wysyłasz danych tylko dla tej led, ale nowy stan dla wszystkich.
Przesiadka na MEGA nic nie da, bo to ta sama prędkość. Jak braknie w loop czasu na obsługę to można dać szybszy uC np. ESP8266. Jak efekt ma być szybszy to szybszy uC nic nie da, bo i tak ledy nie będą działać szybciej, każda musi odebrać swoje dane od poprzedniej led. Można ewentualnie podzielić taki duży pasek na kilka kanałów.
Efekt który fajnie wygląda na biurku ze 100 ledami pewnie nie będzie tak samo dynamiczny jak na 600 rozłożonych na ścianie budynku. Trzeba go po prostu przeliczyć tak, że jak led ma mieć tę samą prędkość kątową, to nie może co 1s przesuwać się o 1 pixel, a o 6, lub żeby był jeszcze tak samo widoczny to po prostu przesuwaj grupę 6 led.
W bibliotece fastled masz tak podany parametr delay FastLED.delay(1000 / UPDATES_PER_SECOND);. Jak zmniejszysz FPS (UPDATES_PER_SECOND) to pewnie zauważysz przyspieszenie dla 600 led.
MEGA ma więcej RAM, to może mieć znaczenie gdyby go teraz brakowało. 600x3bajty to za każdym razem do wysłania 1800, żeby było szybko przeliczenia robi się na RAM, zmienia dany pixel, a potem to 1800B ma wylecieć na pasek w postaci 14400 bitów jako nowy stan wszystkich led z prędkością 800000b/s. 200B na resztę programu to może być problem. Brak ram objawiałby się jakimiś krzakami na efektach, gdy jedne zmienne są nadpisywane losowymi z innych części programu. Pod tym kątem na pewno warto użyć przynajmniej MEGA dla takiej ilości LED.
 
Odpowiedź
#5
Dziękuję za tak obszerne wytłumaczenie, teraz rozumiem skąd takie działanie na większej ilości.
Gdybym chciał podzielić 600led np na 4 kanały po 150szt to jakaś podpowiedź jak to synchronizować? Np jeśli chcę uzyskać efekt latającego oka wzdłuż całego domu to jak oko dolatuje do końca pierwszego kanału to żeby zaczynało się od początku drugiego kanału, są na to jakieś gotowe instrukcje?
Pozdrawiam
 
Odpowiedź
#6
A potrzebujesz 200 FPS?
Nie ma gotowych instrukcji, efekt oka zrobisz na jednym kanale, prościej zastosować np. ESP8266 do większych efektów, 50FPS wystarczy z 600LED.
Dopóki nie będziesz używał funkcji WIFI nie zauważysz istotnych różnic w pisaniu programu dla UNO/ESP.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości