Hallo, ich betreibe einige WS2812 an einem atmega328p. Nun möchte ich nach aussen hin eine Kommunikationsschnittstelle haben, bei der Daten hin und her geschrieben werden können. Bislang lese ich das ganze auf dem mega mit der ISR Lösung (aus dem Wiki) ein. Nur kommen hier ab und zu Fehler. Gibt es eine Möglichkeit, Daten zu empfangen über UART, ohne dass diese durch das deaktivieren der Interrupts (light ws2812b) gestört werden? Ggf. einen vorgeschalteten µC mit Uart (wahlweise einen 16u2 mit direktem usb Interface). Der alle Daten empfängt. Sobald der µC mit den Leds senden fertig ist. Denke da so an so etwas. Master beschickt die Leds mit Daten. Ein Pin wechselt nun ihren Zustand. Nun muss der Slave (an der USB Schnittstelle) die nächsten Daten senden, ehe der Pin erneut wechselt. Andere Möglichkeiten? Möchte bei avr bleiben, da ich mit arm bzw. anderne Herstellern keine Erfahrung habe.
Bei allem menschlichen Respekt, aber wer Ahnung hat, der weiß die Antwort; hat aber vor allem erst einmal eine Vorstellung davon, wo es eigentlich genau hakt - oder zumindest eine nicht unplausible Hypothese. Dazu hat er mindestens einige Monate gebraucht um dahin zu kommen, Schweiss und Tränen vergossen und einige Hektorliter Kaffee. Der Rest, zu dem Du augenscheinlich gehörst, hat sich irgendwas irgendwoher zusammenkopiert; weiß nicht, warum es geht und ist daher verloren, wenn es nicht geht. Dafür sind wir hier nicht die Feuerwehr. Entweder Du analysierst, - durchaus mit unserer Hilfe -, das Problem und löst es, - wiederum, falls nötig, mit unserer Hilfe -, oder Du lernst es alleine. Aber was Du fragst, ist eine der hier mit Recht so unbeliebten Rundumschlagprobleme: Die Antwort ist: Ja. Nein. Kommt darauf an. Sollte man lieber nicht. Wozu eigentlich (im Prinzip sollte sich ein AVR dabei zu Tode langweilen)? Also, was genau passiert? Was erkennst Du am Debugger oder auf sonst eine Weise? Welcher ungewollte Zustand tritt ein (in Begriffen des Programmes)? Was ist der Quellcode? Was das zugrundeliegende Systemdesign? Was die Schaltung?
Weshalb sollten die Interrupts deaktiviert werden ? Das macht man eignetlich nicht.
дамрфкнилх schrieb: > Weshalb sollten die Interrupts deaktiviert werden ? Das macht man > eignetlich nicht. Ich denke, daß seine WS2812-Library das erfordert, weil die LEDs per Bitbanging angesteuert werden und das Timing so kritisch ist, daß eine ISR es durcheinanderbringen würde.
:
Bearbeitet durch User
Thomas E. schrieb: > weil die LEDs per > Bitbanging angesteuert werden und das Timing so kritisch ist, daß eine > ISR es durcheinanderbringen würde. Er könnte auch das regelmäßige Polling des UART (und wegschreiben des empfangenen Bytes) in die WS2812-Routinen einbauen, das sollte zeitlich locker ausreichen. Auswerten kann er sie dann wenn er mit einer kompletten Sequenz durch ist und Zeit hat.
Wenn man die ISR kurz hält (< 4µs), sollte es sogar ausreichen, in der Lib an geeigneter Stelle (= bei Low-Pegel des Ausgangs) die Interrupts kurz zuzulassen.
Sebbi schrieb: > Gibt es eine Möglichkeit, Daten zu empfangen über UART, ohne dass diese > durch das deaktivieren der Interrupts (light ws2812b) gestört werden? Die "offizielle" Lösung für UART-Schnittstellen nennt sich Hardware Handshake. Dabei wartet der sendende Rechner (hier wohl ein PC) bis sein Handshake-Eingang aktiv wird. > Denke da so an so etwas. > Master beschickt die Leds mit Daten. > Ein Pin wechselt nun ihren Zustand. Nun muss der Slave (an der USB > Schnittstelle) die nächsten Daten senden, ehe der Pin erneut wechselt. Dieser Pin ist der Handshake-Ausgang des Masters und nennt sich RTS. Der wird mit dem CTS-Eingang des PC verbunden. Ein zwischengeschalteter Slave ist dafür nicht nötig. Natürlich muss das Programm auf dem PC die Schnittstelle richtig bedienen, was leider nicht immer funktioniert. Aber Versuch macht kluch...
Eine Beleuchtung kommuniziert ja nicht dauern, daher ist ein zweimikrosekunden Zucken nicht stoerend.
дамрфкнилх schrieb: > Weshalb sollten die Interrupts deaktiviert werden ? Das macht man > eignetlich nicht. Natürlich macht man das, nur ist der Programmierer dafür verantwortlich, dass es nur an kritischen Stellen (z.B. Read-Modify-Write oder Wert lesen/Status rücksetzen) geschieht und nur für wenige Takte bzw. µs. Dann kann das aber unmöglich den UART-Empfang stören. Wo du recht hast: längeres Deaktivieren ist IMMER ein Fehler, der muss zuerst beseitigt werden. In jedem Fall muss der TO erst mal lokalisieren wo der Fehler liegt statt im Nebel herumzustochern. Ist natürlich schwer, wenn man bloss unverstandene Code-Bruchstücke per Cut-and-Paste aneinanderreiht, aber ohne Verständnis kann man halt nicht Programme schreiben. Georg
дамрфкнилх schrieb: > Eine Beleuchtung kommuniziert ja nicht dauern, daher ist ein > zweimikrosekunden Zucken nicht stoerend. Die WS2812 zucken aber nicht nur, sondern zeigen völligen Blödsinn an, wenn mal ein kurzer High-Impuls durch das Zwischenfunken einer ISR von 0.625µs auf einige µs gedehnt wird. Wenn man WS2812 mit Datenblatt-konformen Timing per Bit-Banging ansteuern will, geht das nicht mit Interrupts
:
Bearbeitet durch User
Thomas E. schrieb: > Die WS2812 zucken aber nicht nur, sondern zeigen völligen Blödsinn an, > wenn mal ein kurzer High-Impuls durch das Zwischenfunken einer ISR von > 0.625µs auf einige µs gedehnt wird. Na und, das ist doch ein Standardfall: IE aus - 0,6 s Impuls erzeugen - IE wieder an. Null Problemo würde Alf sagen. Und der UART-Empfang wird sicher nicht gestört, wenn Interrupts 1 µs lang nicht erlaubt sind. Georg
@Sebbi Wiedermal viel blabla hier zu lesen. Deshalb auch mal was nützliches: Du hast ein grundsätzliches Problem, da du zwei Komponenten verwendest, die ohne Clock-Signal kommunizieren wollen. Da dies gleichzeitig auftreten kann (UART ohne Hardware-Handshake angenommen, was die Regel ist), wird es immer mal vorkommen, dass eine Kompoente versagt. Während man beim UART-Senden das noch schön vermeiden kann, ist das Empfangen unmöglich zu bewerkstelligen, da es "irgendwann" auftreten kann und WENN es auftritt, darf die Routine nicht unterbrochen werden, da das Timing kritisch ist. Möglichkeiten: 1. AVR mit UART Modul verwenden. Wenn dein PC an die MCU jeweils nur 1 Byte sendet (z.B. Statusbyte), ist das die Lösung. Wenn du mehrere Bytes sendest, könnte es noch die Lösung sein, wenn die Baudrate gering eingestellt ist. (Der AVR Buffer ist nur 1 Byte gross). 2. XMEGA oder sonstige MCU mit DMA verwenden (Anfänger? Lass es.) 3. UART Hardware Handshake Versteh erstmal das grundsätzliche Problem. Das lässt sich auf viele andere Systeme übertragen.
:
Bearbeitet durch User
Christian S. schrieb: > ist das Empfangen > unmöglich zu bewerkstelligen, da es "irgendwann" auftreten kann und WENN > es auftritt, darf die Routine nicht unterbrochen werden Durch die Tatsache daß man mit dem lesen des empfangenen Bytes warten kann bis kurz vor dem Empfang des nächsten entspannt sich das schon wieder und ist gar nicht mehr so dramatisch. Man muss sich halt einfach mal ausrechnen wieviel Zeit zwischen zwei empfangenen Bytes vergeht, wieviel Zeit man noch übrig hat zwischen zwei Bits für die Lichterkette, wie lange es dauern wird ein Byte vom UART abzuholen und wegzuschreiben, notfalls mal ein Timing-Diagramm an die Wand malen, einen Schritt zurücktreten und sich überlegen wie man das am geschicktesten ineinander verschachtet. Und schon hat man einen Plan. Der Rest ist dann Fleißarbeit.
Die einfachste Lösung ist vielleicht, die Baudrate soweit herunterzuschrauben, daß die serielle Übertragung zum Füllen der zwei Bytes Empfangspuffer länger dauert, als die Übertagung der Daten an alle LEDs. Für einfache Kommandos reichen 1200 Baud sicher auch aus...
Hallo Sebbi, es gibt auch die Möglichkeit, den WS2812 über die SPI-Schnittstelle zu betreiben. dabei wird nicht das SPI-Protokoll genutzt, sondern über den SPI-Data-Pin das Bitmuster erzeugt, das der WS2812 benötigt. Such mal hier nach WS2812 und SPI. Der einzige andere mögliche Weg ist der von Bernd beschriebene, der aber auf jeden Fall Asm-Code und eine ziemlich hässliche Verschachtelung erfordert: Bernd K. schrieb: > Er könnte auch das regelmäßige Polling des UART (und wegschreiben des > empfangenen Bytes) in die WS2812-Routinen einbauen, das sollte zeitlich > locker ausreichen. Auswerten kann er sie dann wenn er mit einer > kompletten Sequenz durch ist und Zeit hat. Gruß, Stefan
Sebbi schrieb: > ich betreibe einige WS2812 an einem atmega328p. > Master beschickt die Leds mit Daten. Wieviele und mit welchen Daten ? z.B. 300 LEDs sind 900Bytes RGB. UART: 250KB sind 25000Byt = 40us * 900Byt = 36ms. WS2812: 300 LEDs * 30us = 9ms =================================================== Ergibt 45ms. Das wird schon mal schwierig mit Daten in Echtzeit. > Ein Pin wechselt nun ihren Zustand. Nun muss der Slave (an der USB > Schnittstelle) die nächsten Daten senden, ehe der Pin erneut wechselt. Mega328p hat in UCSR0A einen bit (RxC0), den kann man zwischendurch mal gemutlich abfragen, anstatt mit ISR zu arbeiten, etwa so:
1 | Byt2WS2812:
|
2 | ... ;*** DataPin fur WS2812 auf High, bit holen (shift) 7 Takte |
3 | ... ;*** DataPin entsprechend dem Bitwert setzen 7 Takte |
4 | ... ;*** DataPin fur WS2812 wieder auf LOW (PORT ) 1 Takt |
5 | lds r16, UCSR0A ; 2 |
6 | dec BitCnt ; 1 |
7 | brne Byt2WS2812 ; 2 |
8 | ;================================================================================= |
9 | ; 20 Takte |
10 | ;*** R-G-B gesendet, jetzt wird UART abgefragt... |
11 | lds r17, UDR0 ; 2 / 2 |
12 | sbrs r16, RXC0 ; 1 / 2 |
13 | rjmp NoUart ; 2 |
14 | st X+, r17 ; 2 |
15 | ret
|
16 | NoUart: |
17 | nop ; 1 |
18 | ret ;=========== |
19 | ; 6 / 6 Takte |
Das sind 6 Takte zusatzlich, bei 328p mit 16MHz brauchst du zwischen 16 und 24 Takte fur einen bit beim WS2812-Bitbanging (20 Takte +/- 4 Takte), da kann man sogar zwischen den einzelnen bits UART abfragen, nur darf die Pause zwischen den einzelnen Bytes nicht langer als 10us sein, ansonsten wird Reset ausgelost (WS2812 ist da zickig, nichts mit 50us wie im DaBla). UART braucht beim 250Kb 40us pro Byt, WS2812 aber nur 30us fur R-G-B, da konnen auch keine Bytes verloren gehen. Das funktioniert so, keine Angst.
Früher (TM) also viel früher, so im letzten Jahrtausend, da gab's durchaus die Möglichkeit nur ein Byte an ein Gerät zu senden und dann auf das Echo dieses Zeichens zu warten. Erst dann wurde das nächste Byte gesendet. Das ist natürlich heutzutage verboten und darum braucht man auch für blinkende Leuchtdioden einen vier-Kern ARM.
Norbert schrieb: > dann auf das Echo dieses Zeichens zu warten. > Erst dann wurde das nächste Byte gesendet. > > Das ist natürlich heutzutage verboten und darum braucht man auch für > blinkende Leuchtdioden einen vier-Kern ARM. Bullshit. Die gestellte Aufgabe ist locker mit dem kleinsten ATTiny zu lösen der gerade eben noch ein UART eingebaut hat. Der PC kann jederzeit und so schnell senden wie er kann, die Lichterkette wird nicht flackern. Alles was man braucht ist sich die Zeit richtig einzuteilen, und von der dafür nötigen Zeit ist auch auf dem kleinsten Tiny noch genügend vorhanden.
Bernd K. schrieb: > Alles was man braucht ist sich die Zeit richtig einzuteilen, und von der > dafür nötigen Zeit ist auch auf dem kleinsten Tiny noch genügend > vorhanden. So isses - aber es erfordert eben ein bisschen mehr Gehirnschmalz, als bloß eine paar Funktionsaufrufe in fertige vorgekaute Standard-Libraries, wie das heute so üblich ist...
Norbert schrieb: > Früher (TM) also viel früher, so im letzten Jahrtausend, da > gab's durchaus die Möglichkeit nur ein Byte an ein Gerät zu senden und > dann auf das Echo dieses Zeichens zu warten. > Erst dann wurde das nächste Byte gesendet. Auch im letzten Jahrtausend war das keine gute Idee: Im besten Fall halbiert das die Übertragungsgeschwindigkeit. Das setzt aber voraus, daß de Host auf jedes Zeichen sofort reagiert. Jede Verzögerung auf Seiten des Host wirkt sich massif auf die Geschwindigkeit aus. Bei Verwendung eines FTDI o.ä. wird es noch schlimmer: Über USB werden die Daten im 1ms-Raster übertragen. Bei Deinem Verfahren wird in einem Frame ein Zeichen an den Host gesendet, daraufhin darf das auf dem Host laufende Programm ein Echo generieren, das in einem der nächsten USB-Frames wieder zurück an den mc gesendet wird. Auf diese Weise wird für die Übertragung eines bytes mindestens 4 USB-Frames == 4ms benötigt, entsprechend einer Baudrate von 2500 Baud. Gruß, Stefan
Was spricht hier gegen die Verwendung eines Hardware-Handshakes? Genau für solche Fälle wurde das doch erfunden.
Je nach Hardware kann es sein, daß nach einem gesetzten Handshake noch einige Zeichen gesendet werden, z.B. weil der Sende-UART einen FIFO besitzt. Wir haben an Windows-Systemen schon bis zu 16 gesendete Zeichen nach der Handshake-Flanke gemessen. Die Intention des Handshake ist ja eigendlich, daß der Empfänger keinen Platz mehr im Eingangspuffer hat. In diesem Fall kann ein Sende-FIFO leicht kompensiert werden, indem einfach n Bytes vor Buffer-full das Handshake gesetzt wird. Gruß, Stefan
Stefan K. schrieb: > Je nach Hardware kann es sein, daß nach einem gesetzten Handshake noch > einige Zeichen gesendet werden, z.B. weil der Sende-UART einen FIFO > besitzt. Wir haben an Windows-Systemen schon bis zu 16 gesendete Zeichen > nach der Handshake-Flanke gemessen. > Die Intention des Handshake ist ja eigendlich, daß der Empfänger keinen > Platz mehr im Eingangspuffer hat. In diesem Fall kann ein Sende-FIFO > leicht kompensiert werden, indem einfach n Bytes vor Buffer-full das > Handshake gesetzt wird. Hier gehts aber eher darum, dass vor rausschieben an die WS2812 die Interrupts gesperrt werden sollen. Aber man kann natürlich auch die Interrupts sperren, der Gegenstelle per Handshake die Dendefreigabe entziehen und dann einfach ein bischen warten, ob noch was kommt. Kommt was, dann beginnt die Wartezeit von vorne, kommt innerhalb der Wartezeit nichts mehr, dann ist das Handshake-Verbot wirksam und man beginnt auf die WS2812 rauszutakten. Ist eine Möglichkeit. Und ich schliesse mich vollinhaltlich Thomas Elger an.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.