Forum: Mikrocontroller und Digitale Elektronik Frage zu IR-Remote+LED-Strips an AVR


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

ich möchte LED-Strips und einen Fernbedienungsempfänger gleichzeitig an 
einem AVR-Controller betreiben. Das Rausschreiben der Daten an die 
LED-Strips ist zeitkritisch und muss deshalb unter Interrupt-Sperre 
passieren. Je länger der Strip, desto länger die Sperre. Wenn man jetzt 
einen flüssigen Helligkeitsübergang möchte (Update alle 20ms) und 300 
LEDs hat, ist man schon einen beträchtlichen Anteil der Rechenzeit in 
Interrupt-Sperre unterwegs. Das beeinträchtigt natürlich die Auswertung 
einer IR-Fernbedienung, die ja auch auf Interrupts und Zeitmessung 
basiert. Kennt jemand dieses Problem und eine elegante Lösung dafür ?

Mein bisheriger Ansatz: Die IR-Auswertung erkennt immer noch dass etwas 
gesendet wurde. Nur nicht mehr was das genau war. Daraufhin würde ich 
die Ausgabe der LED-Strips verzögern bis ich einen gültigen Befehl von 
der Fernbedienung empfange (Fernbedienung wiederholt alle ca. 100ms 
solange eine Taste gedrückt ist) oder ein Timeout abgelaufen ist. 
Aktuelles Problem ist, dass die Interruptsperre meist mitten in einer 
IR-Message vorbei ist und die Auswertung dann nicht das erste Byte als 
erstes sieht und mit der Bytezählung durcheinander kommt. Die 
Synchronisation findet sie dann auch nicht mehr, bis die Taste 
losgelassen wurde. Dann müsste man also immer 2x drücken und den 
LED-Strip entsprechend lange pausieren. Das ist nicht mehr komfortabel. 
Ich müsste also die IR-Auswertung entsprechend anpassen, dass sie bei 
der Byte-Zählung flexibler ist.

Bevor ich mir die Arbeit mache wie gesagt: Kennt jemand eine einfachere 
Lösung ? Vielen Dank im Voraus !

von Wolfgang (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Sven G. schrieb:
> Kennt jemand eine einfachere Lösung ?

Multitasking, Multicore/Mulutiprozessor ...

Verrate bloß keine Detais zum Timing der LED Ansteuerung und des 
IR-Signals.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Sven G. schrieb:
> Anteil der Rechenzeit in
> Interrupt-Sperre unterwegs.

Dann lass den Interrupt nicht sperren ... Wenn du deiner ISR-Funktion 
als zweiten Parameter ISR_NOBLOCK mitgibst, ist der erste Befehl in 
deiner ISR ein "sei", der die Interrupts wieder aktiviert.

Du musst nur auf deinen Stack aufpassen, dass der nicht überläuft, soll 
heißen, die ISRs dürfen nicht zu lange brauchen.

Ich vermute, du verwendest IRMP?

Dann richte dir einen Timer-Interrupt mit sowas 15kHz ein, in dem die 
IRMP-Interrupt-Funktion aufgerufen wird.

Der Rest mit den RGB-LEDs dürfte dann per Timer in einer anderen 
Interrupt-Funktion passieren.

So hatte ich es gemacht und bei mir gab es dann keine Probleme :)

von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
Hallo Mampf,

vielen Dank für die Antwort. Ich habe es noch nicht ganz verstanden. Ich 
weiß auch nicht, ob ich mich klar ausgedrückt habe:

Die LED-Strip-Ausgabe verwendet selbst keine ISR, sie sperrt nur die 
Interrupts, weil sie aufgrund der Timing-Anforderung nicht unterbrochen 
werden darf. Ich habe schon ausprobiert die Interruptsperre einfach 
wegzulassen, dann zeigt der LED-Strip aber Blödsinn an. Geht also nicht.

IRMP verwende ich nicht. Ich verwende eine sehr kleine Library, die aus 
einem Lernroboter-Projekt stammt (Ringo Robot). Die benutzt 
Timer/Counter1 zur Zeitmessung. Da ich sehr viele LEDs ansteuern möchte 
brauche ich einen großen Teil des RAMs für das Muster. Daher möchte ich 
mit Code so sparsam wie möglich sein.


Hallo Wolfgang,

vielen Dank. ;-)

Gruß
   Sven

: Bearbeitet durch User
von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Sven G. schrieb:
> Die LED-Strip-Ausgabe verwendet selbst keine ISR, sie sperrt nur die
> Interrupts, weil sie aufgrund der Timing-Anforderung nicht unterbrochen
> werden darf. Ich habe schon ausprobiert die Interruptsperre einfach
> wegzulassen, dann zeigt der LED-Strip aber Blödsinn an. Geht also nicht.

Hmm, in diesem Fall wäre es sinnvoll den Code zu posten, da es einige 
Möglichkeiten gibt, wie du das implementiert haben könntest.

Die Alternative ist, wir ziehen dir das Stück für Stück aus der Nase ;-)

Glaub, Code posten ist einfacher.

von Johannes S. (jojos)


Bewertung
1 lesenswert
nicht lesenswert
Man könnte sich das Leben leichter machen indem man einen uC nimmt der 
die Ansteuerung besser in  Hardware unterstützt, LPC824/845 oder 
ATiny817 oder STM32, 
https://www.mikrocontroller.net/articles/WS2812_Ansteuerung

