WS2812 mit Nucleo und Lib

Gast #4690054
Lesenswert?

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!
(Firma: Vescomp) #4690155
Lesenswert?

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.
Gast #4690160
Lesenswert?

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
Gast #4690291
Lesenswert?

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
#4690355
Lesenswert?

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]
Persönliche Seite #4690386
Lesenswert?

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.
Gast #4690702
Lesenswert?

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 ...
Persönliche Seite #4690712
Lesenswert?

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"
Gast #4690797
Lesenswert?

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/
Gast #4691081
Lesenswert?

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
Gast #4691227
Lesenswert?

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
Gast #4691975
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren