mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik WS2812 mit Nucleo und Lib


Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja was ich auch noch gemacht habe sind folgende Änderungen

https://www.mikrocontroller.net/articles/WordClock...

Autor: Marc V. (Firma: Vescomp) (logarithmus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Marc V. (Firma: Vescomp) (logarithmus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß ja nicht genau wie der Compiler das übersetzt. Ich kann das 
gerade nicht messen, deswegen brauche ich ja euren rat

Autor: Marc V. (Firma: Vescomp) (logarithmus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Marc V. (Firma: Vescomp) (logarithmus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tim  . (cpldcpu)
Datum:

Bewertung
0 lesenswert
nicht 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]

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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..

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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/wordclo...

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
Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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/wordclo...
>
> 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-...

Autor: js (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: js (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
 #include "mbed.h"
 #include "wsDrive.h"

 // update period in ms
 #define updatePeriod 100
  // number of LEDs
 #define chainLen 24

 //DigitalIn dummy(D11,D11); // first activate the pulldown on the pin.
 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

 // pixel storage buffer
 pixelInfo pixelData[chainLen];

 Timer updateRateTimer;

 void blankBuffer(pixelInfo *Ptr)
 {
    memset( (void *)Ptr, 0, chainLen*sizeof(pixelInfo) );
 }

 void setPixel(unsigned int index, pixelInfo *colourToUse) {
   if (index < chainLen) {
     pixelData[index].R = colourToUse->R;
     pixelData[index].G = colourToUse->G;
     pixelData[index].B = colourToUse->B;
   }
 }

 void clearPixel(unsigned int index) {
   if (index < chainLen) {
     pixelData[index].R = 0;
     pixelData[index].G = 0;
     pixelData[index].B = 0;
   }
 }

int main () {

  int litLed = 7;

  pixelInfo colour;
  colour.R = 0x80;
  colour.G = 0x00;
  colour.B = 0x00;

  // Tell the driver where the data is stored
  ledDriver.setData(pixelData, chainLen);

  // Set the buffer to the pattern we want
  blankBuffer(pixelData);
  setPixel(litLed, &colour);

  updateRateTimer.start();
  while (true) {

    ledDriver.sendData(); // send the LED data

    // modify the buffer ready for the next update
    clearPixel(litLed);
    litLed++;
    if (litLed == chainLen)
      litLed = 0;
    setPixel(litLed, &colour);

    // wait until the correct time since the last update...
    while (updateRateTimer.read_ms() < updatePeriod) {
    }

   updateRateTimer.reset();
   }
}

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

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe es sowohl mit und Ohne

DigitalIn dummy(D11,PULLDOWN); // first activate the pulldown on the 
pin.

ausprobiert

Autor: Einsteiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Torsten C. (torsten_c) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du noch keinen hast, könntest Du Dir einen ebay 272155971624 
besorgen und mal nachmessen, woran es liegt.

Autor: js (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
void wsDrive::sendData()
{
    // frequency(2400000); // on STM32F411RE rounded to 1560000 Hz
    frequency(3130000);    // test, only for STM32F411RE
    format(12);
    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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.