: Bearbeitet durch User
von Wolfgang (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Manche Leute verstehe ich nicht: Reißen hier den große Thread auf mit 
der Feststellung, dass es nicht anders geht, so aber nicht funktioniert 
und dann kommen keine Fakten (Programm, Typenbezeichnungen, 
IR-Protokoll), damit sich ja kein anderer ein Bild oder gar konkrete 
Vorschläge zur Lösung machen kann.

von Sven G. (captainalbern)


Bewertung
-2 lesenswert
nicht lesenswert
Ich erwarte nicht, dass sich jemand ein Bein für mich ausreißt. Ich habe 
lediglich gefragt, ob jemand schon mal ein LED-Strip+AVR+IR-Empfänger 
betrieben und damit Erfahrung hat. Ganz einfach. Von dir, Wolfgang, 
erwarte ich gar nichts, soviel Erfahrung habe ich mit diesem Forum.

Ich verwende Adafruit NeoPixel RGBW-LEDs mit 800kHz Datentakt. Das 
Protokoll ist ein 1-Drahl-Protokoll ähnlich dem im Datenblatt zu WS2812, 
WS2811 oder SK6812 beschrieben. Nur mit 32Bit statt 24Bit pro Modul.
Der Code, der die Daten rausschickt sieht so aus...
https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp

Das IR-Protokoll weiß ich gerade nicht und kann ich auch vor Übermorgen 
nicht in Erfahrung bringen. Die sind doch aber alle ähnlich und werden 
alle das gleiche Problem haben, dass man zeitliche Abstände zwischen 
Signalflanken bestimmen muss und daher der Interrupt nicht längere Zeit 
gesperrt sein darf.

Bevor jemand für Wolfgang nochmal antwortet probiere ich es lieber 
selbst nochmal. Vielen Dank schon mal an die anderen für die 
konstruktiven Hinweise.

Gruß
   Sven

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Sowohl IRMP als auch die WS2812- bzw. SK6812-LED-Ansteuerung im 
RGBW-Mode (nichts anderes sind Deine "Neopixel") laufen hervorragend 
zusammen auf z.B. einem STM32F103. Siehe auch WordClock mit WS2812, 
wo beides zusammen eingesetzt wird - neben vielem mehr.

Dabei werden die LEDs per DMA beschickt und der STM32 langweilt sich zu 
Tode.

: Bearbeitet durch Moderator
von Wolfgang (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Sven G. schrieb:
> Bevor jemand für Wolfgang nochmal antwortet ...

Ich frage mich ernsthaft, warum solche Infos nicht im ersten Posting 
auftauchen, sondern erst einmal sechs Postings mit Rätselraten und 
Nebelstochern kommen müssen ...

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Sven G. schrieb:
> Ich verwende Adafruit NeoPixel RGBW-LEDs mit 800kHz Datentakt. Das
> Protokoll ist ein 1-Drahl-Protokoll ähnlich dem im Datenblatt zu WS2812,
> WS2811 oder SK6812 beschrieben. Nur mit 32Bit statt 24Bit pro Modul.
> Der Code, der die Daten rausschickt sieht so aus...
> https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp

Ach du schei*e ... Ich hab mir gerade das Protokoll angeschaut ... Das 
ist ein asynchrones Protokoll mit harten Echtzeitanforderungen (Timing 
+/-150ns) ...

Und der Code dazu ... Völliger Wahnsinn.

Ich würde sagen IR und LEDs beschreiben gleichzeitig kannst du vergessen 
... *edit*: Gerade gesehen, bei einem Low-Pegel von 80µs machen die LEDs 
einen Reset.

Wer hat sich denn den kranken Mist ausgedacht ?


Frank M. schrieb:
> Dabei werden die LEDs per DMA beschickt und der STM32 langweilt sich zu
> Tode.

Ja, das ist auch die einzige Lösung, die mir einfällt.

: Bearbeitet durch User
von Reiner_Gast (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich würde bei zeitkritischen Sachen einen APA102 LED Strip verwenden.
Der versteht SPI und das auch noch deutlich fixer als ein WS2812.

Zumal SPI Übertragung vom AVR von der Hardware aus unterstützt wird...

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Frank M. schrieb:
>> Dabei werden die LEDs per DMA beschickt und der STM32 langweilt sich zu
>> Tode.
>
> Ja, das ist auch die einzige Lösung, die mir einfällt.

Wenn man noch berücksichtigt, dass man die STM32F103 bei eBay als 
kleines aber feines Board für unter 2 EUR bekommt - mit 64 KB Flash und 
20 KB RAM, dann will man keinen AVR mehr anpacken, jedenfalls nicht für 
so eine Aufgabe.

Ebay-Artikel Nr. 272425764978

EDIT:

Der TO könnte noch APA102-LEDs verwenden. Die werden über SPI gesteuert 
und man kann selbst das Übertragungstempo bestimmen. Man wird jedenfalls 
bzgl. Timing nicht fremdbestimmt. Aber ob es die auch in RGBW statt 
lediglich RGB gibt, weiß ich nicht.

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


Bewertung
1 lesenswert
nicht lesenswert
Mampf F. schrieb:
> *edit*: Gerade gesehen, bei einem Low-Pegel von 80µs machen die LEDs
> einen Reset.

Die machen keinen Reset, sondern stellen nach 80µs Ruhe den Ihnen 
zugewiesenen RGB(W)-Wert dar, damit dann alle LEDs gleichzeitig die 
übertragenen Werte darstellen. Die Länge des Ruhepegels ist übrigens 
verschieden und kann von 50µs bis 120µs variieren - je nach Ausführung.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Sven G. (captainalbern)

>ich möchte LED-Strips und einen Fernbedienungsempfänger gleichzeitig an
>einem AVR-Controller betreiben.

Machbar.

> Das Rausschreiben der Daten an die
>LED-Strips ist zeitkritisch und muss deshalb unter Interrupt-Sperre
>passieren.

Kann sein, muß nicht, man kann es ggf. auch clever mit SPI machen.

> Je länger der Strip, desto länger die Sperre.

Nö. Man kann auch zwischen den einzelnen Bytes mal KURZ was anderes 
machen.

>Wenn man jetzt
>einen flüssigen Helligkeitsübergang möchte (Update alle 20ms) und 300
>LEDs hat, ist man schon einen beträchtlichen Anteil der Rechenzeit in
>Interrupt-Sperre unterwegs.

Nö, du bist in einer konzeptionellen Sackgasse.

> Das beeinträchtigt natürlich die Auswertung
>einer IR-Fernbedienung, die ja auch auf Interrupts und Zeitmessung
>basiert.

Das kann man ggf. clever verschachteln, was so oder so der Grundgedanke 
von kooperativem Multitasking ist.

>Mein bisheriger Ansatz: Die IR-Auswertung erkennt immer noch dass etwas
>gesendet wurde. Nur nicht mehr was das genau war. Daraufhin würde ich
>die Ausgabe der LED-Strips verzögern bis ich einen gültigen Befehl von
>der Fernbedienung empfange (Fernbedienung wiederholt alle ca. 100ms
>solange eine Taste gedrückt ist) oder ein Timeout abgelaufen ist.

Ziemlicher Murks. IR-Dekodierung ist doch eher langsam, so im Bereich 
von 1kBit/s. Das kann man relativ einfach mit der LED-Ansteuerung muxen.

>LED-Strip entsprechend lange pausieren. Das ist nicht mehr komfortabel.

In der Tat.

>Ich müsste also die IR-Auswertung entsprechend anpassen, dass sie bei
>der Byte-Zählung flexibler ist.

Scheint so.

>Bevor ich mir die Arbeit mache wie gesagt: Kennt jemand eine einfachere
>Lösung ? Vielen Dank im Voraus !

Kauf dir was fertiges bei Conrad, Pollin oder Perl. ;-)

Wenn du aber kein Konsumerweichei bist, klemmst du dich dahinter und 
löst das Problem ELEGANT!

Und JA, das geht auch mit einem "kleinen" AVR nicht allzuschwer. Fette 
32 Bitter mit DMA und anderen Geschützen braucht man da nicht wirklich. 
Brain 2.0 ist immer noch up to date!

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Sven G. (captainalbern)

>wegzulassen, dann zeigt der LED-Strip aber Blödsinn an. Geht also nicht.

SO einfach geht es nicht. Aber es geht. Siehe mein vorheriger Beitrag.

>IRMP verwende ich nicht. Ich verwende eine sehr kleine Library, die aus
>einem Lernroboter-Projekt stammt (Ringo Robot). Die benutzt
>Timer/Counter1 zur Zeitmessung.

Auch das kann man anpassen.

>Da ich sehr viele LEDs ansteuern möchte
>brauche ich einen großen Teil des RAMs für das Muster. Daher möchte ich
>mit Code so sparsam wie möglich sein.

Jaja, spare jederzeit, dann hast du immer Not. Mein Gott, hat der 
Bastler von heute nicht mal drei Euro für einen ausreichend großen uC 
mit ausreichend RAM?

von Falk B. (falk)


Bewertung
2 lesenswert
nicht lesenswert
@Frank M. (ukw) (Moderator)

>Dabei werden die LEDs per DMA beschickt und der STM32 langweilt sich zu
>Tode.

Weiß Amnesty International schon davon?

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Ach du schei*e ... Ich hab mir gerade das Protokoll angeschaut ... Das
> ist ein asynchrones Protokoll mit harten Echtzeitanforderungen (Timing
> +/-150ns) ...

2 Bit der LED-Daten dauern 2.4µs (8 Bit á 0.3µs), d.h. wenn man die als 
8Bit mit SPI bei 3.33MHz Clk raustackert, hat man zum Bereitlegen der 
Daten, Gucken nach dem IR-Empfängerpin und Warten auf fertige 
SPI-Übertragung 2,4µs Zeit. Nicht die Welt, aber mit Assembler bei einem 
µC, der nicht gerade mit 1MHz dahinschleicht, sind das schon ein paar 
Takte.
Die IR-Auswertung muss dann nach dem LED-Telegramm erfolgen.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Mampf F. (mampf)

>Ach du schei*e ... Ich hab mir gerade das Protokoll angeschaut ... Das
>ist ein asynchrones Protokoll mit harten Echtzeitanforderungen (Timing
>+/-150ns) ...

So what!

>Und der Code dazu ... Völliger Wahnsinn.

Keine Ahung.

>Ich würde sagen IR und LEDs beschreiben gleichzeitig kannst du vergessen
>... *edit*: Gerade gesehen, bei einem Low-Pegel von 80µs machen die LEDs
>einen Reset.

Ja und? Dann lass halt nen High-Pegel stehen.

>> Dabei werden die LEDs per DMA beschickt und der STM32 langweilt sich zu
>> Tode.

>Ja, das ist auch die einzige Lösung, die mir einfällt.

Es gibt so gut wie IMMER mehrere Lösungen, ganz egal wie gut oder 
schlecht die auch sein mögen.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
>> Das Rausschreiben der Daten an die
>>LED-Strips ist zeitkritisch und muss deshalb unter Interrupt-Sperre
>>passieren.
>
> Kann sein, muß nicht, man kann es ggf. auch clever mit SPI machen.

Hatte ich vorher mal durchgerechnet ... SPI müsste auf 20MHz laufen und 
um die Toleranz von +/-150ns einzuhalten, hätte man 3 Taktzyklen Zeit 
eine neue SPI-Übertragung zu starten - bei einem AVR mit 20MHz.

DMA hat der AVR ja leider nicht.

Falk B. schrieb:
>>Ich würde sagen IR und LEDs beschreiben gleichzeitig kannst du vergessen
>>... *edit*: Gerade gesehen, bei einem Low-Pegel von 80µs machen die LEDs
>>einen Reset.
>
> Ja und? Dann lass halt nen High-Pegel stehen.

Lies bitte das Datenblatt, damit du weißt, was dann passiert ;-)


Falk B. schrieb:
>>Ja, das ist auch die einzige Lösung, die mir einfällt.
>
> Es gibt so gut wie IMMER mehrere Lösungen, ganz egal wie gut oder
> schlecht die auch sein mögen.

Wenn dir andere Lösungen einfallen, immer her damit - der TE wäre 
sicherlich hoch erfreut.

: Bearbeitet durch User
von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> 2 Bit der LED-Daten dauern 2.4µs (8 Bit á 0.3µs)

Wie kommst du darauf?

Hatte für Low- und High-Data 0,3µs und 0,95µs gelesen ... Die Daten 
werden wohl in der Länge der High-Low-Pegel kodiert und anscheinend auch 
noch abwechseln mal High mal Low ... Der kleinste gemeinsame Teiler 
wären 0,05µs und der Clock damit 20MHz.

Kann sein, dass ich mir irre, aber so hatte ich es im Datenblatt 
verstanden.

: Bearbeitet durch User
von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Kann sein, dass ich mir irre, aber so hatte ich es im Datenblatt
> verstanden.

Nein, du irrst nicht. Und die anderen beiden sollten die Dinger erstmal 
selbst programmieren.

Falk B. schrieb:
> Keine Ahung.

Ich denke mal, da fehlt ein 'n' in der Mitte. Leider ist das die einzige 
richtige Aussage in deinen Beiträgen. Wenn ich deine sonstigen Beiträge 
auch durchaus zu schätzen weiß, aber bei den Neopixel-Leds liegt du 
nicht zum ersten Mal völlig daneben.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)

>Nein, du irrst nicht. Und die anderen beiden sollten die Dinger erstmal
>selbst programmieren.

Ja, aber.

>> Keine Ahung.

>Ich denke mal, da fehlt ein 'n' in der Mitte.

Hier hast du dein 'n' für 300 Euro. Maren, dreh mal um (also das n meine 
ich)

>Leider ist das die einzige
>richtige Aussage in deinen Beiträgen. Wenn ich deine sonstigen Beiträge
>auch durchaus zu schätzen weiß, aber bei den Neopixel-Leds liegt du
>nicht zum ersten Mal völlig daneben.

Kann sein, muß nicht. Ich sehe das eher sportlich. Der OP geht mit einem 
"OMG, geht alles gar nicht" ins Rennen. Ich sage, wo ein Wille, Know How 
und Sportsgeist vorhanden ist, findet man auch dafür eine Lösung.

Ob man die wilden Stunts mit Inline-Assembler wie in der oben genannten 
Bibliothek machen muss, nur damit es Arduino-Style nach außen ist, sei 
dahingestellt.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Reden wir hiervon?

https://www.adafruit.com/product/1376

Gähn

Die Daten werden pulsbreitenmoduliert mit 800kHz / 1,25us rausgetaktet, 
zwischen den LEDs darf nicht mehr als 50us Pause sein, damit es keinen 
Reset bzw. Latch-Befehl gibt. 50us sind eine EWIGKEIT! Man muss ja nicht 
das gesamte IR-Protokoll in 50us dekodieren, es reicht wenn man ein 
Sample des IR-Empfängers speichert.

