Forum: PC-Programmierung Kompression für RGB LED Datenstrom


von tecfreak (Gast)


Lesenswert?

Hallo,

ich versuche aktuell ein System auszuarbeiten für das drahtlose 
Ansteuern von WS2812b RGB Stripes auf Basis eines nRF24L01.
Die Idee dahinter ist mit Hilfe eines potenten Masters (Raspi & Co.) 
mehrere Slaves innerhalb eines Raums über eine auf den nRFs basierenden 
Funkstrecke mit einem RGB Datenstrom zu versorgen. Aus Kostengründen 
steht den Slaves max. eine Cortex-M0 MCU zur verfügung ala. STM32F1 
(~1€) oder wenn nötig eine M3 ala LPC1343 (~2€).

Dabei würde es sich ja anbieten gleich ein Datenkompression zu 
implementieren. Die Komprimierung darf auch gerne etwas CPU-Zeit auf dem 
Master beanspruchen. Die Dekompression dürfte jedoch nicht all zu viele 
CPU-Cycles beanspruchen um aus den komprimierten Daten ein Byte-Array 
aufzubauen welches dann zur Generierung des Ws2812 Signals genutzt 
werden soll. Hinzu kommt noch die Beschränkung der MCUs auf 8KB Ram 
wovon ein großer Teil für das Byte-Array zur Verfügung stehen sollte um 
möglichst viele LEDs über einen Slave ansteuern zu können.

Nun stell sich die Frage wie solch eine Kompression aussehen sollte um 
stets so wenig Bytes übertragen zu müssen wie es nur geht und ohne dabei 
die Slave MCUs mit der Dekompression zu überfordern.

Jemand eine Idee?

von Pedro C. (blaugelbweiss)


Lesenswert?

Es kommt auf die zu übertragenden Daten an, ob sich Kompression 
überhaupt lohnt. Wenn sie eher zufällig bzw. gleichverteilt sind, wird 
die Kompressionsrate gegen null gehen und man spart rein gar nichts. 
Wenn hingegen einzelne Zeichen sehr häufig auftreten und andere sehr 
selten, dann bringt es möglicherweise etwas.

Eine Huffman-Kodierung wäre ein recht einfaches Verfahren, das auch 
nicht schwer zu implementieren ist. Dabei werden für oft vorkommende 
Zeichen weniger Bits verwendet, dafür braucht man für seltenere Zeichen 
mehr. Programmierbeispiele gibts mit Sicherheit im Netz irgendwo...

von Eric B. (beric)


Lesenswert?

Ansonsten RLE oder LZW (was auch in zB GIF verwendet wird). Der letzter 
komprimiert besser, braucht aber etwas mehr Rechenleistung und RAM beim 
Dekomprimieren.

http://en.wikipedia.org/wiki/Run-length_encoding
http://en.wikipedia.org/wiki/Lempel-Ziv-Welch

von tecfreak (Gast)


Lesenswert?

Danke euch beiden für den Input. Bin selber noch auf miniLZO gestoßen 
was sich uU. auch eignen könnte.

Ich merke schon - das ist nicht so einfach einen passenden 
Kompressionsalgo zu finden um den Anforderungen gerecht zu werden bzw. 
es stellt sich die Frage, wie Pedro schon angemerkt hat, ob eine 
Kompression überhaupt Sinn macht.

Man stelle sich einen RGB Stripe vor mit 1000 LEDs von denen jede in 
einem anderen Farbton leuchtet. Die bisher genannten 
Kompressionsverfahren würden idF. versagen. Für einfache Muster und 
Lauflichter wären diese zwar bestens geeignet, für komplexe/zufällige 
Farbverläufe jedoch wieder unbrauchbar.

Was jetzt die Slave MCU angeht, so habe ich bei aliexpress für ~1,50€ 
den STM32F103C8T6 gefunden. Mit bis zu 72MHz, 64KB Flash und satten 20KB 
SRAM wäre da einiges drin.


Trotzdem muss ich nun mein Vorhaben nochmal überdenken.
Ziel des Projekts ist es mit möglichst günstiger Hardware (idF. nRF24L01 
+ Cortex M0/M3 MCU) ein Alternative zu DMX und Co. zu entwickel zur 
drahtlosen Ansteuerung von RGB Lichtquellen und zwar möglichst vielen 
gleichzeitig (WS281x Stripes) mit einer Framerate von min. 25 o. 30 fps.

