fbpx

Ostatnio pisałem o tym jak wysterować diody WS2812B z pomocą STM32. Jednak samo sterowanie nie wystarczy, aby w pełni cieszyć się możliwościami jakie dają nam całe paski tych LEDów. Dzisiaj przedstawię bibliotekę zawierającą szereg ciekawych efektów świetlnych. Do dzieła!

Ten artykuł jest częścią cyklu:

Biblioteki Arduino a STM32

Jest jedna rzecz za którą lubię Arduino. Jest to mnogość gotowych bibliotek napisanych pod tę platformę. Są one pisane raz lepiej, czasem gorzej, ale dla ogólnego zamysłu w jaki sposób można podejść do problemów uważam, że są dobre. Nie inaczej jest z adresowalnymi diodami i efektami świetlnymi dla nich. Istnieje na GitHubie taka fajna  biblioteka WS2812FX napisana przez użytkownika kitesurfer1404(link), która zawiera mnóstwo ciekawycych animacji dla naszych diodek. Niestety jest ona napisana w Arduinowym C++ dlatego postanowiłem przeportować ją w znacznej części dla potrzeb STM32 i mojej biblioteki WS2812B opartej o HAL.

Model przestrzeni barw HSV

Biblioteka WS2812FX w całości bazuje na przestrzeni barw RGB w której podaje się wartości kolejnych składowych czerwonej, zielonej i niebieskiej. Bardzo ciekawą alternatywą dla RGB jest przestrzeń HSV. Nawiązuje ona do tego jak barwy odbiera nasze oko. Składowe tego modelu to:

  • H (hue) – odcień światła, czyli kolor. Przyjmuje wartości w stopniach okręgu barw od 0 do 359.
  • S (saturation) – nasycenie koloru. Jak dużo koloru jest w emitowanym świetle.
  • V (value, brightness) – moc światła białego.

Wartości S i V standardowo są ułamkiem i mieszczą się w zakresie między 0 a 1. Na potrzeby mikrokontrolerów napisałem funkcje konwertujące w dwie strony(RGB->HSV i HSV->RGB) w zakresie 0 – 255 dla tych składowych i oczywiście 0-359 dla składowej H. Szkoda cykli zegara na float’y, gdy tych operacji może być na prawdę sporo 😉 Przecież nie każdy MCU ma FPU.

Model HSV graficznie prezentuje się następująco.

Rysunek lepiej działa na wyobraźnię jeśli chodzi o zrozumienie jak modyfikowanie poszczególny ch składowych wpłynie na kolor wynikowy. H wiadomo, kolor bazowy. Kręcąc składową S, kolor płynnie przechodzi w światło białe. Kręcąc V wygaszamy kolor schodząc w stronę czerni. Można z tego uzyskać ciekawe efekty przejścia czy pulsowania.

Takie dwa efekty dodałem od siebie przy porotwaniu biblioteki. Jest to odpowiednio przejście od koloru białego lub czarnego w stronę ustawione przez użytkownika. Czas całego przejścia  (wyrażony w milisekundach) kolor->biały->kolor definiuje się poprzez funkcję ustawiania prędkości. Piszę to dlatego, że dla pozostałych efektów wartość speed  jest interpretowana inaczej i definiuje ona czas pomiędzy kolejnym przejściem w efekcie (również w milisekundach).

Działanie biblioteki

Przeportowana biblioteka opiera swoje działanie na programowym timerze, który dekrementowany jest w przerwaniu SysTick timera. Jeżeli timer zostanie wyzerowany, funkcja WS2812BFX_Callback() wywołuje wcześniej wybrany tryb efektów. Tam wykonywany jest kolejny krok aktualizujący wartości diod w pasku oraz ustawiany programowy timer, zdefiniowany wcześniej czas do kolejnego kroku. Prosty przykład wygląda następująco:

WS2812B_Init(&hspi1);
WS2812BFX_SetSpeed(5000);
WS2812BFX_SetColorRGB(0, 0,255,0);
WS2812BFX_SetColorRGB(1, 32,0,0);
WS2812BFX_SetColorRGB(2, 0,64,0);
WS2812BFX_SetMode(FX_MODE_WHITE_TO_COLOR);
WS2812BFX_Start();

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
	WS2812BFX_Callback();
}

Pierwszym krokiem jest inicjalizacja sterowania diodami WS2812B_Init(&hspi1). Tak samo jak w poprzednim wpisie użyłem tutaj SPI1. Następnie należy skonfigurować działanie paska.

Trzeba ustawić prędkość działania funkcją. Można to też robić również podczas działania efektu.

WS2812BFX_SetSpeed(uint16_t Speed)

Jak już wcześniej wspomniałem dla wszystkich trybów wartość Speed określa czas pomiędzy kolejnymi krokami wyrażony w milisekundach. Dwa tryby – FX_MODE_WHITE_TO_COLOR i FX_MODE_BLACK_TO_COLOR – są wyjątkami i wartość ta określa czas pełnego cyklu przejść.