Gehen wir mal sportlich von 100 LEDs aus, so dauert deren Ansteuerung 
1250 us, ein Witz. Wenn wir also alle 10 LEDs (=12,5us / 80kHz) ein 
Sample nehmen, ist das mehr als ausreichend. Da wir ja nicht dauerhaft 
nur LEDs ansteuern, sondern mal sportlich von 100 Hz Updaterate 
ausgehen, bleiben noch ca. 8,5ms übrig, um dann die Dekodierung der 
IR-Daten vorzunehmen. In wie weit die Software des IR-Dekoders dafür 
schon ausgelegt ist, weiß ich nicht.

Das Ganze macht man spielend in reinem C ohne eine Zeile Inline 
Assembler, sinnvollerweise natürlich mit dem SPI oder UART im SPI-Mode 
oder USI, je nach Verfügbarkeit.

Will jemand dagegen wetten?

Die minimale Pulsbreite von 0,35us entspricht 2,8 MHz. Da das SPI vom 
AVR mindestens mit Teilerfaktor 2 arbeitet, braucht man halt ~5,7 MHz. 
Bei den Arduino-üblichen 16 MHz wird es etwas krumm mit dem 
Teilerfaktor, sollte laut Datenblatt aber auch noch gehen!

16 MHz / 4 = 4 MHz / 250ns (liegt in den +/-150ns drin)

Ok, ist nicht optimal in bezug auf die verbleibenden Toleranzen. Also 
den Quarz auf 12 MHz umlöten.

von Wolfgang (Gast)


Bewertung
2 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Wolfgang schrieb:
>> 2 Bit der LED-Daten dauern 2.4µs (8 Bit á 0.3µs)
>
> Wie kommst du darauf?

Ich war von Timing der SK6812 RGBW Chips[1] ausgegangen, i.e. 0-Bit als 
0.3µs High + 0.9µs Low und 1-Bit als 0.6µs High + 0.6µs Low. Dann könnte 
man das Bitmuster über SPI mit 0.3µs-Takt und 4 SPI-Bits pro LED-Bit 
generieren. Ob das auf einem AVR mit 16MHz in Assembler genug Freiraum 
schafft, müsste man probieren.

[1] 
https://cdn-shop.adafruit.com/product-files/2757/p2757_SK6812RGBW_REV01.pdf

Der TO bekommt es ja irgendwie nicht fertig, zu seinen Chips mal das 
Datenblatt rüberwachsen zu lassen.
Wenn er was anderes braucht - nur her damit.

von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
Vielen vielen Dank soweit. Ich bitte es zu entschuldigen, wenn ich mich 
erst mal nicht mehr melde. Ich muss erst ausprobieren.

IRMP kannte ich nicht. Ich habe mir inzwischen den Artikel dazu 
durchgelesen und daraufhin Mampf's 1. Kommentar mit der 15kHz-Routine 
jetzt verstanden. Wenn es tatsächlich möglich ist, zwischen den 
einzelnen LEDs kurze Pausen zu machen und die Timing-Anforderungen nur 
innerhalb der 32Bit für ein LED-Modul gelten, könnte man da evtl. was 
multiplexen.

Ich bedanke mich und gucke, wie ich damit weiterkomme.

PS: Nach dem Code der IR-Auswertung und der Beschreibung im IRMP-Artikel 
könnte es ein NEC-Code sein. Auf jeden Fall 38kHz, 1-Start-Bit, 32Bit 
Daten (Adresse, invertierte Adresse, Datenbyte, invertiertes Datenbyte). 
Falls es ein Stopp-Bit gibt ignoriert es der Code.

: Bearbeitet durch User
von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Ich sage, wo ein Wille, Know How
> und Sportsgeist vorhanden ist, findet man auch dafür eine Lösung.

Vollkommen richtig.

Falk B. schrieb:
> Ob man die wilden Stunts mit Inline-Assembler wie in der oben genannten
> Bibliothek machen muss, nur damit es Arduino-Style nach außen ist, sei
> dahingestellt.

Natürlich nicht.
   #define WsOut() do\
                     {\
                        unsigned int ledind = 0;\
                        unsigned char colorind = 1;\
                        unsigned char data = 0;\
   \
                        unsigned char* wsled = (unsigned char*)WsLed;\
   \
                        while(ledind < (WS_N * 3))\
                        {\
                           data = wsled[ledind + colorind--];\
                           for(unsigned char nInd = 0; nInd < 8; nInd++)\
                           {\
                              if(data & (1 << 7))\
                              {\
                                 WS_TOGGLE;\
                                 HighDelay();\
                                 WS_TOGGLE;\
                              }\
                              else\
                              {\
                                 WS_TOGGLE;\
                                 LowDelay();\
                                 WS_TOGGLE;\
                              }\
                              data <<= 1;\
                              LoopDelay();\
                           }\
                           if(colorind == 1) ledind += 3;\
                           else if(colorind == 255) colorind = 2;\
   \
                        }\
   \
                     }while(0)

Die Delays sind je nach Controllertakt(>=6MHz) 0 - 7 NOPs. Das ist die 
Zeit, die für anderes zur Verfügung steht. WS_TOGGLE ist mit dem 
Schreibzugriff aufs PIN-Register realisiert.

Das Gewürge mit colorind ist dem Umstand geschuldet, daß ich die 
Farbwerte in der Reihenfolge RGB eingeben will und die Leds sie anders 
haben wollen.

Beim besten Willen: Wo willst du da noch was einbauen? Denn das Tolle 
ist, daß auch nur kleine Abweichungen, also ein NOP zuviel oder zu 
wenig, die Dinger zum wilden oder auch nur gelegentlichen Blinken 
bringen. Schon das WS_TOGGLE, welches man normalerweise jeweils vor oder 
hinter die if/else stellen würde, verhagelt dir bei manchen Taktraten 
das Timing.

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


Bewertung
1 lesenswert
nicht lesenswert
Sven G. schrieb:
> PS: Nach dem Code der IR-Auswertung und der Beschreibung im IRMP-Artikel
> könnte es ein NEC-Code sein.

Ja, sieht so aus. Über 90% aller herumschwirrenden Fernbedienungen 
nutzen heutzutage den NEC-Code.

Es gäbe vielleicht noch folgende Alternative:

IRMP auf ATTiny45 und Rausschreiben der empfangenen Codes per 
Software-Uart an Deinen verwendeten µC. Wenn Du auf die Übertragung der 
Geräteadresse verzichtest und das schon im ATTiny prüfst, ob sie zu 
Deiner Fernbedinung passt, reicht ein Byte zur Übertragung des 
IR-Kommandos. Dieses kannst Du dann bequem zwischen den LED-Frames, die 
Du verschickst, auf Deinem UART einlesen und entsprechend verarbeiten.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Ob man die wilden Stunts mit Inline-Assembler wie in der oben genannten
> Bibliothek machen muss, nur damit es Arduino-Style nach außen ist, sei
> dahingestellt.

Bei dem Protokol muss man wohl zumindest Assembler verwenden und die 
Zyklen abzählen, wenn man keine Hardware-Unterstützung hat.

Also hier die Problemlösung:

300 LEDs mit je 32Bit @ 1,25µs pro Bit (1,25µs LO, 1,3µs HI) bräuchten 
dann in etwa 12ms insgesamt.

Pro LED - das wäre dann quasi eine Atomare Einheit, die man nicht 
unterbrechen kann - wären das 40µs

- Timer einrichten mit zB 10kHz (IRMP zB verwendet mindestens 10kHz für 
den IR-Sampler) = 100µs
- In jedem Timeraufruf die Daten für 2 LEDs senden (80µs)
- Nach dem Daten schreiben den IR-Sampler aufrufen (maximal 20µs oder ca 
400 Taktzyklen bei 20MHz AVR).
- etwas Overhead kommt vlt noch hinzu, aber die gehen halt dann von den 
400 Taktzyklen weg.

Die 20µs für den IR-Sampler sind noch unterhalb der 80µs Reset-Time der 
LEDs, passt also.

Und der IR-Sampler wird mit ziemlich konstanten 10kHz aufgerufen.

Die Refresh-Zeit ist damit dann ziemlich genau 15ms und innerhalb der 
20ms, die der TE anstrepte.

Voila, Problem gelöst :)

: Bearbeitet durch User
von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Voila, Problem gelöst

Blink, Blink!

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)

>Natürlich nicht.
>   #define WsOut() do\

Auch herje, ein Monster-Makro. Auch das braucht man hier nicht wirklich.

>Die Delays sind je nach Controllertakt(>=6MHz) 0 - 7 NOPs. Das ist die
>Zeit, die für anderes zur Verfügung steht. WS_TOGGLE ist mit dem
>Schreibzugriff aufs PIN-Register realisiert.

Schon klar.

>Beim besten Willen: Wo willst du da noch was einbauen?

Zwischen den einzelnen LED-Paketen, dort hat man bis zu 50us Zeit. 
Schrieb ich bereits mehrfach.

>Denn das Tolle
>ist, daß auch nur kleine Abweichungen, also ein NOP zuviel oder zu
>wenig, die Dinger zum wilden oder auch nur gelegentlichen Blinken
>bringen.

Dann haben sie entweder ihr Datenblatt nicht gelesen oder du einen 
Fehler gemacht. Was ist wohl wahrscheinlicher?

> Schon das WS_TOGGLE, welches man normalerweise jeweils vor oder
>hinter die if/else stellen würde, verhagelt dir bei manchen Taktraten
>das Timing.

Wer das mit einem beliebigen Takt per Bitbanging machen will, bitte 
schön. Kriegt man hin, ist aber auch eher ein Makro-Krampf. Aber das ist 
doch gar nicht zwingend nötig. SPI/UART, fertig.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Frank M. (ukw) (Moderator)

>IRMP auf ATTiny45 und Rausschreiben der empfangenen Codes per
>Software-Uart

Kann man machen, ist aber nicht nötig. Auch wenn der AVR nur ein guter, 
alter 8-Bitter ist, kriegt der das hin.

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> SPI/UART, fertig.

Kauf dir einen Streifen, programmier die Dinger und dann zeig, was du 
hast. In der Zwischenzeit unterhalte ich mich mit dem Papst über, na du 
weißt schon was.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)

>> SPI/UART, fertig.

>Kauf dir einen Streifen, programmier die Dinger und dann zeig, was du
>hast.

Deal. Wo gibt's die zu kaufen, außer in den USA?

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Deal. Wo gibt's die zu kaufen, außer in den USA?

