Mit dieser Library können bis zu 8 LED-Ketten vom Typ WS2812 betrieben werden.
Für eine nähere Beschreibung der WS2812 siehe meine andere Library
(78=WS2812-Lib)
Wenn man alle 8 Stränge parallel legt, kann man auch Texte darstellen.
Einen entsprechenden Font mit 8×6 Pixel habe ich dazugepackt.
Im H-File können nicht benutzte Kanäle per Define abgeschaltet werden.
(Um RAM zu sparen)
Im H-File muss die Länge der längsten LED-Kette eingetragen werden
(um Speicherplatz zu reservieren) Die Software versucht aber die tatsächliche
Längen aller angeschlossener Ketten zu messen (wärend der Init-Funktion).
Dazu müssen die Ausgänge der letzten LEDs von allen Ketten über Dioden
(z.B. BAT46) per “Wired-Or” mit dem externen Interrupt-Pin “PD0″
verbunden werden. Falls die Längenmessung bei einer Kette nicht funktioniert,
geht die Software von der maximalen Länge aus die im H-File eingestellt ist.
Die Init-Funktion liefert in dem Fall ein “Error” zurück.
Die gemessenen Längen aller Ketten steht in “WS2812_CHAIN_LEN.ch1″
bis “WS2812_CHAIN_LEN.ch8″
Bild :
Hinweis : falls ihr die automatische Längenmessung nicht benutzen wollt,
müsst ihr NACH der Init-Funktion alle Längen manuell setzen :
1 2 3 4 5 6 7 8 | // init WS2812 UB_WS2812_Init(); // ignore automatic chain length and // set chain lenght manually WS2812_CHAIN_LEN.ch1=5; WS2812_CHAIN_LEN.ch2=3; WS2812_CHAIN_LEN.ch3=4; |
Zur Software :
Alle Funktionen die LEDs betreffend, ändern nur die Farbwerte im RAM.
Um die geänderten Werte an die LEDs zu senden, muss einmal die Funktion
“UB_WS2812_RefreshAll” aufgerufen werden.
Bei den Shift/Roll-Funktionen kann über eine Bitmaske bestimmt werden,
welche LED-Ketten benutzt werden sollen. Damit ist es möglich nur eine einzelne
LED-Kette zu verschieben oder mehrere gleichzeitig.
Benutzte Pins :
1 2 3 4 5 6 7 8 9 10 | CH1 = PC6 CH2 = PB5 CH3 = PB0 CH4 = PB1 CH5 = PE9 CH6 = PE11 CH7 = PE13 CH8 = PE14 EXTI = PD0 (zum messen der Anzahl der LEDs aller WS2812-Ketten) |
Voraussetzungen :
1 2 | Benutzte Module der CooCox-IDE : GPIO, TIM, DMA, MISC, EXTI, SYSCFG Benutzte Librarys : keine |
Funktionen :
1 2 3 4 5 6 7 8 9 10 11 12 | ErrorStatus UB_WS2812_Init(void); // zum init aller WS2812-Kette(n) void UB_WS2812_RGB_2_HSV(WS2812_HSV_t hsv_col, WS2812_RGB_t *rgb_col); // HSV-Wert in RGB umrechnen void UB_WS2812_Pixel_RGB(uint32_t x, uint8_t y, WS2812_RGB_t rgb_col); // eine einzelne LED setzen (als RGB Wert) void UB_WS2812_All_RGB(uint8_t ch_maske, WS2812_RGB_t rgb_col); // alle LEDs der Kette(n) setzen void UB_WS2812_Shift_Left(uint8_t ch_maske); // alle LEDs der Kette(n) einen Step links schieben void UB_WS2812_Shift_Right(uint8_t ch_maske); // alle LEDs der Kette(n) einen Step rechts schieben void UB_WS2812_Rotate_Left(uint8_t ch_maske); // alle LEDs der Kette(n) einen Step links rotieren void UB_WS2812_Rotate_Right(uint8_t ch_maske); // alle LEDs der Kette(n) einen Step rechts rotieren void UB_WS2812_Char_RGB(uint32_t x, uint8_t ascii, WS2812_RGB_t vg, WS2812_RGB_t bg); // zeichnet ein Ascii-Zeichen (8 Ketten notwendig) void UB_WS2812_String_RGB(uint32_t x, char *ptr, WS2812_RGB_t vg, WS2812_RGB_t bg); // zeichnet einen String (8 Ketten notwendig) void UB_WS2812_RefreshAll(void); // sendet alle Daten an die LEDs ErrorStatus UB_WS2812_Check_Len(void); // test der Laenge aller Ketten |
Beispiel :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | //-------------------------------------------------------------- // File : main.c // Datum : 04.10.2014 // Version : 1.0 // Autor : UB // EMail : mc-4u(@)t-online.de // Web : www.mikrocontroller-4u.de // CPU : STM32F4 // IDE : CooCox CoIDE 1.7.4 // GCC : 4.7 2012q4 // Module : CMSIS_BOOT, M4_CMSIS_CORE // Funktion : Demo der WS2812_8CH Library // Hinweis : Diese zwei Files muessen auf 8MHz stehen // "cmsis_boot/stm32f4xx.h" // "cmsis_boot/system_stm32f4xx.c" //-------------------------------------------------------------- #include "main.h" #include "stm32_ub_ws2812_8ch.h" int main(void) { WS2812_RGB_t hg_col, vg_col; SystemInit(); // Quarz Einstellungen aktivieren // init aller WS2812-Ketten // (8 Ketten mit je max 100 LEDs) UB_WS2812_Init(); // Farbe fuer Hintergrund auf gruen setzen hg_col.blue=0; hg_col.green=10; hg_col.red=0; // Farbe fuer Vordergrund auf rot setzen vg_col.blue=0; vg_col.green=0; vg_col.red=10; // setzen aller LEDs auf Hintergrund Farbe UB_WS2812_All_RGB(0xFF, hg_col); // Zeichnen vom Text 'Hallo' an Position 0 UB_WS2812_String_RGB(0,"Hallo", vg_col, hg_col); // Ausgabe aller Daten an die LEDs UB_WS2812_RefreshAll(); while(1) { // nichts zu tun } } |
Hier die Library zum Download :
Hier der komplette CooCox-Projektordner zum Download :
Hallo Uwe,
sagmal es ist wahrscheinlich nicht möglich die Ausgaben noch schneller zu gestalten oder? Weil es kommt mir relativ langsam vor, wenn ich z.B. eine LED Durchlaufen lasse dann kann man zugucken beim durchlaufen wenn die LED Kette mehr als 250-300 LEDs hat.
rechne doch mal nach. Eine LED = 30us -> 300 LEDs = 9ms. Ein kompletter refresh dauert also 9ms. Wenn du eine LED von vorne nach hinten also um 300 LEDs durchlaufen lassen willst und jeden Zwischenschritt anzeigst, dauert das 9ms * 300 = 2,7 sekunden. schneller geht nur, wenn du kürzere Ketten nimmst und diese hintereinander anordnest, oder wenn du nicht jeden Schritt anzeigst.
Ja da hast du wohl Recht, das hatte ich gar nicht berücksichtigt. Hab’s nun auf max 150 LEDs beschränkt und dementsprechend die Programme angepasst das es trotzdem aussieht wie ein durchgängiger Strip.
Trotzdem vielen Dank für deine Hilfe
Good afternoon!
Trying to 12 LED strings.
It will not conflict DMA and interrupt? What are the problems?
Project:https://docviewer.yandex.ru/?url=ya-disk%3A%2F%2F%2Fdisk%2F%D0%94%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B%2FWS2812B.7z&name=WS2812B.7z&c=5657e27abf60
Thank you!
sorry, i dont search failure in external code.
How to determine the channel interrupts and process it? I can do so and will not conflict because the interrupt handler is the same?
if (DMA_GetITStatus(DMA1_Stream2, DMA_IT_TCIF2))
{}
=> TIM3-CC4 => DMA1, Channel5, Stream2
=> TIM5-CC1 => DMA1, Channel6, Stream2
Thank you!
you cant use two channels on the same stream at the same dma. either use dma2 or another stream. or use the channels one after the other.