Następnie należy ustawić kolory, które będą użyte w trybie przy pomocy jednej z fukncji do tego przeznaczonej.

void WS2812BFX_SetColorStruct(uint8_t id, ws2812b_color c);
void WS2812BFX_SetColorRGB(uint8_t id, uint8_t r, uint8_t g, uint8_t b);
void WS2812BFX_SetColorHSV(uint8_t id, uint16_t h, uint8_t s, uint8_t v);
void WS2812BFX_SetColor(uint8_t id, uint32_t c);

Niektóre tryby wykorzystują 2 lub nawet 3 kolory do działania. Numer koloru określa argument id. Przygotowałem 4 funkcje dla wygody użytkowania. Można ustawić kolor za pomocą przestrzeni RGB lub HSV. Ustawienie poprzez strukturę lub zmienną 32-bitową jest ustawieniem w przestrzeni RGB w danym formatowaniu.

Kolejnym krokiem jest wybór efektu.

void WS2812BFX_SetMode(fx_mode mode);

Jako argument funkcja przyjmuje wartość enumeracyjną z nazwą wybranej funkcji.

typedef enum {
	FX_MODE_STATIC,
	FX_MODE_WHITE_TO_COLOR,
	FX_MODE_BLACK_TO_COLOR,
	FX_MODE_BLINK,
	FX_MODE_BLINK_RAINBOW,
	FX_MODE_STROBE,
	FX_MODE_STROBE_RAINBOW,
	FX_MODE_BREATH,
	FX_MODE_COLOR_WIPE,
	FX_MODE_COLOR_WIPE_INV,
	FX_MODE_COLOR_WIPE_REV,
	FX_MODE_COLOR_WIPE_REV_INV,
	FX_MODE_COLOR_WIPE_RANDOM,
	FX_MODE_COLOR_SWEEP_RANDOM,
	FX_MODE_RANDOM_COLOR,
	FX_MODE_SINGLE_DYNAMIC,
	FX_MODE_MULTI_DYNAMIC,
	FX_MODE_RAINBOW,
	FX_MODE_RAINBOW_CYCLE,
	FX_MODE_FADE,
	FX_MODE_SCAN,
	FX_MODE_DUAL_SCAN,
	FX_MODE_THEATER_CHASE,
	FX_MODE_THEATER_CHASE_RAINBOW,
	FX_MODE_RUNNING_LIGHTS,
	FX_MODE_TWINKLE,
	FX_MODE_TWINKLE_RANDOM,
	FX_MODE_TWINKLE_FADE,
	FX_MODE_TWINKLE_FADE_RANDOM,
	FX_MODE_SPARKLE,
	FX_MODE_FLASH_SPARKLE,
	FX_MODE_HYPER_SPARKLE,
	FX_MODE_MULTI_STROBE,
	FX_MODE_CHASE_WHITE,
	FX_MODE_CHASE_COLOR,
	FX_MODE_CHASE_RANDOM,
	FX_MODE_CHASE_RAINBOW,
	FX_MODE_CHASE_FLASH,
	FX_MODE_CHASE_FLASH_RANDOM,
	FX_MODE_CHASE_RAINBOW_WHITE,
	FX_MODE_CHASE_BLACKOUT,
	FX_MODE_CHASE_BLACKOUT_RAINBOW,
	FX_MODE_RUNNING_COLOR,
	FX_MODE_RUNNING_RED_BLUE,
	FX_MODE_RUNNING_RANDOM,
	FX_MODE_LARSON_SCANNER,
	FX_MODE_COMET,
	FX_MODE_FIREWORKS,
	FX_MODE_FIREWORKS_RANDOM,
	FX_MODE_MERRY_CHRISTMAS,
	FX_MODE_FIRE_FLICKER,
	FX_MODE_FIRE_FLICKER_SOFT,
	FX_MODE_FIRE_FLICKER_INTENSE,
	FX_MODE_CIRCUS_COMBUSTUS,
	FX_MODE_HALLOWEEN,
	FX_MODE_BICOLOR_CHASE,
	FX_MODE_TRICOLOR_CHASE,
	FX_MODE_ICU
} fx_mode;

W tym momencie przypisane są do zmiennych trybu wcześniej wybrane kolory oraz zerowane są wszystkie zmienne licznikowe użyte w bibliotece. Biblioteka jest już gotowa do wystartowania. Aby ruszyć z efektami wystarczy wywołać

void WS2812BFX_Start(void);

W pętli głównej umieść callback do obsługi efektów.

void WS2812BFX_Callback(void);

Aby timer software’owy działał razem z SysTick’iem należy zdefiniować fukncję callbackow’ą.

/* USER CODE BEGIN 4 */
void HAL_SYSTICK_Callback(void)
{
  WS2812BFX_SysTickCallback();
}
/* USER CODE END 4 */