https://www.ebay.de/sch/i.html?_from=R40&_trksid=p2380057.m570.l1311.R1.TR12.TRC2.A0.H0.Xws2812.TRS0&_nkw=ws2812b&_sacat=0

Das sind die WS2812b mit RGB. Die vom TO sind die verschärfte Variante 
mit RGBW.

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Falk B. schrieb:
> Zwischen den einzelnen LED-Paketen, dort hat man bis zu 50us Zeit.

Mit einem LED-Paket meinst Du die Daten für eine LED, richtig?

Um 24 Bit (1 Bit = 1.25µs) für eine LED zu übertragen, bist Du dann ca. 
30 µs taub auf dem IR-Receiver. Bei 32 Bit für eine RGBW-SK6812-LED, wie 
sie der TO verwendet, sind es ca. 38µs (hier: 1 Bit = 1.2µs).

Das heisst, Du hast bei empfangenen IR-Daten einen Fehler beim Messen 
der IR-Flanken von 38µs.

Wenn man sich das NEC-Protokoll anschaut:

  0-Bit   560µs Puls, 560µs Pause
  1-Bit   560µs Puls, 1690µs Pause

kann das hier konkret, wo sich die Pausen für 1-Bit und 0-Bit erheblich 
unterscheiden, tatsächlich funktionieren. Denn 560µs sind von den 1690µs 
noch meilenweit entfernt, so dass man einen großen Toleranzbereich (von 
ca. 50%) für die gemessenen Zeiten ansetzen kann.

Allerdings schätze ich, dass sich die Übertragungszeit für den ganzen 
LED-Frame von 400 LEDs ungefähr verdoppelt. Aus 400 * 36µs = 14,4ms 
werden dann so ca. 28 ms. Naja, damit kann man wahrscheinlich leben.

EDIT:

Könnte tatsächlich auch mit IRMP noch funktionieren, man muss lediglich 
den Timer-Interrupt, der für IRMP zuständig ist, während der Übertragung 
der Daten für eine LED abschalten. IRMP arbeitet beim NEC-Protokoll mit 
einer Toleranz von 40%, wenn ich das richtig in Erinnerung habe.

: Bearbeitet durch Moderator
von GrobiG (Gast)


Bewertung
0 lesenswert
nicht lesenswert
... eine Lösung mit einem zusätzlichem µc der auf die IR Kommandos 
lauscht wurde glaube ich schon vorgetragen, wenn man es wirklich nicht 
anders hinbekommen sollte ist das wohl die einfachste und angenehmste 
Lösung.
Wenn man möchte könnte man dem IR µc einen Puffer verpassen für die 
empfangenen Kommandos und der LED steuernde µc gibt dann entsprechend 
die Übertragung zwischen den beiden µc frei, wenn genug Zeit dafür ist.
Oder der IR µc "fragt" halt periodisch den LED µc ob er ein neues 
Kommando an ihn senden darf, schon recht simpel.

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
1 lesenswert
nicht lesenswert
Frank M. schrieb:
> Falk B. schrieb:
>> Zwischen den einzelnen LED-Paketen, dort hat man bis zu 50us Zeit.
>
> Mit einem LED-Paket meinst Du die Daten für eine LED, richtig?

Wenn er das wirklich so meint, leuchtet nur die erste.


Frank M. schrieb:
> Um 24 Bit (1 Bit = 1.25µs) für eine LED zu übertragen, bist Du dann ca.
> 30 µs taub auf dem IR-Receiver. Bei 32 Bit für eine RGBW-SK6812-LED, wie
> sie der TO verwendet, sind es ca. 38µs (hier: 1 Bit = 1.2µs).
>
> Das heisst, Du hast bei empfangenen IR-Daten einen Fehler beim Messen
> der IR-Flanken von 38µs.

Die Daten für alle Leds müssen in einem Rutsch gesendet werden. Die 
Dinger warten nicht, bis die 50µs zuende sind. Das ist die Mindestzeit, 
die eingehalten werden muß, bevor der nächste Frame kommt, damit die 
letzte, also in diesem Fall die dreihundertste, das auch noch mitkriegt. 
Diese LED-Streifen sind keine synchronen Schieberegister, sondern 
digitale Eimerketten.

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


Bewertung
1 lesenswert
nicht lesenswert
Thomas E. schrieb:
> Die Daten für alle Leds müssen in einem Rutsch gesendet werden. Die
> Dinger warten nicht, bis die 50µs zuende sind.

Doch, warten sie. Solange die 50µs nicht überschritten werden, geben sie 
die Daten an die nächste LED weiter.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)

>>> Zwischen den einzelnen LED-Paketen, dort hat man bis zu 50us Zeit.
>>
>> Mit einem LED-Paket meinst Du die Daten für eine LED, richtig?

>Wenn er das wirklich so meint, leuchtet nur die erste.

Nö.

>> Das heisst, Du hast bei empfangenen IR-Daten einen Fehler beim Messen
>> der IR-Flanken von 38µs.

>Die Daten für alle Leds müssen in einem Rutsch gesendet werden. Die
>Dinger warten nicht, bis die 50µs zuende sind.

Das sollten sie aber. Oder das Datenblatt stimmt nicht.

> Das ist die Mindestzeit,
>die eingehalten werden muß, bevor der nächste Frame kommt, damit die
>letzte, also in diesem Fall die dreihundertste, das auch noch mitkriegt.
>Diese LED-Streifen sind keine synchronen Schieberegister, sondern
>digitale Eimerketten.

Naja, es ist schon ein wenig ein Hack ala OneWire, nur deutlich 
schneller.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Das sollten sie aber. Oder das Datenblatt stimmt nicht.

Das Ding kommt aus China. Da kann das mal passieren.

Irgendwer muss den LED-Controllerchen doch sagen, dass ein neues 
Datenbit kommt und das kann eigentlich nur die steigende Flanke sein. 
Sonst wäre keine Synchronisation möglich und bei vielen LEDs liefe einem 
das Timing weg.

von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
Ihr Lieben !

Ich bin sowas von begeistert ! Ich habe leider zwei Tage warten müssen, 
bevor ich es ausprobieren konnte, aber es funktioniert auf Anhieb. 
Vielen Dank für die Inspiration !

Folgendermaßen:

Ich habe in die Assemblerschleife, die die Daten an die LEDs rausschickt 
einfach vor dem Rücksprung an den Anfang ein sei; eingefügt und am 
Anfang ein cli;. Damit sind für einen kurzen Augenblock die Interrupts 
freigegeben. Wenn jetzt zwischendurch ein Interrupt ausgelöst wird, 
wartet der in der Hardware bis er dran ist und nutzt dann diese kurze 
Zeit direkt aus. Die dadurch entstehende Verzögerung ist so gering, dass 
das IR-Signal noch gut ausgewertet werden kann. Die von mir verwendete 
IR-Auswertung verwendet allerdings keinen regelmäßigen Interrupt wie 
IRMP das tut, sondern lässt den Interrupt vom Flankenwechsel am 
Empfänger auslösen. Nochmal vielen Dank an Mampf für die Idee mit dem 
Multiplexing. Ich habe gezweifelt, dass ich das hinkriege und nie 
gedacht, dass das SO einfach ist.

Auszug aus dem Veränderten Code (Quelle: Adafruit)
   "head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
      "cli;"                     "\n\t" // Änderung 1
      "st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
      "sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
       "mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
      "dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
      "st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
      "mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
      "breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
      "rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
      "nop"                      "\n\t" // 1    nop           (T = 13)
      "st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
      "nop"                      "\n\t" // 1    nop           (T = 16)
      "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
      "rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
     "nextbyte20:"               "\n\t" //                    (T = 10)
      "ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
      "ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
      "st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
      "nop"                      "\n\t" // 1    nop           (T = 16)
      "sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
      "sei;"                     "\n\t" // Änderung 2
       "brne head20"             "\n"   // 2    if(i != 0) -> (next byte)

: Bearbeitet durch User
von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sven G. schrieb:
> Ich bin sowas von begeistert !

Prima

> Die dadurch entstehende Verzögerung ist so gering, dass
> das IR-Signal noch gut ausgewertet werden kann.

Interessant wäre jetzt noch zu wissen, wie lange bei einem Interrupt die 
Ausgabe an die LEDs maximal verzögert wird.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
>> Die dadurch entstehende Verzögerung ist so gering, dass
>> das IR-Signal noch gut ausgewertet werden kann.
>
> Interessant wäre jetzt noch zu wissen, wie lange bei einem Interrupt die
> Ausgabe an die LEDs maximal verzögert wird.

Soweit ich das verstanden habe, ist das egal ... Die LEDs dürfen nur 
nicht länger als 80µs ein LOW-Signal erhalten.

80µs ist eine lange Zeit, in der viel gemacht werden kann - der 
IR-Interrupt wird diese bestimmt nicht aufbrauchen.

Die Lösung vom TE finde ich gut!

Daran hatte ich nicht gedacht, dass der Interrupt gespeicher und dann 
ausgeführt wird, sobald die Interrupts wieder aktiviert werden.

Die maximal 40µs Verzögerung dürften dem IR-Dekoder dann kaum stören.

: Bearbeitet durch User
von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Soweit ich das verstanden habe, ist das egal ... Die LEDs dürfen nur
> nicht länger als 80µs ein LOW-Signal erhalten.

Ich bin auch dieser Meinung, obwohl das den Angaben im Datenblatt 
widerspricht. Deshalb wäre es IMHO gut zu wissen wie weit die 
IR-Interruptroutine von Sven diesen 0-Pegel ungestraft verlängert.
Ich habe leider keine von den LEDs hier, um mal das Streching der 
0-Phase auszureizen.

von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
Ich werde bei Gelegenheit mal die Zeit in der IR-Routine messen.

Den kompletten Code der IR-Routine wollte ich hier nicht her kopieren 
und ich habe auch gerade keinen konkreten Link dahin gefunden. Er stammt 
auf jeden Fall von http://www.plumgeek.com/ und gehört zu einem 
Lernroboter Ringo2. Der Originalcode ist nur für 8MHz und braucht für 
16MHz µC eine kleine Änderung in der Zeitmessung (>>1).

Dass der Interrupt in der Hardware wartet, hatte ich glaube ich mal 
irgendwo gelesen, war mir aber nicht mehr sicher. Aber dass es jetzt 
reibungslos funktioniert spricht dafür, dass das stimmt.

von batman (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sven G. schrieb:
> Damit sind für einen kurzen Augenblock die Interrupts
> freigegeben.

Besser fährt man i.d.R. mit der umgekehrten Logik:
Die IRQ für die nötige Zeit sperren, sonst freigeben.

Nicht alle IR-Protokolle verkraften 80µs Framing-Error.

von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
@batman: Das ist schon klar. Aber es ging doch jetzt gerade darum, aus 
einem leistungsschwachen µC ein Protokoll mit harten Timinganforderungen 
rauszuquetschen und dafür braucht man eine lange Interruptsperre. Jetzt 
haben wir offenbar eine Stelle im Protokoll gefunden, wo die 
Timinganforderung lockerer ist und nutzen die für den Interrupt. Das von 
mir verwendete IR-Protokoll kann die kurze Verzögerung gut verkraften. 
Wenn es für andere nicht reicht muss man da wohl trickreicher sein oder 
aber gleich einen anderen µC verwenden, wie oben andere schon 
vorgeschlagen haben.

Da ich sehr gern so lange wie möglich bei Bekanntem bleibe, bin ich froh 
dass das nochmal funktioniert.

Es sollte natürlich Augenblick heißen. ;-)

: Bearbeitet durch User
von Mampf unterwegs (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Pragmatische Einstellung, finde ich gut :)

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Mampf unterwegs (Gast)

>Pragmatische Einstellung, finde ich gut :)

Jain. Der OP hat auch eine gute Portion Glück, daß es hier so einfach 
funktioniert. Wenn man sicher sein will, muss man zumindest mal 
durchmessen, wie lange die ISR braucht und wieviel Reserve noch zu den 
offiziellen 50us Maximalpause vorhanden ist.

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sven G. schrieb:
> Jetzt haben wir offenbar eine Stelle im Protokoll gefunden, wo die
> Timinganforderung lockerer ist und nutzen die für den Interrupt.

Man kann es auch ganz klar so formulieren: Das Datenblatt der LEDs ist 
bzgl. der Dauer des Zeitfensters für die Low-Phase falsch.

Meine Vermutung: Die angegebenen Werte z.B. beim SK6812 für T0L und T1L 
sind Minimalwerte und die Toleranzangaben ("±0.15μs") sind in dieser 
Form Unfug. Die maximale Dauer der Low-Phase ist durch die Schwelle 
von 80µs für Trst (Reset/Latch?) begrenzt.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Wolfgang (Gast)

>Man kann es auch ganz klar so formulieren: Das Datenblatt der LEDs ist
>bzgl. der Dauer des Zeitfensters für die Low-Phase falsch.

>Meine Vermutung: Die angegebenen Werte z.B. beim SK6812 für T0L und T1L
>sind Minimalwerte und die Toleranzangaben ("±0.15μs") sind in dieser
>Form Unfug. Die maximale Dauer der Low-Phase ist durch die Schwelle
>von 80µs für Trst (Reset/Latch?) begrenzt.

Das würde ich auch vermuten. Die Dekodierung erfolgt einfach über 2 
retriggerbare  Monoflops. Das erste mißt die Pulsdauer von 
350/700ns, das 2. die Resetdauer von 50us.