Dabei gibt es zwei Möglichkeiten:

1. RGB Stream
Das dürfte die unkompliziertere Implementierung sein und zugleich leicht 
erweiterbar da nur der Master sich um die Erzeugung des RGB Musters 
kümmern muss.
Die Daten lassen sich wie bereits festgestell nur bedingt komprimieren. 
Hier wäre sogar eine adaptive Kompression angebracht die je nach 
Effekt/Muster Huffman, RLE oder LZW/LZO nutzt. Bei komplexeren 
Effekten/Mustern müsste man die Kompression deaktiviert lassen wodurch 
sich die mögliche Anzahl der anzusteuernden LEDs nicht erhöht und dieser 
Umstand die Kompression idF. damit generell in Frage stellt.

Ich habe ausgerechnet, dass mit der nRF lib von TMRh20 ohne ACK es 
theoretisch möglich wäre bei 30fps ~2000 RGB LEDs anzusteuern. Das wäre 
schon mal mehr als das 10fache was mit einem DMX Universe möglich wäre 
und ohne der vergleichweise teuren Hardware und Kabelage.


2. Effekt-Lib auf jeder Slave-MCU vom Master aus getriggert
Dabei ensteht aber gleich das Problem, dass die Slaves untereinander 
Synchronisiert sein müssten. Das sollte aber mit einer Genauigkeit von 
<5mS möglich sein was auch schon ausreichend wäre.
Das System wäre schwiriger zu Pflegen da mit jeder Erweiterung auch die 
Slaves neu geflasht werden müssten. Zudem beschränk das System 
prinzipbedingt die gestalterischen Möglichkeiten was nur teilweise mit 
einem vergleichsweise hohen Programmieraufwand zu kompensieren wäre.
Was aber wiederum ein großer Vorteil wäre, wäre die fast belibig hohe 
Anzahl an ansteuerbaren LEDs.


Schätze beides zu implementieren und stattdessen beim Stream auf die 
Kompression zu verzichten wäre wohl am besten. Eine OTA Updatefunktion 
für die Effekte würde das ganze auch etwas pflegeleichter machen.

Glaube das mutiert langsam zu einem Mammutprojekt.

Hat evtl. jeman noch Input zu dem Vorhaben, auch wenn es jetzt OT wird?


Gruss
tec

von Vlad T. (vlad_tepesch)


Lesenswert?

Wie sehen denn die übertragenden Werte aus? sind die rohen PWM-Werte? 
Ansonsten spart es schon enorm, die Umrechnung Farbwert->PWM-Wert (wegen 
Linearisierung Helligkeit) auf dem Controller zu machen und die 
kleineren Werte zu übertragen.

von tecfreak (Gast)


Lesenswert?

@Vlad Tepesch
Die WS281X RGB Controller werden mit RGB Daten gefüttert (3x8Bit). Die 
PWM wird auch von diesen Controllern übernommen. Siehe dazu 
https://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/


Um die zu übertragene Datenmenge zu reduzieren ohne die Slave MCU zu 
überfordern, hatte ich jetzt eine weitere Idee.

Dazu bräuchte man nur ein simples Übertragungsprotokoll mit möglichst 
geringem Overhead und 4 verschiedene Modi für die Notation/Kompression 
der RGB Daten.

Ausgehend davon, dass beim nRF24L01 eine Frame (Brutto-Payload) max 32 
Byte lang sein darf und die Länge zur Laufzeit nicht verändert wird, 
also fix und nicht variabel ist, stehen abzüglich 2 byte für den Header 
30 Byte für Instruktionen und Daten zur Verfügung.


Aufbau des Headers:

8 bit - CRC8
1 bit - Frame-Type (1=preceding frame [PF]; 0=attendant frame [AF])
7 bit - n Frames (PF) / x Frame (AF) - (0-127)

Macht unterm Strich 2 Byte und damit theoretisch bis zu 1280 (128 Frames 
* 30 Byte payload / 3 Byte) ansteuerbare RGB-LEDs pro Slave bei im 
schlimmsten Fall nicht anwendbarer Kompression bzw. der initial 
Bild-Frame.

Das zweite Byte des Headers ist immer >0 wenn RGB Daten übertragen 
werden. Auf 0x0 gesetzt kann das Frame auch für andere Zwecke genutzt 
werden um z.B. Konfigurationsparameter vom Master aus zu übertragen, 
Resets auszulösen etc.


Kompressionsmodi:

1. RLE
2. 3 byte corresponding bitmask
3. 1 byte corresponding bitmask
4. plain RGB

Bei der "bitmask Kompression" (2. und 3.) geht es darum mit nur einem 
Bit zu indizieren ob sich für die jeweilige RGB-LED (2.) oder den 
jeweiligen Farbkanal (3.) zu den Werten der vorangegangen Bild-Frame 
etwas geändert hat. Der bitmask folgen dann dementsprechend nur die 
geänderten Werte und der Rest wird eingespart.

Wie die Notation der einzelnen Modi auszusehen hat muss ich mir noch 
überlegen. Auf jeden Fall soll immer stets der ganze Payload genutzt 
werden und die Instruktionsblöcke dann auf dem Slave aus einem kleinen 
Buffer heraus zusammengesetzt und anschließend gleich ausgeführt werden. 
Damit würde die Dekodierung/Dekompression praktisch on-the-fly 
vonstatten gehen sodass kurz nach dem Eintreffen des letzten Frame das 
RGB-Array vollständig wäre und die MCU gleich das Erzeugen des WS281x 
Signals anstoßen könnte.


Was haltet ihr von diesem Ansatz?

von Vlad T. (vlad_tepesch)


Lesenswert?

tecfreak schrieb:
> @Vlad Tepesch
> Die WS281X RGB Controller werden mit RGB Daten gefüttert (3x8Bit). Die
> PWM wird auch von diesen Controllern übernommen. Siehe dazu
> 
https://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/

das heißt aber nicht, dass diese 8bit eine Kennlinie abbilden, die unser 
Auge als Linear wahrnehmen würde.

sind diese 8bit einfach das PWM-Tastverhältnis würde es wahrscheinlich 
reichen pro Kanal 5bit zu übertragen

von Amateur (Gast)


Lesenswert?

Hast Du es nicht allzu eilig, so könnte man nur die Differenzen 
übertragen.

Schau' Dir die 3 Werte (RGB) an, stelle die jeweiligen Differenzen fest 
und pack' sie in ein Byte (z.B. sRRsGGsB). Sollte eine Farbe eine 
größere Abweichung als z.B. 1 oder 3 aufweisen, so muss der Master den 
Rest, in den nächsten Bytes, nachliefern.
Spart 2/3 bei 8/8/8.

Sind die Änderungen größer, so gäbe es noch die Möglichkeit die 
Differenz in ein Wort zu packen z.B. -sRRRRsGGGGsBBBB. Dann ist die 
Ersparnis aber nur noch 1/3.

Die meisten Kompressionsalgorithmen benötigen Tabellen oder 
Baumstrukturen für die Kompression. Das ist nur nutzbar, wenn Du 
"Bilder" übertragen willst. Die kannst Du vorher nach Häufigkeiten 
durchforsten, eine Tabelle erstellen und dann nur noch die 
Kompressionswerte übertragen.

Viele Kompressionsalgorithmen "leben" aber davon, dass der nächste Wert 
z.B. in 4 Bit dargestellt werden kann.
Ich kenne aber kein Übertragungsverfahen, das mit variabler Datenlänge 
klarkommt. Auch müssen gelegentlich 9 oder 10 Bit übertragen werden.

Ist, wie gesagt, eine Frage der Geschwindigkeit.

Oder so.

von Vlad T. (vlad_tepesch)


Lesenswert?

man kann auch eine dynamische Huffmankodierung probieren (vorrausgesetzt 
der RAM reicht für die Tabelle und der Prozessor schafft die 
Bit-Fummelei).
Man geht von einem vorgegebenen Baum aus und passt den Baum auf beiden 
Seiten nach jedem übertragendem Symbol an.

Aber alle entropie-basierten Kompressionsalgorithmen haben das Problem, 
dass die Daten im Worstcase eben nicht komprimiert werden können und 
damit die Übertragungsbandbreite sprengen. Deswegen würde ich auf sowas 
verzichten und mir eine Variante aussuchen, die Unabhängig von den 
darzustellenden Daten die verfügbare Bandbreite auf jeden Fall nicht 
überschreitet.

von tecfreak (Gast)


Lesenswert?

Vlad Tepesch schrieb:
>
> das heißt aber nicht, dass diese 8bit eine Kennlinie abbilden, die unser
> Auge als Linear wahrnehmen würde.
>
> sind diese 8bit einfach das PWM-Tastverhältnis würde es wahrscheinlich
> reichen pro Kanal 5bit zu übertragen

Hab jetzt wegen der Darstellung der Farben etwas recherchiert und bin 
auf das fastLED Projekt gestoßen: 
https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors

Dort wird eine reduzierte HSV Farbpalette (rainbow) verwendet die weit 
aus besser geeignet ist als plain-RGB für die Effekt- und 
Ambientebeleuchtung.
Dabei stehen 256 Farbtöne, 256 Sättigungsstufen und 256 
Helligkeitsstufen zur Verfügung, was auch mehr als ausreichend ist.

Bei dem genannten HSV Modell kann man jetzt eigentlich davon ausgehen, 
dass sich schon mal die Helligkeit eher selten ändern wird und nicht 
übertragen werden muss und wenn doch, dann in den allermeisten Fällen 
für alle LEDs den gleichen Wert einnimmt (-> RLE).
Ähnlich dürfte sich das auch beim Farbton und bei der Sättigung 
verhalten.
Viele Effekte dürften meist immer nur mit einem dieser bedien Werte 
arbeiten.



Amateur schrieb:
> Hast Du es nicht allzu eilig, so könnte man nur die Differenzen
> übertragen.
>
> Schau' Dir die 3 Werte (RGB) an, stelle die jeweiligen Differenzen fest
> und pack' sie in ein Byte (z.B. sRRsGGsB). Sollte eine Farbe eine
> größere Abweichung als z.B. 1 oder 3 aufweisen, so muss der Master den
> Rest, in den nächsten Bytes, nachliefern.
> Spart 2/3 bei 8/8/8.
>
> Sind die Änderungen größer, so gäbe es noch die Möglichkeit die
> Differenz in ein Wort zu packen z.B. -sRRRRsGGGGsBBBB. Dann ist die
> Ersparnis aber nur noch 1/3.
>
> Die meisten Kompressionsalgorithmen benötigen Tabellen oder
> Baumstrukturen für die Kompression. Das ist nur nutzbar, wenn Du
> "Bilder" übertragen willst. Die kannst Du vorher nach Häufigkeiten
> durchforsten, eine Tabelle erstellen und dann nur noch die
> Kompressionswerte übertragen.
>
> Viele Kompressionsalgorithmen "leben" aber davon, dass der nächste Wert
> z.B. in 4 Bit dargestellt werden kann.
> Ich kenne aber kein Übertragungsverfahen, das mit variabler Datenlänge
> klarkommt. Auch müssen gelegentlich 9 oder 10 Bit übertragen werden.
>
> Ist, wie gesagt, eine Frage der Geschwindigkeit.
>
> Oder so.

Wäre auch ein sehr guter Ansatz und Rechenleistung sollte auf nem Cortex 
M0/M3 auch ausreichend da sein. Ob das in dieser Form bei dem o.g. HSV 
Farbmodell noch gut anwendbar ist muss man schauen. Würde jetzt aber 
sagen, dass Plain-RGB einfach keinen Sinn macht wenn man sich die 
Vorteile von HSV-rainbow anschaut. Man fährt besser, wenn die HSV Daten 
übertragen werden und die Wandlung von HSV nach RGB auf der Slave-MCU 
stattfindet.



Vlad Tepesch schrieb:
> man kann auch eine dynamische Huffmankodierung probieren
> (vorrausgesetzt
> der RAM reicht für die Tabelle und der Prozessor schafft die
> Bit-Fummelei).
> Man geht von einem vorgegebenen Baum aus und passt den Baum auf beiden
> Seiten nach jedem übertragendem Symbol an.
>
> Aber alle entropie-basierten Kompressionsalgorithmen haben das Problem,
> dass die Daten im Worstcase eben nicht komprimiert werden können und
> damit die Übertragungsbandbreite sprengen. Deswegen würde ich auf sowas
> verzichten und mir eine Variante aussuchen, die Unabhängig von den
> darzustellenden Daten die verfügbare Bandbreite auf jeden Fall nicht
> überschreitet.

Hast vollkommen recht und deswegen scheiden Huffman & Co. auch aus. 
Schon allein aus dem Grund, dass man bei der adaptiven Huffmankodierung 
aus zwangsläufig mit ACKs bei der Übertragung arbeiten müsste, da sich 
sonst jeder noch so kleine Übertragungsfehler fortpflanzen und den 
Quellsymbol-Baum zerstören würde.



So, was aber auf jeden Fall mal sinnvol wäre ist RLE zu implementieren. 
Gerade bei dem HSV Farbmodell lässt sich damit auch bei komplexeren 
Farbverläufen/Effekten immer noch sehr viel einsparen im Vergleich zu 
RGB.

Der Vorschlag von "Amateur" nur die jeweilige Differenz zu übertragen 
lässt sich auch auf HSV anwenden wobei ich hierbei wenn, dann auf eine 
leicht abgewandelte Form setzen würde.

Habe jetzt auch etwas genauer das Datenblatt zum nRF24L01 studiert und 
mir den Aufbau der Datenpakete angeschaut und wie diese behandelt 
werden.
So errechnet der nRF selbständig vor dem Versenden eine 1-2 Byte CRC und 
hängt sie and das Paket ran. Stimmt diese nach dem Empfang nicht, so 
wird das ganze Paket einfach verworfen und landet erst garnich im 
RX_FIFO Buffer. Für solche Fälle gibt es auch die Möglichkeit ACKs zu 
verschicken und im gegebenen Fall Retransmissions anzustoßen, aber das 
alles kostet sehr sehr viel Bandbreite. Verlorene Pakete müssen daher am 
besten auf Anwendungsebene behandelt werden.


Die drei Kanäle/Werte H, S und V nacheinander anstatt kombiniert zu 
übertragen sollte das ganze auch etwas vereinfachen. Das bedeutet, dass 
der Master für jeden Kanal erstmal einen separaten, komprimierten 
Datenstrom erzeugt und diese dann der Größe nach und beim kürzesten 
angefangen nacheinander überträgt.
Sobald am Slave das erste Frame für den 3. Kanal reinkommt, kann dieser 
anfangen zu dekomprimieren und nach RGB zu wandeln.



Der Header Aufbau:

7bit - n frame (0-63)
7bit - x frames (0-63)
2bit - color value (0=H; 1=S; 2=V; 3=n/a)


Kompressionsmodi:

0: uncompressed

1: RLE - 1 byte (0-255)
 Wert über eine definierte Länge

2: RLE-DIFF - 1 byte (0-255)
 Differenz zur vorangegangenen Bildframe über eine definierte Länge

3: 3bit DIFF - 1Byte 2x(+/- & 0-7) <50% Ersparnis
 sHHHsHHH  sSSSsSSS  sVVVsVVV

4: 4bit DIFF - 2Byte 3x(+/- & 0-15) <33% Ersparnis
 -sHHHHsHHHHsHHH  -sSSSSsSSSSsSSSS  -sVVVVsVVVVsVVVV


Mode-Byte:

3bit - compression mode (0-7)
5bit - iteration count (0-31)

Das Mode-Byte wird immer vorangestellt und beschreibt um welchen 
Kompressionsmodi es sich handelt und wie viele darauf folgenden 
Anweisungsblöcke/Werte dazu gehören.

Im Falle von RLE dienen die 5bit des Mode-Byte zur Längenangabe. Bei 
Länge >=31 folgt dem Mode-Byte ein Length-Byte und dann erst das 
Value/Diff-Byte.



Ich schätze, dass sich Dank HSV-rainbow und den Kompressionsmodi 
mindestens 50% der zu übertragenen Datenmenge einsparen lässt.
Einziger Nachteil dürfte der hohe Speicherverbrauch auf der Slave-MCU 
sein, denn man benötigt sowohl Speicher für die RGB Daten als auch für 
die HSV Daten. Für 1000 LEDs sind es ~6kB.


Kritik, Anmerkungen, Ideen?


Danke euch schon mal für den Input.

von Bart J. (tecfreak)


Lesenswert?

Kleine Korrektur,
beim Header liegt der Wertebereich bei 7bit natürlich bei 0-127 und 
nicht bei 0-63.
Das ergibt zwar maximal 11.136 LEDs (128*29*3) die sich so ansprechen 
ließen, aber dafür reicht weder die Bandbreite um eine gewisse Framerate 
zu halten noch reicht auf den meisten MCUs der RAM dafür.

von Wolfgang (Gast)


Lesenswert?

tecfreak schrieb:
> Dabei stehen 256 Farbtöne, 256 Sättigungsstufen und 256
> Helligkeitsstufen zur Verfügung, was auch mehr als ausreichend ist.

Das gilt aber nur bei Maximalhelligkeit oder bei reinen R/G/B-Farben.
Beim runterdimmen reduziert sich die Auflösung für Farbtöne und 
Sättigung.

von Bart J. (tecfreak)


Lesenswert?

Damit kann man aber denke ich mal immer noch leben. Sollte auf jeden 
Fall praktikabler sein für Raumbeleuchtung als reines RGB wo die 
Helligkeitsregelung nicht so einfach wäre und der Farbverlauf sehr 
ungleichmäßig ist im Vergleich zu HSV, besonders bei den Gelb- und 
Orangetönen.

von Martin S. (led_martin)


Lesenswert?

Bei HSV kann man sehr gut in den Helligkeits-Pfad eine Korrekturkurve 
einbauen, die die logarithmische Wahrnehmung der Helligkeit kompensiert, 
und danach halt mit mehr als 8 Bit weiterrechnen, die Ausgaben (PWM) 
sollte dann mindestens 10 Bit auflösen, besser 11 oder 12. Bei HSV 
verfälscht eine solche Korrektur auch nicht die Farben. Mit einer 
solchen Korrektur sind 8 Bit für die Helligkeit gut ausreichend. Für 
Farbe, und Sättigung reichen 8 Bit auch aus.

Mit freundlichen Grüßen - Martin

von benwilliam (Gast)


Lesenswert?

darf man noch fragen wie genau du die WS2812 dann mit dem Cortex-M0/M3 
ansteuerst?
wenn du die light lib verwendest, werden die ja per bitbanging 
angesteuert, was ordentlich CPU zeit kostet ...
ich nutze ebenfalls den STM32F103C8T6 für die WS2812B allerdings mit SPI 
und DMA, die LEDs sind tolerant genug, dass es noch gut funktioniert.
dafür wandle ich aber das RGB Array in ein "SPI freundlicheres" Array 
um, wobei 4 bits einem WS2812 bit entspricht. Evtl. liese sich die 
Umwandlung auch "on-the-fly" im SPI interrupt machen, was ne menge 
Speicher sparen würde aber etwas mehr die CPU belastet, sollte aber 
immer noch  deutlich weniger sein als mit bit banging.

ich habe leider noch keine Erfahrung mit den NRF24, allerdings frage ich 
mich hier die ganze zeit, was passiert bei Übertragungsfehlern? Wenn die 
frames einfach verworfen werden könnte es ja zum flackern kommen.
Wäre es da nicht sinnvoll mit Redundanz zu arbeiten?

evtl. reichen ja 32 verschiedene hellilgkeitstufen pro farbe schon aus.
Somit würde jede farbe mit 5 bits codiert sein und 3 bits als Redundanz. 
Dann wäre die kompression zwar dahin aber 1 bit fehler würden sich 
korrigieren lassen und 2 bit fehler zumindest erkennen

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Sollen nur einzelne Anweisungen oder ein kontinuierlicher Datenstrom 
gesendet werden?
Für einzelne Anweisungen könntest du eine Art Farbtabelle erarbeiten. 
Ein 8Bit Index für 256 verschiedene Farben, eine zweite für Effekte.

von Bart J. (tecfreak)


Lesenswert?

@Martin Schlüter

Hättest du dazu evtl. einen Link wo ich mich zu dem Thema etwas einlesen 
könnte?


@benwilliam