Jak widzisz, umieściłęm ją w sekcji czwartej dla kodu użytkownika w pliku main.c. Dzięki temu nie tylko tym może się SysTick zajmować. Zwróć uwagę, że void HAL_SYSTICK_Callback(void) jest funkcją weak tak jak funkcje callback’ów DMA użyte w poprzednim wpisie. Bez zdefiniowania tej funkcji, biblioteka FX nie będzie działać!

Teraz jest już wszystko. Można podziwiać wybrany efekt. Polecam potestować działanie.

Podsumowanie

Uzupełniając kod diod WS2812B o bibliotekę z efektami świetlnymi jestem pewien, że będzie to przez wiele osób wykorzystane podczas zbliżających się świąt. Przyznaj, że efekty są świetne!

Przeportowana biblioteka jest przeze mnie cały czas wspierana także jeżeli znajdziesz jakieś błędy to napisz mi o tym. W oryginalnym kodzie dla Arduino zaimplementowany został też podział na niezależne segmenty. Zajmę się tym w najbliższym czasie i opublikuję stosowny wpis.

Dziękuję Ci za przeczytanie tego wpisu. Jeśli taka tematyka Ci odpowiada, daj mi znać w komentarzu. Będę też wdzięczny za propozycję tematów które chciałbyś abym poruszył.

Kod standardowo dostępny jest na moim GitHubie: link

Jeśli zauważyłeś jakiś błąd, nie zgadzasz się z czymś, chciałbyś coś dodać istotnego lub po prostu uważasz, że chciałbyś podystkutować w tym temacie, napisz komentarz. Pamiętaj, że dyskusja ma być kulturalna i zgodna z zasadami języka polskiego.

Ten artykuł jest częścią cyklu:

5/5 - (3 votes)

Podobne artykuły

.

9 komentarzy

spiralbrain · 03/05/2022 o 12:33

Hi thank you for the great code.

I am trying to adapt your code for the newer LED’s which have a longer reset time. However I cannot get my head around how you use the bytes to send out a reset pulse.

for(uint8_t i = 0; i < 58; i++)
buffer[i] = 0x00;

HAL_SPI_Transmit_DMA(hspi_ws2812b, buffer, 48);

and then again

if(!ResetSignal)
{
for(uint8_t k = 0; k < 24; k++) // To 72 impulses of reset
{
buffer[k] = 0x00;
}
ResetSignal = 1; // End reset signal

Can you help me increase the reset pulse duration?

Thanks

spiralbrain

    Mateusz Salamon · 03/05/2022 o 18:13

    You are digging in the right direction 🙂 You have to make a longer buffer or send it twice for reset by moving the ResetSignal later in the whole procedure. I don’t know how long should be with your LEDs.

paulus · 14/11/2018 o 22:59

Witam. Cenne informacje dla mnie, super sie czyta. Jesli znalazbys chwile wrzuc na tapete wyswietlacz graficzny.

    Mateusz · 14/11/2018 o 23:00

    Cześć! Graficzny mono czy TFT?

Zbigniew · 14/11/2018 o 22:24

Rewelacja. Jednak murze zgodzić z moimi poprzednikami mało info w necie, o Arduino wszędzie dużo tego. Chętnie i poczytam o kolejnych.

    Mateusz · 14/11/2018 o 22:40

    Dzięki za pozytywną reakcję. Arduino jest na tyle popularne, że internet jest nim totalnie zalany. Zmieńmy to 😉

Bartek · 14/11/2018 o 21:18

Rozumiem ale dla laika np takiego jak ja przydałby się kurs od podstaw. Szkoda że dla Arduino jest tego cały internet od mrugania diodami po rozbudowane projektu. Bluepill jest pomijane właśnie przez brak pomocy

Bartek · 14/11/2018 o 20:54

Witam. Ciekawy artykuł. Nie myślales o serii kursów z programowania stm 32 bluepill? Chodzi mi o takie kursy jak są dla Arduino od postaw. Instalacja, pierwszy program, wyświetlacz, obsługa silników dc, moduły nrf24l01, jakieś czujniki, przyciski, wielowatkowosc itp? Płytki są tańsze jak Arduino i mają większe możliwości lecz mało kursów i poradników dla laików

    Mateusz · 14/11/2018 o 21:03

    Cześć Bartek!
    Fakt. Mało jest tego typu poradników, a szkoda bo STM’ki to fajne chłopaki. Moje dotychczasowe wpisy poniekąd są takimi kursami lecz niestety nie od podstaw. Może kiedyś… Zauważ też, że używając HAL’a możesz łatwo przenieść kod z F4 na F1 jeżeli peryferia się zgadzają. To, że mam wpisy dotyczące F4 czy L4 nie skreśla użycie kodu dla F1 z bluepill. Sam Cube też udostępnia migrację na niektóre rodziny. Na ogół stare->nowe.

Dodaj komentarz

Avatar placeholder

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *