LEDs, LEDs, LEDs, …

Nachdem wir im letzten Artikel eine einzige LED mit einem 555 Timer haben blinken lassen, wird es Zeit für mehr LEDs, viel mehr LEDs!!!

Viele kennen vermutlich die WS2812B LED Streifen, manchmal auch Neopixel genannt. Diese LEDs sind sehr speziell, da über eine einzige Datenleitung praktisch beliebig viele LEDs angesteuert werden können. So habe ich zum Beispiel bei meiner Wortuhr eine einzige Datenleitung genutzt um die 114 LEDs anzusteuern. Das funktioniert, da in jeder einzigen LED ein kleine Chip eingebaut ist, der die ersten drei empfangenen Bytes für sich selbst beansprucht und alle anderen Daten danach weiterleitet an die nächste LED.

Nun gab es leider keine Library, für Forth und ich setzt in letzter Zeit nur noch auf Forth auf STM32 Mikrocontroller. Nun denn, schreiben wir halt selbst eine Library. Dazu war es wichtig zuerst das Format der übertragenen Daten zu verstehen. Zum Glück gibt es im Internet bereits gute Beschreibungen.

Ich wollte aber nicht die einzelnen Bits *von Hand* übertragen, wie es im oben verlinkten Artikel gemacht wird. Mein Ziel war es, dass der Mikrocontroller selbstständig die Daten überträgt und das im Hintergrund. Zwei Technologien sind dazu notwendig.

SPI: „Serial Peripheral Interface“ ist gedacht zur Kommunikation mit anderen ICs auf der Platine. Die Geschwindigkeit ist super (mehrere MHz) und die Unterstützung durch Hardware ist gegeben. SPI ist in der Lage ein mit WS2812B kompatibles Bitmuster auszugeben. Bei 4.5MHz SPI-Rate wird das Bitmuster 110 als eine 1 gesehen von den Neopixel und das Bitmuster 100 als eine 0. Heisst also, dass wir 3x mehr Daten schicken müssen wegen dieser Kodierung – kein Problem für einen STM32 mit 64kB RAM.

DMA: „Direct Memory Access“ erlaubt einem Mikrocontroller im Hintergrund Aufgaben abzuarbeiten, ohne die CPU zu belasten. Und genau das kommt zum Einsatz um die im Arbeitsspeicher abgelegten Bitmuster direkt auf dem SPI Bus auszugeben.

Der DMA Controller kann die Daten nicht mehr verändern, das heisst, diese müssen genau so im Arbeitsspeicher liegen, wie sie ausgegeben werden. Also muss auch im Arbeitsspeicher bereits dieses 3-Bit Muster für jedes Bit abgelegt werden. Aber wie bereits erwähnt hat der STM32F103 genügend Arbeitsspeicher um auch so noch über Tausend LEDs anzusprechen.

SPI für WS2812B
SPI für WS2812B

Das Bildschirmfoto oben zeigt, wie jeweils 8x 3-Bit als ein Byte angesehen werden von den LEDs. Wer kann mir sagen, was für eine Farbe diese LED zeigt?

Fazit

Das Schreiben so einer Library für Forth war für mich ein guter Wiedereinstieg in Forth nach einer längeren Pause. Auch war es spannend zum ersten Mal DMA für solch eine Aufgabe einzusetzen. Ich bezeichne die aktuelle Version dieser Library als 1.0 – sie läuft, hat aber Potenzial für Verbesserungen. Die Datei liegt auf Github. Und wurde für die Forth-Laufzeitumgebung von jeelabs.org geschrieben.

Verbesserungen?

Natürlich sind immer Verbesserungen möglich. Eine Idee ist, den DMA-Controller in den Cycle-Mode zu schalten und nur immer die selben 18 Bytes auszugeben. Da der DMA-Controller einen Interrupt auslösen kann beim Erreichen der Mitte und dem Ende des Speicherbereichs könnte man immer jeweils die nächsten Bytes in den gerade ungenutzten Bereich des DMA-Bereiches übertragen. Das ginge ungefähr so:

  1. Die ersten beiden LEDs in das 3-Bit Format für die SPI Ausgabe konvertieren und in die 18 Bytes DMA-Bereich schreiben.
  2. DMA-Übertragung starten
  3. Nun folgt der Mid-Transfer Interrupt, sobald die ersten 9 Bytes übertragen wurden. In diesem Interrupt Handler werden nun also die ersten 9 Bytes ausgetauscht mit den 9 Bytes für die dritte LED.
  4. Später folgt der End-Transfer Interrupt, wenn auch die zweiten 9 Bytes übertragen wurden. Der DMA-Controller ist im Cycle-Mode, beginnt also sofort von vorne mit den eben geschriebene Bytes der dritten LED. Wir nutzen den Interrupt Handler zum Schreiben der vierten LED in den zweiten Teil des DMA-Memories.
  5. usw… bis alle LEDs übertragen wurden.

So braucht man nicht mehr 9 Bytes Arbeitsspeicher pro LED sondern nur noch 3 Bytes (ein Byte pro Grundfarbe). Dafür hat die CPU mehr zu tun, da diese alle 3.2µs ein neues Byte bereit haben muss für den Transfer. Das sind aber über 2000 CPU-Zyklen bei der 72MHz CPU und sollte gut reichen. Aber ob das der Aufwand wert ist für diese paar WS2812B LEDs?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

0 Shares
Teilen
Twittern
Teilen