von batman (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die 50µs Zeit hat man ja nicht nur nach einem bestimmten sondern nach 
jedem LED-Bit. Bei einem 20MHz µC entspricht das 1000 Takten Zeit. Da 
sehe ich die "harten Timinganforderungen" nicht wirklich.

von Mampf unterwegs (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wolfgang schrieb:
> Man kann es auch ganz klar so formulieren: Das Datenblatt der LEDs ist
> bzgl. der Dauer des Zeitfensters für die Low-Phase falsch.

Im mc.net Artikel steht für die WS2812 das gleiche ... Allerdings wird 
dort geschrieben, dass meistens schon 5us ausreichen für einen Reset 
anstatt 50us ... :)

von Reiner_Gast (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Falk B. schrieb:
> @Mampf unterwegs (Gast)
>
>>Pragmatische Einstellung, finde ich gut :)
>
> Jain. Der OP hat auch eine gute Portion Glück, daß es hier so einfach
> funktioniert. Wenn man sicher sein will, muss man zumindest mal
> durchmessen, wie lange die ISR braucht und wieviel Reserve noch zu den
> offiziellen 50us Maximalpause vorhanden ist.

Aus Interesse habe ich mir vor einiger Zeit mal den vom AVR-GCC 
erstellten Assembler Code (zu finden in der *.LSS Datei im 
Kopilerordner) für eine ISR angesehen...

Je nach Optimierung des Compilers kann man für das Pushen / Pullen der 
uC Register auf den Stack etwas 50 Takte als Overhead rechnen, d.h. bei 
16Mhz macht das gut 3,1us zusätzlich zum eigentlichen Code in der 
ISR.... Sollte also noch satt im Toleranzbereich der WS2812 Chips liegen

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Reiner_Gast (Gast)

>> durchmessen, wie lange die ISR braucht und wieviel Reserve noch zu den
>> offiziellen 50us Maximalpause vorhanden ist.

>Aus Interesse habe ich mir vor einiger Zeit mal den vom AVR-GCC
>erstellten Assembler Code (zu finden in der *.LSS Datei im
>Kopilerordner) für eine ISR angesehen...

Und was hast du gesehen? Wieviele Takte wurden benötigt?

>Je nach Optimierung des Compilers kann man für das Pushen / Pullen der
>uC Register auf den Stack etwas 50 Takte als Overhead rechnen, d.h. bei
>16Mhz macht das gut 3,1us zusätzlich zum eigentlichen Code in der
>ISR.... Sollte also noch satt im Toleranzbereich der WS2812 Chips liegen

???

Ich sehe keine Angabe zur ISR-Laufzeit. Die besteht ja nicht nur aus 
deinen ca. 50 Takten für push/pop.

von Reiner_Gast (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Falk B. schrieb:
> @Reiner_Gast (Gast)
>
>>> durchmessen, wie lange die ISR braucht und wieviel Reserve noch zu den
>>> offiziellen 50us Maximalpause vorhanden ist.
>
>>Aus Interesse habe ich mir vor einiger Zeit mal den vom AVR-GCC
>>erstellten Assembler Code (zu finden in der *.LSS Datei im
>>Kopilerordner) für eine ISR angesehen...
>
> Und was hast du gesehen? Wieviele Takte wurden benötigt?
>
>>Je nach Optimierung des Compilers kann man für das Pushen / Pullen der
>>uC Register auf den Stack etwas 50 Takte als Overhead rechnen, d.h. bei
>>16Mhz macht das gut 3,1us zusätzlich zum eigentlichen Code in der
>>ISR.... Sollte also noch satt im Toleranzbereich der WS2812 Chips liegen
>
> ???
>
> Ich sehe keine Angabe zur ISR-Laufzeit. Die besteht ja nicht nur aus
> deinen ca. 50 Takten für push/pop.

Ja, was weiß denn ich, ich kenne auch nicht den Code jeder ISR auf 
dieser Welt... Das kann nur der Programmierer sagen, wenn er schaut, was 
der Compiler daraus macht (siehe LSS Datei)

Wie ich geschrieben kann mal als zusätzlichen der Overhead ca 50 Takte 
zum eigentlichen Code innherhalb der ISR rechnen

von batman (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Man kann auch gleich Assembler schreiben.
Für eine ISR müssen nicht zwingend 50 Register gepusht werden, wenn 
überhaupt welche.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@batman (Gast)

>Man kann auch gleich Assembler schreiben.

Kann man, will man meistens aber nicht.

>Für eine ISR müssen nicht zwingend 50 Register gepusht werden, wenn
>überhaupt welche.

Niemand redet von 50 Registern, sondern bestenfalls von 50 TAKTEN! Aber 
naja, wir wissen ja vom wem dieser Beitrag kommt.

von Reiner_Gast (Gast)


Bewertung
0 lesenswert
nicht lesenswert
batman schrieb:
> Man kann auch gleich Assembler schreiben.
> Für eine ISR müssen nicht zwingend 50 Register gepusht werden, wenn
> überhaupt welche.

50 Take != 50 Register....

Schau mal ins Datenblatt von z.B. dem ATMega328 (Kapitel 37)... Da 
"kostet" ein PUSH oder ein PULL eines Registers jeweils 2 Takte

Bei 50 Takte macht das 25 Takte für den Eintritt in die ISR... Und 25 
Takte für das Wiederherstellen der uC Umgebung... das ganze nochmal 
geteilt durch die 2 Takte pro Befehl...

Einfluss hat darauf auch, welche Compiler Optimierung eingeschaltet ist 
bzw. wie viele der Register in der ISR tatsächlich benutzt werden (weil 
nur die vorher gesichert werden)

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Mampf unterwegs schrieb:
> Im mc.net Artikel steht für die WS2812 das gleiche ... Allerdings wird
> dort geschrieben, dass meistens schon 5us ausreichen für einen Reset
> anstatt 50us ... :)

Das halte ich für ein Gerücht. Neuerdings bekommt man bei eBay eher 
WS2812-LEDs, die eine Mindestzeit von 250µs(!) brauchen, bevor die 
Daten ausgegeben werden ("Latch"). Wahrscheinlich liegt das an den neu 
eingeführten WS2813-LEDs, welche auch bei Defekt noch das Signal über 
einen "Bypass" an die nächste LED weitergeben. Diese brauchen "ganz 
offiziell" (s. Datenblatt) diese 250µs.

Aber man muss nicht meinen, dass die Chinesen diese "neuen" WS28212 als 
solche deklarieren. Ich habe das vor ca. einem halben Jahr nur durch 
Trial- and Error herausgefunden, wo ich von den neuen WS2813 noch nichts 
wusste.

EDIT:

Siehe auch https://www.elecrow.com/blog/ws2813-vs-ws2812/

: Bearbeitet durch Moderator
von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Das halte ich für ein Gerücht.

Ich nicht.

Ich habe gerade nagelneue SK6812 mit RGBW auf dem Tisch. Die benehmen 
sich zwar deutlich manierlicher als WS2812b, resetten aber dennoch nicht 
erst nach den im Datenblatt angegebenen 80µs, sondern nach 40µs.

Aber vielleicht bin ich ja nur wieder zu blöd, das Datenblatt zu lesen 
oder mein Monstermakro ist schuld.

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Thomas E. schrieb:
> Frank M. schrieb:
> Das halte ich für ein Gerücht.
>
> Ich nicht.
>
> Ich habe gerade nagelneue SK6812 mit RGBW auf dem Tisch.

SK6812 != WS2812

von Wolfgang (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mampf unterwegs schrieb:
> Im mc.net Artikel steht für die WS2812 das gleiche ... Allerdings wird
> dort geschrieben, dass meistens schon 5us ausreichen für einen Reset
> anstatt 50us ... :)

Immerhin ist im Datenblatt der WS2813 jetzt angegeben, dass die 
Low-Phase vom Signal bis zu 100 Mikrosekunden lang sein darf. Reset ist 
dort mit >300µs angegeben.

Das hört sich schon anders an als 0.9µs/0.6μs ±0.15μs bei den SK6812 
bzw. 0.8us/0.6µs ±150ns bei den WS2812.

http://www.normandled.com/upload/201605/WS2813%20LED%20Datasheet.pdf

von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Das halte ich für ein Gerücht

ich habe ja deine IRMP in "meine" wordclock mit 114 ws2812b LEDs 
eingebaut und keine Probleme, sind aber nur um 3ms für die LEDs das 
rauszutakten.

Meine wordclock24 mit 296 LEDs ist leider auf dem Rückweg kaputt 
gegangen sonst hätte ich da weiter messen und probieren können.

Dort braucht das raustakten ca. 9ms.

Du bist ja zum STM gewechselt ich vom ATmega328p zum ATmega1284p und 
immer noch optimistisch das ich es schaffe.

Wie regelst du das beim STM OK per DMA für die LEDs, aber läuft der DMA 
unabhängig vom IRQ?

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> SK6812 != WS2812

Ach, sag nicht sowas. Ist aber das gleiche Prinzip, inklusive dem 
RG-Dreher und ein weiteres Indiz dafür, daß diese Neopixels sich einen 
Scheiß an die Angaben im Datenblatt halten.

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Thomas E. schrieb:
> daß diese Neopixels sich einen Scheiß an die Angaben im Datenblatt
> halten.

Da gebe ich Dir recht. Allerdings muss man da auch fragen: Welches 
Datenblatt kann man da als verbindlich betrachten, wenn man irgendwelche 
WS2812 oder SK6812 in China bestellt. Von den Datenblättern schwirren 
zig Varianten im Internet rum.

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Wie regelst du das beim STM OK per DMA für die LEDs, aber läuft der DMA
> unabhängig vom IRQ?

Ja, der DMA läuft komplett unabhängig vom Rest. Da kannst Du den STM32 
mit IRQs malträtieren, wie Du willst: Die Übertragung auf die LEDs läuft 
einfach stoisch durch.

Für den DMA-Transfer übergibst Du einfach einen Pointer auf einen Buffer 
und die Länge. Danach hast Du nichts mehr damit zu tun. Das ist die 
einfache, aber relativ RAM-intensive Lösung.

Seit über einem Jahr benutzt die WordClock mit WS2812 jedoch eine 
etwas raffiniertere Kombination von DMA und DMA-Interrupt. Damit 
reduziert sich der nötige RAM-Bedarf auf einen Bruchteil. Im 
DMA-Interrupt werden die nötigen Daten on-the-fly aus den noch zu 
übertragenen RGB-Werten berechnet und dann laufend nachgeliefert. Der 
DMA-Buffer hat hier keinen Anfang und kein Ende, sondern ist ein 
Ringbuffer.

Mit dieser Optimierung konnte ich die Pausen zwischen zwei 
Animationsframes für knapp 400 LEDs derart minimieren, dass das 
"Fehlverhalten" neuerer WS2812, die nun mehr als 250µs statt 50µs Pause 
für den Reset brauchen, erst aufgefallen ist. Statt dann vorne am Anfang 
der Stripes weiterzumachen, wurden die Daten des zweiten Frames 
plötzlich am Ende des Stripes bitweise rausgekippt. Das bemerkte ich auf 
der Suche nach den verlorenen LED-Daten erst, als ich nach den 400 LEDs 
noch ein paar weitere LED an den Streifen hing. Die fingen dann 
plötzlich an zu leuchten. Dieser Effekt war erst weg, als ich die 50µs 
Pause schrittweise bis auf 250µs erhöhte. Mittlerweile arbeitet die 
WordClock mit einer Pause von sogar 280µs, um auf der sicheren Seite zu 
sein.

P.S.
Die Wordclock24h hat nicht exakt 400 LEDs, sondern inkl. Ambilight 
zwischen  349 und 409 LEDs - je nach Ausführung.

: Bearbeitet durch Moderator
von batman (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> Für den DMA-Transfer übergibst Du einfach einen Pointer auf einen Buffer
> und die Länge. Danach hast Du nichts mehr damit zu tun. Das ist die
> einfache, aber relativ RAM-intensive Lösung.

Und der serialisiert und transferiert die Daten über den Port zu den 
LEDs?

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
batman schrieb:
> Und der serialisiert und transferiert die Daten über den Port zu den
> LEDs?

Jepp. Du musst die rohen RGB-Daten natürlich vorher noch ein wenig 
"aufarbeiten". Normalerweise lässt Du den DMA-Transfer per HW-Timer 
steuern, dann hast Du einen definierten DMA-Takt, der rein durch HW 
gesteuert wird und um den Du Dich nicht kümmern musst. Dafür musst Du 
die 0en und 1en vorher so im DMA-Buffer platzieren, dass sie den Zeiten 
T0H, T0L, T1H und T1L  entsprechen. Du blähst Deine Daten dadurch von 
24Bit pro LED Rohdaten mal schnell auf einen satten 8K-DMA-Buffer auf - 
je nach Anzahl der LEDs. Das war die simple Methode.

Jetzt zu der eleganten:

Wenn Du den DMA-Buffer so dimensionierst, dass er gerade die Daten für 2 
LEDs halten kann, Du diesen dann als "Circular buffer" für DMA 
definierst, kommst Du mit weniger als 100 Bytes fürs RAM aus, *egal 
wieviele* LEDs Du am Streifen hast. Immer, wenn eine Hälfte des 
DMA-Buffers (also für eine LED) bereits übertragen ist, lieferst Du die 
Daten für die übernächste LED nach, während der DMA-Transfer gerade die 
Daten für die nächste LED raustaktet.

Zusammen mit einem Double-Buffer für den nächsten 400er Frame kannst Du 
bereits die Daten für den nächsten Animationsframe berechnen, während 
die DMA immer noch am ersten Frame knabbert. Du bist also insgesamt viel 
schneller als die LEDs überhaupt verkraften könnten.

Mit DMA macht das so richtig Spaß :-)

: Bearbeitet durch Moderator
von batman (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hmm mit ISR kommt mir das einfacher vor aber ich habs noch nicht 
probiert.

von Sven G. (captainalbern)


Bewertung
0 lesenswert
nicht lesenswert
Ich wollte noch nachreichen: Die IR-Routine braucht 12-16µs mit micros() 
gemessen (also unter 20µs).

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
2 lesenswert
nicht lesenswert
Circular-DMA-Transfer für WS2812:

  https://www.mikrocontroller.net/svnbrowser/wordclock24h/src/ws2812/ws2812.c?view=markup

Circular-DMA-Transfer für SK6812:

  https://www.mikrocontroller.net/svnbrowser/wordclock24h/src/sk6812/sk6812.c?view=markup

DMA-Transfer für APA102:

  https://www.mikrocontroller.net/svnbrowser/wordclock24h/src/apa102/apa102.c?view=markup

Bei den APA102 wird auf den kleinen Circular Buffer und den DMA-IRQ 
verzichtet, da sich das wegen SPI nicht mehr lohnt. Das geht hier 
sowieso um ein Vielfaches schneller als bei den WS2812 und SK6812 und 
braucht auch keinen so großen DMA-Buffer. Hier ist der DMA-Buffer genau 
so groß wie die RGB-Rohdaten, also pro LED 24Bit.

Trotzdem: Auch hier gibt einem der DMA-Transfer (SPI über DMA) viel Luft 
für andere zu erledigende Dinge.

von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> P.S.
> Die Wordclock24h hat nicht exakt 400 LEDs

mein Prototyp hat ohne Ambilight 18 x 16 + 5 Status LEDs = 293

von Falk B. (falk)


Angehängte Dateien:

Bewertung
10 lesenswert
nicht lesenswert
So, da bin ich mal wieder. Ich hab mir mal 5m LED-Streifen mit 60Stück/m 
= 300 Stück bestellt. Wenn man dafür nicht mal 40 Euro bezahlt, ist das 
irgendwie spottbillig 8-0. Es sind WS2812B, die haben 4 Pins und leider 
auch nicht ihr Datenblatt gelesen 8-(. Denn die dort genannte Resetzeit 
von >50us sind real nur 5us, wie es auch schon im Artikel 
WS2812 Ansteuerung geschrieben steht. Hat da der Chinese einen 
Dezimalpunkt vergessen? Das penible Einhalten der HIGH/LOW Zeiten ist 
nicht nötig? Dachte ich am Anfang! Nach ersten, schnellen Erfolgen an 
der LED-Front kam irgendwann die Ernüchterung! Man kann die LEDs zwar 
ansteuern, aber die Farben stimmen keine Sekunde! Hää? Sind die High/LOW 
Zeiten wirklich SOOO eng? Scheint so. Also mal fix nen Crashkurs "Wie 
binde ich Assemblerfunktionen in C ein" und ein paar Stunden später dann 
die taktgenaue Ansteuerung in Software. Jetzt passen die Farben exakt. 
Hmmm. Damit ist SPI zumindest raus! Warum?

Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560 
nicht so ganz schnell ist. D.h. man kann nicht lückenlos hintereinander 
Daten senden, auch wenn man die Schleife zur Datenausgabe mit nop() 
taktgenau optimiert. Es bleibt immer eine minimale Lücke von ca. 300ns 
(5 CPU-Takte), welche nicht unterschritten werden kann. Eine weitere 
Merkwürdigkeit ist, daß man das Bit CPHA im Register SPCR setzen muss, 
damit MOSI am Ende der Datenausgabe auf LOW bleibt! Setzt man es nicht, 
geht es immer auf HIGH! Das hab ich bisher bei keinem SPI gesehen, auch 
nicht auf anderen AVRs. Bug oder Feature?

Also doch Assembler und Bitbanging. Naja, wenns halt nicht anders geht. 
Der Vorteil dieser Funktion ist zumindest, daß man sie auf jeden 
beliebigen Portpin anwenden kann. Mit den passenden Arduino-Wrappern 
geht das sogar im Arduini-Style. Hab ich jetzt aber nicht gemacht. Die 
Low Pulse sind 6 CPU-Takte lang, macht bei 16 MHz = 375ns, die langen 
Pulse exakt doppelt so lang. Passt. Doch was machen wir jetzt mit den 
doch arg knappen 5us, welche maximal als Pause zulässig sind? 5us sind 
nicht wirklich viel Zeit, auch nicht bei 16 MHz CPU-Takt. Wir nehmen die 
sportliche Herausforderung an!

Der IRMP basiert darauf, daß das Signal vom IR-Empfänger mit 10-20kHz 
abgetastet und dann dekodiert wird. Sagen wir 16 kHz, das sind 62,5us 
Periodendauer. Wenn gleich die Auswertung schnell ist, so sind 5us recht 
knapp. Wir wollen also nicht die Dekodierung in Echtzeit im 
Timer-Interrupt machen, wie es IRMP standardmäßig macht. Anstelle dessen 
werden nur die Informationen der Abtastung gespeichert und später zur 
günstigen Zeit ausgewertet. D.h. der Timerinterrupt liest nur das 
IR-Data Signal und speichert es in einem Array. Sozusagen ein 
Logikanalysator mit 1 Bit. So weit, so gut.

Aber trotzdem ist das so eine Sache. 5us sind für eine echt kurze ISR 
incl. Hin- und Rücksprung zwar machbar, auch in C, aber es bleibt ein 
relativ großer Overhead an CPU-Last, welcher eher ungünstig ist. Mit den 
hier verwendeten FIFO-Funktionen wird die Zeit zu lang, wie man im 
Screenshots Timing_ISR_short und Timing_ISR_long.png sieht. Selbst der 
kurze Durchlauf ohne FIFO-Zugriff reißt eine 6.4us Lücke, der lange mit 
FIFO-Zugriff ca. 8,7us. Man sieht auch, daß der Testpuls SYNC, welcher 
im C ganz am Anfang und Ende der ISR steht, deutlich kürzer ist. Die 
restliche Zeit ist nicht meßbar und wird zum An/Abspringen der ISR sowie 
Register sichern/wiederherstellen benötigt! Das sieht man auch recht gut 
im *.lss File im Unterordner default.
ISR(COMPA_VECT) {
 328:   1f 92           push    r1
 32a:   0f 92           push    r0
 32c:   0f b6           in  r0, 0x3f    ; 63
 32e:   0f 92           push    r0
 330:   0b b6           in  r0, 0x3b    ; 59
 332:   0f 92           push    r0
 334:   11 24           eor r1, r1
 336:   2f 93           push    r18
 338:   8f 93           push    r24
 33a:   9f 93           push    r25
 33c:   ef 93           push    r30
 33e:   ff 93           push    r31

Satte 9xpush + 3 einfache Befehle + 4 Takte zum ISR-EinSsprung macht mal 
locker 25 Takte! Das Gleiche beim Beenden!

Darum wählen wir einen etwas unorthodoxen Ansatz. Während der 
Übertragung der LED-Daten werden die Interrupts global gesperrt (I-Bit 
der CPU = 0). Nach jedem Byte wird allerdings geprüft, ob das 
Interruptflag des Timers, welcher ja weiter läuft, schon gesetzt ist. 
Denn das passiert immer, egal ob der Interrupt freigegeben ist oder 
nicht! Man kann den Timer somit auch im Abfragebetrieb, neudeutsch 
"Polling" betreiben. Und genau das tun wir hier. Ist das Timerflag 
gesetzt, führen wir die Aktion der Timer-ISR direkt vor Ort aus. Das 
spart das Hin- und Rückspringen sowie Register sichern. Das verschafft 
uns wertvolle CPU-Zeit, die man im Falle einer komplexeren Operation gut 
gebrauchen kann. Das Ganze packen wir in eine 2. Assemblerfunktion, die 
neben der LED-Datenausgabe auch noch die IR-Daten abtastet und im FIFO 
speichert. Weil während der Interruptsperre auch der Softwarezähler in 
der ISR nicht weiter läuft, wird das auch in der Assemblerfunktion mit 
erledigt, damit stimmt das Gesamttiming wieder.

Die übertragung der LED-Daten dauert 1,2us/Bit * 24Bit/LED * 300LED = 
8640us. Bei 16 kHz Abtastfrequenz sind das ca. 138 Samples. Runden wir 
das mal großzügig auf 256 Samples = 32 Bytes auf. Dieser werden als 
FIFO benutzt. D.h. während die Timer-ISR mit 16 kHz neue Daten 
aufnimmt, werden die bereit vorhandenen Daten in den IRMP gefüttert und 
verarbeitet. Das FIFO ist ein wenig vereinfacht, es gibt keine 
Echtzeitprüfung auf Überlauf. Es wird nur am Anfang der LED-Übertragung 
geprüft, ob genügend Platz im FIFO ist. Wenn nicht, war die Dekodierung 
zu langsam und es kann ein Fehler signalisiert werden. Im Beispiel ist 
de FIFO sogar 64 Bytes groß. Warum? Weil die UART-Ausgabe mit 9600 Baud 
ziemlich langsam ist, ein Zeichen dauert mehr als 1ms! So lang ist auch 
ca. ein Bit der IR-Übertragung! Wenn gleich der Interrupt während der 
UART-Ausgabe weiter läuft und Daten sammelt, werden diese nicht 
ausgewertet! Wenn also zu lange Strings per UART ausgegeben werden, wird 
irgendwann mal der FIFO überlaufen. Abhilfte schaffen hier eine deutlich 
höhere Baudrate, ein größeres FIFO oder eine UART-Ausgabe mit 
Interrupts.

Das Update der LED-Kette erfolgt im 20ms Raster, d.h. es bleiben ca. 
11,5ms für die IR-Dekodierung und andere Dinge übrig. Das ist mehr als 
genug. Die Steuerung der 3 Testprogramme sowie deren Geschwindigkeit 
erfolgt über die empfangenen IR-Codes meiner Fernseherfernbedienung, die 
entgegen den Aussagen im Artikel IRMP noch mit RC5 Code arbeitet ;-) 
Mittels der Lautstärketasten (+/-) kann man die Geschwindigkeit 
einstellen, mittels der Programmwahltasten (+/-) das Testprogramm. Mit 
der POWER Taste kann man die LEDs dunkel schalten. Es werden nur die 
Codes der ersten Betätigung ausgewertet, die nachfolgenden bei 
gehaltener Taste werden ignoriert. Das kann man ggf. auch ändern. 
Parallel dazu erfolgt die Ausgabe per UART mit 9600 Baud, dann sieht 
man, welche Tastencodes empfangen wurden.

OK, das ganz große Luxusziel der Ansteuerung nur mit C und SPI wurde 
verfehlt. Aber bei DEN engen Timinganforderungen ist das auch 
illusorisch. Aber dennoch wurde gezeigt, wie man zwei zeitlich 
anspruchsvolle Aufgaben multiplexen kann, und damit problemlos mit nur 
einem eher kleinen Mikrocontroller auskommt, auch wenn man zur 
Assembler-Schrotflinte greifen muss ;-)

In Zukunft ist es jedoch SEHR zu empfehlen, LEDs mit DEUTLICH längerer 
Reset-Zeit und entspannterem Timing zu nutzen, wie sie hier im Thread 
genannt wurden. Dann kann man auch auf Assembler verzichten. Das 
Grundkonzept bleibt aber gleich!

Im Anhang ein paar Screenshots vom Timing und Versuchsaufbau.

Timing_WS2812B_bit.png      Bitabstand innerhalb eines Bytes
Timing_WS2812B_byte.png     Bitabstand zwischen Bytes
Timing_WS2812B_sample.png   Bitabstand zwischen Bytes beim Sampling und 
Speicherung im FIFO

Hinweis! In meinem Test wird der LED-Streifen direkt vom Arduino mit 5V 
versorgt. Das geht natürlich nur, wenn man nur sehr wenige LEDs mit 
voller Stromstärke einschaltet! Will man mehr LEDs gleichzeitig leuchten 
lassen, muss man ein externes Netzteil anschließen und die 5V vom 
Arduino abklemmen! Wenn man alle 300 LEDs gleichzeitg mit voller 
Stromstärke einschalten WÜRDE, würde der LED-Streifen 18A ziehen! Das 
klappt praktisch natürlich nicht, weil dann der Spannungsabfall auf den 
dünnen Leitungen viel zu groß wird. Wer dennoch mögichst viele LEDs 
leuchten lassen, will, muss mit dicken Leitungen vom Netzteil an 
Zwischenpunkten einspeisen. Ich würde mal 2,5mm^2 Querschnitt und eine 
Einspeisung pro Meter empfehlen.

von Falk B. (falk)


Bewertung
2 lesenswert
nicht lesenswert
Hier noch ein Video des Aufbaus, sowas liegt ja im Trend ;-)

https://youtu.be/R85U29fj_Rw

Uiii, mein allererstes Youtube-Video!!!

von Ralf M. M. (ramime)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> So, da bin ich mal wieder.

Danke für die ausführliche Erklärung, so hat man auch als nur "Mitleser" 
was davon

: Bearbeitet durch User
von Falk B. (falk)


Bewertung
2 lesenswert
nicht lesenswert
Nachtrag zur Unmöglichkeit des vollen LED-Stroms.

Beitrag "Re: Led- Lichterkette der besonderen Art."

Ich kann im Moment nicht messen, wie hoch der Widerstand der +5V/GND 
Leitungen dieser Streifen ist. Es sind ca. 4mm breite Bahnen. Sind wir 
mal optimistisch und gehen von 35um Dicke aus, macht das 0,14mm^2 
Querschnitt. 8-0

Wenn wir von

N = 300 LEDs (RGB)
I-LED = 60mA/LED (RGB zusammen)
17mm Abstand
0,14mm^2 Querschnitt
18mOhm mm^2/m (Kupfer)

ausgehen, kommen wir auf

300*60mA=18A Gesamtstrom
Rk = rho * l / A
   = 18 mohm mm^2/m * 0,017m / 0,14mm^2
   = 2,2mOhm 

zwischen den LEDs (jeweils auf GND und +5V)

Macht in Summe
U = N/2 * (N+1)*I-LED * 2 * Rk
  ~ N^2 * I-LED * Rk
  = 90000 * 60mA * 2,2mOhm
  = 11,9V

Bissel viel für ein 5V System ;-)

Ok, rechnen wir mal realistischer mit 0,5m LED-Streifen, einseitig 
gespeist, das ist gleichbedeutend mit 1m LED-Streifen und beidseitiger 
Speisung.
U ~ N^2 * I-LED * Rk
  = 900 * 60mA * 2,2mOhm
  = 0,122V

Das passt! Und jetzt mit 1m LED-Streifen einseitig (=2m LED zweiseitig)
U ~ N^2 * I-LED * Rk
  = 3600 * 60mA * 2,2mOhm
  = 0,483V

Das geht gerade noch so, d.h. man muss einen 5m LED-Streifen an den 
Enden sowie je 1,5m nach innen versetzt speisen. Zum Gegensteuern kann 
man ja mit 5,5V speisen, das ist noch OK.

von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Wer dennoch mögichst viele LEDs
> leuchten lassen, will, muss mit dicken Leitungen vom Netzteil an
> Zwischenpunkten einspeisen. Ich würde mal 2,5mm^2 Querschnitt und eine
> Einspeisung pro Meter empfehlen.

ich hatte alle 36 LEDs einen eigenen stepdown aus 24V gewählt um die 
Ströme beherschbar zu machen.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Damit ist SPI zumindest raus! Warum?
>
> Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560
> nicht so ganz schnell ist. D.h. man kann nicht lückenlos hintereinander
> Daten senden, auch wenn man die Schleife zur Datenausgabe mit nop()
> taktgenau optimiert.

Danke für's ausprobieren. Ich hatte das weiter oben im Thread schon mal 
nachgerechnet und kam auf das gleiche Ergebnis :)

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Falk B. schrieb:
> Denn die dort genannte Resetzeit von >50us sind real nur 5us, wie es
> auch schon im Artikel WS2812 Ansteuerung geschrieben steht.

