Forum: Mikrocontroller und Digitale Elektronik WS2811 mit SPI(atmega 2560)


von Dominic K. (domi1997)


Lesenswert?

Guten Tag zusammen.
Ich habe zwar Erfahrungen mit dem Programmieren von Atmel Prozessoren, 
jedoch habe ich nie mit spi gearbeitet. Da ich jedoch eine Aufgabe habe, 
welche sehr Zeit Relevant ist dachte ich daran den WS2811 per SPI 
anzusteuern um den Rest nicht auszubremsen. Nun meine Recherche hat mich 
an viele Orte gebracht wo ich zum beispiel die FastLed librarie fand. 
Doch scheint dies nur für Arduino zu sein. Bzw habe ich weder 
herausgefunden wie ich den IC wähle und vorallem gab es fehler beim 
Kompilieren, dass dateien Fehlen.

von Horst (Gast)


Lesenswert?

Dominic K. schrieb:
> Ich habe zwar Erfahrungen mit dem Programmieren von Atmel Prozessoren,
> jedoch habe ich nie mit spi gearbeitet

Warum nimmst Du dann nicht eine echte Anwendung mit SPI?
Der WS2811-Bus hat wenig mit SPI zu tun (ok, er ist auch seriell ...) 
und Du mußt das Hardware-SPI im AVR ganz schön verbiegen, damit das 
irgendwie paßt.
Ist meiner Meinung nach der falsche Weg SPI kennen zu lernen.

von Dominic K. (domi1997)


Lesenswert?

Gäbe es den eine andere Hardware serielle Schnittstelle in der 
Atmegaserie welche besser passt? Mit einem PWM wäre wohl eher aufwändig. 
Und der ws2811 ist hauptbestandteil des ganzen also kann ich ihn nicht 
einfach weglasen.

von c-hater (Gast)


Lesenswert?

Dominic K. schrieb:

> Gäbe es den eine andere Hardware serielle Schnittstelle in der
> Atmegaserie welche besser passt?

Ja, die UART im SPI-Modus (sofern man eine solche hat).

Damit hat man die höchstmögliche Toleranz gegen Latenzprobleme, wegen 
des Double-Buffer der UART.

Leider verfügen die älteren ATMegas oft zwar über eine oder gar mehrere 
UARTs, die haben aber noch keinen SPI-Modus...

von Tom (Gast)


Lesenswert?

habe mich zwar noch nie mit WS2811 beschäftigt, aber soweit ich die 
Datenübertragung des WS2811 verstanden habe wird ein HIGH mit einem 
Langen HIGH und kurzem LOW und ein LOW mit einem kurzen HIGH und einem 
langen LOW auf dem BUS des WS2811 dargestellt. Wenn das nicht so sein 
sollte und ich mich geirrt habe, dann vergiss das folgende...

Wenn man SPI nimmt, könnte man "vielleicht" das so gestalten:
Jedes benötigte WS-BUS Bit wird aus 3 SPI Bits gebildet. Dann hat man 
eben für zu sendende 24Bit 72Bit im Speicher, die über die SPI gesendet 
werden. Wird ein HIGH auf dem WS-BUS benötigt sendet SPI 1,1,0 und Wenn 
ein LOW auf dem WS-BUS benötigt wird, dann sendet SPI 1,0,0 solange bis 
alle 72 Bits (also für den WS-BUS dann nur 24Bit!) übertragen sind. Das 
bedeutet nach 9 Bytes sind die 24Bit WS-BUS übertragen. Es muss dann nur 
noch das Timing, also die Zeitspanne der 3 SPI Bits für den WS-BUS 
passen. Ob man die SPI allerdings so genau auf das Timing des WS-BUS 
dann einstellen kann müsste man halt mal ausprobieren.

Wäre vielleicht eine Möglichkeit. Ansonsten könnte man das ganze 
natürlich auch per PWM machen. Eine Spezielle Schnittstelle an einem 
ATmega, die das Format des WS-Bus hat, kenne ich nicht.

von Horst (Gast)


Lesenswert?

Tom schrieb:
> Wäre vielleicht eine Möglichkeit.

So in der Art machen das die SPI-Implementationen für die WS2811. Das 
Timing ist bei denen auch nicht ganz so kritisch wie bei den 
integrierten ws2812, warscheinlich weil die 400 und 800kHz können.

von pitschu (Gast)


Lesenswert?

Ich beutze für die WS2811/12 immer eine UART im 7N1 Modus mt negiertem 
Pin. Da das WS2811 Protokoll immer mit einem HIGH startet und einem LOW 
endet sind das Startbit und das Stopbit schonmal korrekt. Die 7 
Datenbits bilden dann 3 zu übertragende Bits (Startbit +2, 3 Datenbits, 
2 Daten + Stopbit). Das ganze mit 2.4Mbaud ergibt 800kHz Bitrate für die 
LEDs. Funktioniert perfekt bei minimalem Softwareaufwand.

von Ben W. (ben_w)


Lesenswert?

hab für die WS2812B auch ein SPI verwendet, aber mit einem STM32 nicht 
atmel.
War ein wenig verbiegung notwendig, ein WS2812B bit enstrpicht 4 SPI 
bits, dafür kann ich aber bequem DMA verwenden

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Ben W. schrieb:
> hab für die WS2812B auch ein SPI verwendet, aber mit einem STM32 nicht
> atmel.
> War ein wenig verbiegung notwendig, ein WS2812B bit enstrpicht 4 SPI
> bits, dafür kann ich aber bequem DMA verwenden

 Ja, mache ich genau so.
 Nachteil :
    Pro LED werden 15 Byt RAM gebraucht.
 Vorteile :
    Es ist viel einfacher zu kodieren als 3-bit Blödsinn.
    Es ist Fire-and-forget - CPU merkt nichts von der Ausgabe.
    Es läuft ohne Probleme mit 8MHz SPI, also 1MHz für WS2812.

 170 LEDs werden in etwa 4ms rausgefeuert, entspricht fast 250Hz.
 Und die dafür nötigen 2,5KB RAM kann ich sogar bei einfachsten
 Blue Pill ganz leicht verschmerzen - bei mindestens 20KB RAM...

 Ohne DMA lohnt sich der ganze Zirkus mit SPI bzw. UART kaum - da ist
 Bitbanging ganz einfach schneller und braucht zudem nur 3 Byt pro LED.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Marc V. schrieb:
> Pro LED werden 15 Byt RAM gebraucht.

Es geht auch sparsamer auf dem STM32. Man nehme:

  - einen Timer
  - zyklischen DMA-Transfer für jeweils 2 LEDs
  - ISR, welche den DMA-Buffer nach dem halben Transfer (also nach
    Datenübertragung für 1 LED) nachfüllt.

RAM-Bedarf: 48 Bytes - unabhängig von der Anzahl der LEDs.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Frank M. schrieb:
> - ISR, welche den DMA-Buffer nach dem halben Transfer (also nach
>     Datenübertragung für 1 LED) nachfüllt.

 Der Sinn (DMA) ist aber gerade in dem Fire-and-forget Prinzip. Wenn
 ich alle paar us irgendeine ISR anspringen muss, wird das Ganze
 ziemlich ineffizient, oder ?

> RAM-Bedarf: 48 Bytes - unabhängig von der Anzahl der LEDs.

 Pro LED braucht man auf jeden Fall 3 Bytes, ob mit oder ohne DMA.
 RAM ist bei STM32 genügend vorhanden, aber Zeit (wie bei allen
 anderen uC) ist (fast) nie ausreichend vorhanden.
 Wenn man mit 1:4 bit SPI arbeitet, wird der SPI-Array zuerst in einem
 Rutsch (auch per DMA) mit Nullen (0x88) aufgefüllt, danach werden nur
 die entsprechenden log.1 bits (bzw. Nibbles in konkretem Fall) gesetzt.
 Das geht unheimlich schnell, mindestens 2 Mal so schnell wie mit 3-bit
 Quälerei. Danach wird DMA abgefeuert - und vergessen.

 Natürlich kann das jeder machen wie es ihm beliebt und so lange es
 richtig funktioniert ist es auch in Ordnung, nur kommen die Probleme
 meistens wenn man das Ganze nachträglich noch mit irgendeiner Funktion
 ergänzen will, welche womöglich auch mit ISR arbeitet und da bei STM32
 die Interrupts Prioritäten haben...

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Marc V. schrieb:
> Der Sinn (DMA) ist aber gerade in dem Fire-and-forget Prinzip. Wenn
>  ich alle paar us irgendeine ISR anspringen muss, wird das Ganze
>  ziemlich ineffizient, oder ?

Kommt darauf an, was die ISR dafür noch veranstalten muss, um die 
DMA-Werte zu berechnen.

Im Projekt WordClock mit WS2812 hatte ich zunächste alle 388 LEDs 
(288 fürs Display, 100 für das Ambilight) mit einem Riesen-DMA-Buffer 
gefüttert - so wie von Dir präferiert. Das war bei RGBW-LEDs (hier hast 
Du sogar 4 Farben) eine ziemliche Speicherverschwendung, so dass dann 
inkl. Animationen und anderen Spielereien plötzlich die 20KB RAM eines 
STM32F103C8T6 fast aufgebraucht waren.

In diesem Falle hat der Wechsel auf einen zirkularen DMA-Buffer 
jedenfalls eine Menge gebracht. Die Zeit, welche die ISR da verbraucht, 
um den DMA-Buffer kontinuierlich zu füttern, kann man dabei wirklich 
vernachlässigen. Von "ineffizient" kann da keine Rede sein. Im 
Gegenteil: Durch das nun mögliche Double-Buffering wurde das ganze 
wesentlich effizienter: Während die DMA den alten Ringbuffer noch 
abarbeitet, kann das Hauptprogramm schon den nächsten Frame für alle 388 
LEDs berechnen, z.B. für Animationen und Fading.

Das Double-Buffering wäre mit einer Verdopplung des Riesen-DMA-Buffers 
nicht mehr möglich gewesen. Manchmal kann man mehr durch geschickte 
Programmierung rausholen als durch brachialen Einsatz von RAM. Natürlich 
nicht generell, in diesem speziellen Fall aber schon. ;-)

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Frank M. schrieb:
> Manchmal kann man mehr durch geschickte
> Programmierung rausholen als durch brachialen Einsatz von RAM. Natürlich
> nicht generell, in diesem speziellen Fall aber schon. ;-)

 Wenn du von der WordClock redest, ja, stimme ich zu.

 Wir machen z.Zt. ein Projekt mit 512 LEds und verwenden immer noch
 DMA mit 1:4 SPI. Es braucht zwar 512 * 15 + 1536 = 9KB, aber es sind
 immer noch 11KB RAM übrig und 70Hz Refresh Rate ist locker zu schaffen.
 LED-Array ist double-buffered - deswegen die zusätzlichen 1,5KB RAM,
 SPI-Array aber nicht. LED-Arrays werden abwechselnd von der SD-CARD
 per DMA eingelesen und danach nach SPI-Array ausgerollt. Selbst das
 wäre nicht nötig, aber SD-Cards sind manchmal zickig - deswegen.
 STM32 merkt aber kaum etwas davon - von den 14,3ms pro Frame ist die
 CPU höchstens 1-2% der Zeit damit beschäftigt.

 Und 98% der Zeit für andere Aufgaben frei zu haben ist meistens viel
 wichtiger als 50% des RAMs frei zu haben, zumal es für nicht benutzten
 RAM keinen Bonus gibt.

 Irgendwo ist da natürlich eine Grenze, aber solange die nicht erreicht
 ist, werde ich versuchen, den ganzen Zirkus so einfach wie nur irgend
 möglich zu halten...

: Bearbeitet durch User
von Ben W. (ben_w)


Lesenswert?

Frank M. schrieb:
>
> Kommt darauf an, was die ISR dafür noch veranstalten muss, um die
> DMA-Werte zu berechnen.
>


klingt interessant, muss ich mir mal genauer anschauen

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
Noch kein Account? Hier anmelden.