Also bitbanging kommt vermutlich nicht in Frage.
Dachte eher an diesen Ansatz: 
http://eliaselectronics.com/driving-a-ws2812-rgb-led-with-an-stm32/
Kombiniert mit einem Ringbuffer sollte auch der limitierende RAM kein 
Problem sein: https://github.com/tiltit/ws2812_dma
Hoffe nur, dass die CPU schnell genug ist den buffer fortlaufend zu 
befüllen.


Was die Übertragungsfehler angeht.
Beim nRF ist das so, dass wenn z.B. ein Bit gekippt ist der nRF das 
anhand der CRC feststellen kann und idF. das ganze Frame verwirft. 
Dieses Verhalten lässt sich auch nicht beeinflussen. Alternativ wäre es 
möglich mit ACKs zu arbeiten wodurch jedoch die Bandbreite von 
~200Kbyte/s auf 60-70KByte/s sinkt, denn jedes empfangene Frame muss ja 
erst quittiert werden bevor ein neues gesendet werden kann.
Daher habe ich mir überlegt mit einem Framecounter zu arbeiten wie 
weiter oben bei dem Protokoll-Entwurf beschrieben.
Kommen eine oder mehrere Frames nicht an muss sich die Slave MCU nur die 
fehlenden Frame-Nummern merken und diese mit nur einem Request zum Ende 
jeder Sequenz am Master erfragen und die Requests dann im Falle von 
weiteren Übertragungsfehlern so lange wiederholen bis alle Frames 
empfangen wurden und dies dem Master dann anschließend mitgeteilt werden 
kann der dann mit der neuen Sequenz loslegen kann.
Zu der Fehlerrate habe ich mal einen Blogeintrag gelesen (hab den Link 
leider nicht mehr), dass ~7 von 10.000 Frames verloren gehen. Also 
könnte man davon ausgehen, dass bei idealen Bedingungen ca. 1 von 1000 
Frames erneut gesendet werden muss was die max. Bandbreite theoretisch 
nicht nennenswert beeintrechtigen sollte.

Der nRF24L01 soll mit einem RFX2401C PA/LNA Frontend und einer 
omnidirektionalen Fractalantenne ( FR05-S1-N-0-001 ) kombiniert werden.



@Random
Diese Überlegung hatte ich auch und evtl. kann man das dann zusätzlich 
noch implementieren, aber die Hauptidee war eigentlich jeden einzelne 
LED mehrere Slaves/Empfänger von einem Master aus "bespielen" zu können.

Eine Effektbibliothek wäre aber auf jeden Fall ein großer Mehrwert. Bei 
64KB Flash des STM32F103C8T6 (evtl. "nur" 56KB abzüglich 8KB für einen 
optionalen Bootloader) sollte noch genügend Platz für viele 
Effektroutinen bleiben. Die Parameter der einzelnen Effekte könnte man 
dann zentral vom Master aus zur Laufzeit ändern (Farbton, 
Geschwindigkeit usw.) oder diese als Profile in einem EEPROM ablegen.

von Martin S. (led_martin)


Lesenswert?

Was man da so findet ist sehr theoretisch, ob das Dich einer praktischen 
Lösung näherbringt:

http://de.wikipedia.org/wiki/Gammakorrektur

http://de.wikipedia.org/wiki/Stevenssche_Potenzfunktion

http://de.wikipedia.org/wiki/Helligkeit

http://www.seebacher.de/ISYNET_MODULE/LED-Dimmer-LED-03E-PM-2200-DALI.html


Hast Du schon mal ein Bisschen mit LEDs, und PWM 'gespielt', wenn nicht, 
solltest Du das vielleicht tun, bevor Du an solch ein Projekt rangehst. 
Ein paar LEDs (Einfarbig / RGB) ein kleiner Mikrocontroller / Eval-Board 
und Steckbrett genügen.

Für Dein Projekt sind vorallem zwei Erkenntnisse wichtig: Wenn man z.B. 
8 LEDs mit (zahlenmäßig) gleichmäßig steigender PWM ansteuert, merkt man 
schnell, daß die Abstufung bei den ersten 3 LEDs recht grob ist, während 
man bei den letzten 3 LEDs fast keinen Unterschied sieht. Die sichtbare 
Änderung (8 Bit PWM angenommen) von Stufe 1 zu 2 ist größer als von 
Stufe 245 zu 255. Konsequenz ist, 'unten' ist's imer zu grob / stufig 
und im oberen Bereich braucht man gar nicht alle möglichen Werte, da man 
den Unteschied eh kaum sieht. Das kann man sich zur Datenreduktion, oder 
zur Steigerung der Qualität zu nutze machen.