Das ist natürlich böse. Offenbar gibt es da alles mögliche zwischen 5us 
und 280ms. Und alle nennen sich WS2812.

> Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560
> nicht so ganz schnell ist.

Meinst Du, dass dieses nur speziell beim ATmega 2560 so ist oder bei 
allen AVRs?

Alles in allem danke für den ausführlichen Test und Bericht, war eine 
Freude zu lesen :-)

von Reiner_Gast (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> So, da bin ich mal wieder.

Cha­peau! Wirklich tolle Zusammenfassung!

Da lag ich mit dem Overhead durch die ISR gar nicht schlecht ;-)

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Frank M. (ukw) (Moderator) Benutzerseite

>> Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560
>> nicht so ganz schnell ist.

>Meinst Du, dass dieses nur speziell beim ATmega 2560 so ist oder bei
>allen AVRs?

Das hab ich so noch nicht gesehen, wobei ich die Lücke vor Ewigkeiten 
mal als 1 CPU-Takt identifiziert habe. Das war aber auf einem ATtiny2313 
oder so.

Beitrag "Re: Atmega SPI Geschwindigkeit (Arduino schneller als C?)"

Beitrag "Re: SPI Codetuning"

http://www.matuschek.net/atmega-spi/

(Mein Gott, das Netz vergißt nichts)

