Hallo, ich habe jetzt mal angefangen mit den WS2812B LEDS herumzuspielen. Hierfür habe ich mir einen LED Ring mit 24 LEDS gekauft. Ich habe wie gewünscht +5V und GND mit dem Nucleoboard und den Stripes angeschlossen. Im nächsten schritt bin ich dann auf die mbed seite gegangen und habe mir folgende Lib angeschaut https://developer.mbed.org/components/Generic-WS2812-Driver/ Nur leider bekomme ich es mit dieser lib meine LEDS nicht zum laufen. Ich ändere in diesem Example nur meinen Pin auf D3 und die Anzahl der LEDS auf 24 #define WS2812_BUF 24 #define NUM_COLORS 24 #define NUM_LEDS_PER_COLOR 20 Ich schätze mal das ich irgend ein Timing problem habe. Denn nach 5 minuten oder mehr warten springen die LEDS an. Wahrscheinlich hat der uC dann genau den richtigen takt mal erreicht. Um das zu überprüfen benötige ich ein Oszilloskop das habe ich leider nicht. Laut dem Datenblatt des WS2812b müssen die Timings folgendermassen sein Seite 3 https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf In der Lib ist beschrieben das ein Nop ca. 400ns delay macht also setze ich die Zeit auf WS2812 ws(D3, 24, 1, 2, 2, 1); Könntet ihr mir weiterhelfen wie ich am besten weiterkomme ? Danke!
Ach ja was ich auch noch gemacht habe sind folgende Änderungen https://www.mikrocontroller.net/articles/WordClock_mit_WS2812#STM32F401RE_Nucleo_und_STM32F411RE_Nucleo
Einsteiger schrieb: > In der Lib ist beschrieben das ein Nop ca. 400ns delay macht Ich kenne Arduino Lib nicht, aber Arduino läuft mit 16MHz, ein Takt dauert demzufolge 62,5ns, in Assembler braucht ein NOP genau einen Takt, also 62,5ns. Warum das in Arduino C länger dauern sollte, ist mir schleierhaft. Und auch wie man 400ns mit 62,5ns ohne Rest teilt, müssen dir die Authoren erst mal erklären.
Marc V. schrieb: > Ich kenne Arduino Lib nicht, aber Arduino läuft mit 16MHz, ein Takt > dauert demzufolge 62,5ns, in Assembler braucht ein NOP genau einen > Takt, also 62,5ns. Warum das in Arduino C länger dauern sollte, ist > mir schleierhaft. > > Und auch wie man 400ns mit 62,5ns ohne Rest teilt, müssen dir die > Authoren erst mal erklären. Tut mir leid das ich das nicht vorher gesagt habe, aber ich arbeite mit dem Stm32F411 Mikrocontroller bzw dem nucleo board und nicht dem Arduino
Einsteiger schrieb: > Tut mir leid das ich das nicht vorher gesagt habe, aber ich arbeite mit > dem Stm32F411 Mikrocontroller bzw dem nucleo board und nicht dem Arduino LOL. Und da dauert ein NOP 400ns ?
:
Bearbeitet durch User
Ich weiß ja nicht genau wie der Compiler das übersetzt. Ich kann das gerade nicht messen, deswegen brauche ich ja euren rat
Einsteiger schrieb: > Ich weiß ja nicht genau wie der Compiler das übersetzt. Ich kann das > gerade nicht messen, deswegen brauche ich ja euren rat Ich auch nicht, aber NOP sollte NOP sein und auch so übersetzt werden. Und bei 100MHz ist NOP 10ns und nicht 400ns... Du kannst das aber in einem loop austesten.
Marc V. schrieb: > Ich auch nicht, aber NOP sollte NOP sein und auch so übersetzt > werden. > Und bei 100MHz ist NOP 10ns und nicht 400ns... > > Du kannst das aber in einem loop austesten. Hmm ist schwer das auszutesten, weil ich insgesamt vier parameter umändern kann und die können im Bereich von 1 bis 20 sein
Einsteiger schrieb: > Hmm ist schwer das auszutesten, weil ich insgesamt vier parameter > umändern kann und die können im Bereich von 1 bis 20 sein Nein, nur NOP in einem loop testen. Und schauen was in .lss steht.
Einsteiger schrieb: > Ich weiß ja nicht genau wie der Compiler das übersetzt. Das macht man ja auch unabhängig von der Übersetzung mit Timern. Insbesondere beim Stm32F411! Entweder mit DMA+UART oder DMA+SPI oder DMA+Bit-Banging. Schau mal, wie das z.B. bei der WordClock mit WS2812 mit dem STM32F411 gemacht wurde.
Also bei so einer Implementierung ist es auch eher Glückssache, dass es funktioniert. - Compilersettings - CPU-Clocks - Flash-waitstates - uvm Haben alle einen Einfluss auf das Timing. Gerade auf schnelleren CM4 wäre ich sehr skeptisch. Bitbanging ist auf AVR ein sinnvoller Ansatz. Bei den Cortexen wüde ich eher Hardwarelösungen einsetzten. Es gibt bereits etliche Beispiele zu STM32 im Netz. [code} // Begin bit-banging for (i = 0; i < FRAME_SIZE * __size; i++) { j = 0; if (__transmitBuf[i]){ __gpo = 1; for (; j < __oneHigh; j++) { __nop(); } __gpo = 0; for (; j < __oneLow; j++) { __nop(); } } else { __gpo = 1; for (; j < __zeroHigh; j++) { __nop(); } __gpo = 0; for (; j < __zeroLow; j++) { __nop(); } } } [/code]
Hi Tim, Du kennst Dich ja mit den WS2812 von allen hier wohl am besten aus. Ich traue mich kaum, was hinzuzufügen. Tim. schrieb: > Es gibt bereits etliche Beispiele zu STM32 im Netz. Am weitesten verbreitet scheint Timer-Channel + DMA zu sein. UART mit drei Bits pro Byte macht aber mehr Sinn, denke ich. > Bitbanging ist auf AVR ein sinnvoller Ansatz. > Bei den Cortexen wüde ich eher Hardwarelösungen einsetzten. War auch so gemeint: Timer-Hardware triggert DMA-Hardware. Damit bei einer defekten LED nicht zuviele LEDs 'dahinter' ausfallen, kann man z.B. 8 Bit mit Timer-DMA ins GPIO BSRR parallel ausgeben. Das meinte ich mit Bitbanging.
Torsten C. schrieb: > Schau mal, wie das z.B. bei der WordClock mit WS2812 mit dem > STM32F411 gemacht wurde. Ja danke sehr, ich suche gerade noch die Stelle wie da die Timer gesetzt werden. Ich habe es noch nicht gefunden..
OK, ich bin jetzt schon am verzweifeln.... ich finde in der Word Clock Projekt nicht die Lib. Ich möchte einfach eine Lib haben die ich bei meinem Mbed online editor mit einbinden kann und dann einfach die LEDS steuern kann. Sprich LED nummer XX soll in Farbe Rot leuchten ...
Einsteiger schrieb: > Sprich LED nummer XX soll in Farbe Rot leuchten ... Also:
1 | ws2812_set_led(uint_fast16_t n, WS2812_RGB * rgb) |
https://www.mikrocontroller.net/svnbrowser/wordclock24h/src/ws2812/ws2812.c?revision=28&view=markup#l295 Aber wie das im Mbed online editor geht? Vielleicht kann ein anderer helfen? Frank hat das mit EM::Blocks gemacht. Ich würde ja einen Inverter an den UART-TX anschließen und die Bits einfach ohne fremde Bibliotheken aus dem UART schieben, siehe auch: Beitrag "WS2812B über USB-UART ansteuern"
:
Bearbeitet durch User
Torsten C. schrieb: > Einsteiger schrieb: >> Sprich LED nummer XX soll in Farbe Rot leuchten ... > > Also:ws2812_set_led(uint_fast16_t n, WS2812_RGB * > rgb)https://www.mikrocontroller.net/svnbrowser/wordclock24h/src/ws2812/ws2812.c?revision=28&view=markup#l295 > > Aber wie das im Mbed online editor geht? > Vielleicht kann ein anderer helfen? > > Frank hat das mit EM::Blocks gemacht. > > Ich würde ja einen Inverter an den UART-TX anschließen und die Bits > einfach ohne fremde Bibliotheken aus dem UART schieben, siehe auch: > Beitrag "WS2812B über USB-UART ansteuern" Danke erst einmal vorab... Ich weiß nicht warum, aber ich bekomme es nicht hin über eclipse den STM zu programmieren.. -.- Deswegen habe ich mich für die mbed online variante entschieden. Ich habe es nach der Anleitung probiert... http://www.carminenoviello.com/2014/12/28/setting-gcceclipse-toolchain-stm32nucleo-part-1/
probiere mal das 'cylon' Beispiel in mbed, hatte bei mir auf Anhieb mit einer 300er Kette funktioniert: https://developer.mbed.org/users/AndyA/code/cylon/ du must das die chainLen auf deine 24 setzen und im main code in der initialisierung die 3 Ketten auf Längen von zB 6..8 stellen.
Nachtrag: die benutzte wsDrive Lib arbeitet mit SPI, du musst also einen SPI MOSI Pin am Nucleo benutzen. Die (Burst)SPI Variante ist besser weil die nicht die ganze CPU blockiert.
js schrieb: > probiere mal das 'cylon' Beispiel in mbed, hatte bei mir auf Anhieb mit > einer 300er Kette funktioniert: > https://developer.mbed.org/users/AndyA/code/cylon/ > > du must das die chainLen auf deine 24 setzen und im main code in der > initialisierung die 3 Ketten auf Längen von zB 6..8 stellen. hmmm... irgendwie bin ich anscheinend auch dafür zu blöd hier mein Programmcode
1 | #include "mbed.h" |
2 | #include "wsDrive.h" |
3 | |
4 | // update period in ms |
5 | #define updatePeriod 100 |
6 | // number of LEDs |
7 | #define chainLen 24 |
8 | |
9 | //DigitalIn dummy(D11,D11); // first activate the pulldown on the pin. |
10 | wsDrive ledDriver(D11,D12,D13); // create the SPI bus. You can normally list the MISO and CLK as NC but some mbed library versions don't like that |
11 | |
12 | // pixel storage buffer |
13 | pixelInfo pixelData[chainLen]; |
14 | |
15 | Timer updateRateTimer; |
16 | |
17 | void blankBuffer(pixelInfo *Ptr) |
18 | { |
19 | memset( (void *)Ptr, 0, chainLen*sizeof(pixelInfo) ); |
20 | } |
21 | |
22 | void setPixel(unsigned int index, pixelInfo *colourToUse) { |
23 | if (index < chainLen) { |
24 | pixelData[index].R = colourToUse->R; |
25 | pixelData[index].G = colourToUse->G; |
26 | pixelData[index].B = colourToUse->B; |
27 | } |
28 | } |
29 | |
30 | void clearPixel(unsigned int index) { |
31 | if (index < chainLen) { |
32 | pixelData[index].R = 0; |
33 | pixelData[index].G = 0; |
34 | pixelData[index].B = 0; |
35 | } |
36 | } |
37 | |
38 | int main () { |
39 | |
40 | int litLed = 7; |
41 | |
42 | pixelInfo colour; |
43 | colour.R = 0x80; |
44 | colour.G = 0x00; |
45 | colour.B = 0x00; |
46 | |
47 | // Tell the driver where the data is stored |
48 | ledDriver.setData(pixelData, chainLen); |
49 | |
50 | // Set the buffer to the pattern we want |
51 | blankBuffer(pixelData); |
52 | setPixel(litLed, &colour); |
53 | |
54 | updateRateTimer.start(); |
55 | while (true) { |
56 | |
57 | ledDriver.sendData(); // send the LED data |
58 | |
59 | // modify the buffer ready for the next update |
60 | clearPixel(litLed); |
61 | litLed++; |
62 | if (litLed == chainLen) |
63 | litLed = 0; |
64 | setPixel(litLed, &colour); |
65 | |
66 | // wait until the correct time since the last update... |
67 | while (updateRateTimer.read_ms() < updatePeriod) { |
68 | } |
69 | |
70 | updateRateTimer.reset(); |
71 | } |
72 | } |
Aber danke schon einmal vorab... Wie beschrieben, setze ic hdie Chainlength auf 24 und in der Init die Variable ... Ich habe auch mit dem Ohmmeter mal nachgemessen , die Data in Leitung der Leds hat kontakt mit dem Mosi Pin des uC
Ich habe es sowohl mit und Ohne DigitalIn dummy(D11,PULLDOWN); // first activate the pulldown on the pin. ausprobiert
Also ich bekomme zwa rmit der Lib die LEDs eingeschaltet, aber kann sie nicht in der Farbe Variieren.... Bei mir leuchten alle LEDS WEiß und ich muss anstelle der Chain length von 24 eher 48 angeben, damit alle leuchten
Wenn Du noch keinen hast, könntest Du Dir einen ebay 272155971624 besorgen und mal nachmessen, woran es liegt.
Einsteiger schrieb: > Also ich bekomme zwa rmit der Lib die LEDs eingeschaltet, aber kann sie > nicht in der Farbe Variieren.... dein Code sieht ok aus, der dummy In kann weg. Habe mir die mbed Lib für den F411RE angesehen, das Problem ist das der SPI Clock nur grob über den Prescaler eingestellt wird. Das Timing ist korrekt wenn der 2,4 MHz beträgt, die Lib rundet den aber auf 1,56 MHz ab. Mit dem nächstkleineren Prescaler bist du bei 3,13 MHz, das gibt Bitzeiten von 320 / 640 ns. Auch noch ausserhalb der Spec und ohne Gewähr das es geht, aber das wäre eine einfache Änderung: in wsDrive.cpp
1 | void wsDrive::sendData() |
2 | {
|
3 | // frequency(2400000); // on STM32F411RE rounded to 1560000 Hz
|
4 | frequency(3130000); // test, only for STM32F411RE |
5 | format(12); |
6 | setFormat(); |
Für eine saubere Lösung mit dem SPI müsste man den Takt anders herleiten. Ich hatte die Lib mit einem LPC Board benutzt, da wird der Takt genau auf die gewünschte Frequenz gestellt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.