Bei RGB muß man allerdings aufpassen, bei der Wahrnehmung von Farben 
entscheidet das physikalische Verhältnis der Anteile zueinander. Hat man 
also ein schönes Orange z.B. R: 100%, G: 30%, B: 0% und will das dunkler 
machen. muß man z.B. auf R: 50%, G: 15%, B: 0% gehen, damit der Farbton 
erhalten bleibt. Geht man mit den einzelnen Anteilen des RGB-Wertes nun 
über eine nichtlineare Umrechnung, verändert das den Farbton, und da 
kann HSV seine Stärke ausspielen, da es Farbton und Helligkeit 
voneinander trennt, da kann man mit dem Helligkeitswert über eine solche 
Kurve gehen, ohne daß sich der Farbton ändert. und dann kann man halt 
aus 3 8 Bit Werten für Farbe, Sättigung, und Helligkeit sinnvoll 12 Bit 
Werte für R, G, und B machen, und dabei die feinstufigkeit der 12 Bit 
ausnutzen (im unteren Bereich).

Wenn einem, zum experimentieren, die Gamma-Kurve zu kompliziert ist, 
eine Exponential-Funktion, bei der man den untersten Wert auf Null setzt 
funktioniert auch recht gut. Zur Berechnung solcher Tabellen benutze ich 
immer Open Office Calc, da kann man schön mit den Parametern spielen.

Es ist auf jeden Fall sinnvoll, da selbst ein Bisschen zu 'spielen'. Ein 
eigenes 'Gefühl' für solche Licht-Spielereien ist nicht durchs lesen von 
Wiki-Artikeln zu ersetzen.

Mit freundlichen Grüßen - Martin

von Bart J. (tecfreak)


Lesenswert?

Hallo Martin,

also selber habe ich mit LEDs noch nicht rumprobiert. Habe nur die 
üblichen 0815 Controller daheim die ich unbedingt gegen etwas qualitativ 
besseres austauschen möchte mit der Möglichkeit zur drahtlosen 
Vernetzung.
Dabei soll das ganze möglichst günstig zu realisieren sein wodurch DMX 
und artNET schon mal wegfallen.

Bei den WS281X LEDs kann ich keinen Einfluss drauf nehmen wie und mit 
welcher Genauigkeit die PWM generiert wird.
Jedoch kommen diese Stripes nur an wenigen Stellen zum Einsatz, sodass 
ein weiterer Controller nötig wird um auch normale RGB Stripes ansteuern 
zu können.
Ein kleinerer STM32 oder ein ATMEGA8a mit drei FETs sollten es tun.


Werde dann erstmal die Wiki Einträge studieren und meinen Arduino mit 
drei FETs als Experimentierplattform benutzen. Evtl. kann ich auch 
meinen Colorimeter (Spyder3) benutzen um Farbwerte & Co. auch 
verifizieren zu können.


Danke dir vielmals für die Infos. Das bringt für mich schon mal etwas 
Licht ins Dunkel :)


Gruss
Bart

von Martin S. (led_martin)


Lesenswert?

Ich habe mir mal dieses Datenblatt angesehen:

http://www.parallax.com/downloads/ws2812b-rgb-led-datasheet

http://auschristmaslighting.com/wiki_source/images/b/ba/WS2811.pdf


Da ist nur die Rede von 8 Bit / Farbe, über die Art der Umsetzung wird 
da nichts gesagt, ich vermute aber daß sie linear ist. Im Datenblatt zum 
WS2811 (Der Ansteuer Chip ohne LED) ist immerhin von PWM die Rede.

Mit freundlichen Grüßen - Martin

von Fabi (Gast)


Lesenswert?

Hallo,
schon mal über ESP8266 nachgedacht? Da gibt es schon code um ArtNet zu 
empfangen:

https://github.com/cnlohr/ws2812esp8266

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.