>Alles in allem danke für den ausführlichen Test und Bericht, war eine
>Freude zu lesen :-)

Gern geschehen.

von batman (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Man kann sich das Leben auch schwer machen. Die gängigen IR-Protokolle 
lassen sich mit einer handvoll Codezeilen decodieren. Man braucht nicht 
immer ein fettes IRMP reinzuquetschen.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
batman schrieb:
> Man kann sich das Leben auch schwer machen. Die gängigen
> IR-Protokolle
> lassen sich mit einer handvoll Codezeilen decodieren. Man braucht nicht
> immer ein fettes IRMP reinzuquetschen.

Ja kann man ... Aber weshalb sollte man?

Klar, der Quellcode ist sehr lang, aber wenn IRMP entsprechend 
konfiguriert ist, wird nur das nötigste mit kompiliert und dann ist es 
nicht mehr fett.

Und ich finde IRMPs Sample-Ansatz sehr gut ... Der Sampler wird vom 
Timer aufgerufen und macht selbst nur sehr wenig.

Und ganz ehrlich, man kann sich das Leben auch schwer machen und das Rad 
immer wieder neu (und schlechter) erfinden ;-)

: Bearbeitet durch User
von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Klar, der Quellcode ist sehr lang,

und sprengt die Arduino IDE, als ich meine wordclock 2015 baute klappte 
es noch, als ich es mit neuester IRMP versuchen wollte leider nicht 
mehr.

von Mampf F. (mampf) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Mampf F. schrieb:
>> Klar, der Quellcode ist sehr lang,
>
> und sprengt die Arduino IDE, als ich meine wordclock 2015 baute klappte
> es noch, als ich es mit neuester IRMP versuchen wollte leider nicht
> mehr.

Hmm, hattest du alle Protokolle aktiviert?

Hatte mit IRMP bisher keine Probleme - auch nicht letztens auf einem 
ATMega8 (mit vUSB).

von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Mampf F. schrieb:
> Hmm, hattest du alle Protokolle aktiviert?

ja, daran wirds gelegen haben, wollte einen Uni Dekoder machen

nur welche lässt man dann weg für einen Code Erkenner?

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@Joachim B. (jar)

>> Hmm, hattest du alle Protokolle aktiviert?

>ja, daran wirds gelegen haben, wollte einen Uni Dekoder machen

Das sollte kein Problem sein.

>nur welche lässt man dann weg für einen Code Erkenner?

Gar keinen. Warum auch? Die paar kB Flash hat doch jeder. Was ging denn 
nicht?

von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Gar keinen. Warum auch? Die paar kB Flash hat doch jeder. Was ging denn
> nicht?

Die Arduino IDE stotterte konnte den gesammten Code nicht verarbeiten, 
file zu groß wenn ich mich recht erinnere, ist schon etwas her, habe 
dann abgebrochen.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal den IRMP im Normalzustand vermessen. Die ISR dauert dort 
3,5-9,2us, dazu kommen die nicht meßbare An- und Absprungzeit der ISR 
von ca. 3us bei 16 MHz CPU-Takt. Incl. Reserve sind vielleicht 15us im 
Maximum. Wenn man also LEDs hat bzw. kauft, welche 20us oder mehr als 
Pause vertragen, braucht man weder Assembler noch eine 
IRMP-Modifikation!

von Joachim B. (jar)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Wenn man also LEDs hat bzw. kauft, welche 20us oder mehr als
> Pause vertragen, braucht man weder Assembler noch eine
> IRMP-Modifikation!

meine wordclock von 2015 mit IRMP und 114 LEDs läuft ordentlich ohne 
Probleme.

Timer alle 10ms updatet die LEDs, IRMP ist mit IRQ alle 1/15000s dran

von Jan L. (ranzcopter)


Bewertung
0 lesenswert
nicht lesenswert
Joachim B. schrieb:
> Die Arduino IDE stotterte konnte den gesammten Code nicht verarbeiten,

das hab' ich noch nie erlebt; dass ein Compilat mal grösser als die 
Zielflashgrösse wurde, ok, das gibt aber ja bloss entsprechende 
Meldungen...

@Falk: total OT, aber ich glaube, der Nachfolger deiner 0.6.5 
uralt-Software ist diese hier: http://www.qdkingst.com/en/download :-)

von Horst M. (horst)


Bewertung
0 lesenswert
nicht lesenswert
Falk B. schrieb:
> Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560
> nicht so ganz schnell ist. D.h. man kann nicht lückenlos hintereinander
> Daten senden, auch wenn man die Schleife zur Datenausgabe mit nop()
> taktgenau optimiert. Es bleibt immer eine minimale Lücke von ca. 300ns
> (5 CPU-Takte), welche nicht unterschritten werden kann.

Was haste genommen, ein normales SPI?
Probier mal einen USART im Master-SPI-Mode, da ist das Tx-Register 
doppelt gepuffert.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Horst Meier (horst)

>Was haste genommen, ein normales SPI?

Ja.

>Probier mal einen USART im Master-SPI-Mode, da ist das Tx-Register
>doppelt gepuffert.

Kann sein, ist aber jetzt mit der Softwarelösung überflüssig.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
@ Jan L. (ranzcopter)

>@Falk: total OT, aber ich glaube, der Nachfolger deiner 0.6.5
>uralt-Software ist diese hier: http://www.qdkingst.com/en/download :-)

Hab ich probiert, die Software findet meinen LA nicht. Scheint die 
falsche Firmware zu haben. Außerdem meldet Windows beim Anstecken ein 
Problem, obwhl der alte Treiber mit der alten Software läuft. Ein 
Deinstallieren und neu Installieren des Treibers brachte keinen Erfolg. 
8-0
Ich glaub meine Hardware ist nicht kompatibel, denn von dem LA1016 gibt 
es diverse (Billig)Nachbauten.

von Falk B. (falk)


Angehängte Dateien:

Bewertung
2 lesenswert
nicht lesenswert
Das Bessere ist immer Feind des Guten. Ich hab mal meine Funktionen mit 
ein paar Macros aufgepeppt. Jetzt können sie mit 6,3-10MHz arbeiten, und 
das mit recht geringen Abweichungen vom optimalen Timing.

von Falk B. (falk)


Bewertung
0 lesenswert
nicht lesenswert
Arrrgh, Tippfehler! 6,3-20MHz natürlich!

von Falk B. (falk)


Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Sooo, da ich gerade mal wieder ein WS2811 Problem beheben musste, habe 
ich mal meine ASM-Funktion ein wenig aufgefrischt und optimiert. Man 
kann jetzt die Bitzeiten direkt in den Quelltext schreiben, die 
Berechnung der Delays erfolgt im Quelltext. Ebenso kann man zwischen LOW 
und HIGH Speed Modus wählen.

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.