Hallo ich will eine Wortuhr bauen mit WS2812 LED Pixel als Anzeige. Es gibt ja auf dieser Seite eine Zusammenfassung über die Ansteuerung: https://www.mikrocontroller.net/articles/WS2812_Ansteuerung Ich wollte einen Streifen aus ca 10 LEDs mal zum testen mit einem PIC16F887 ansteuern. Es werden ja 24 Bits in einer Reihe gesendet für ein LED (G;R;B). Zum testen habe ich den Ausgang direkt im Code ohne Schleifen etc. 24-Mal ein und ausgeschaltet. Für 0-Bits schalte ich den Ausgang ein und direkt wieder aus. Laut anderen Quellen spielt die Low-Dauer so gut wie keine Rolle. Für ein 1 füge ich zwischen ein- und ausschalten 2 NOP() Aufrufe ein. Beispiel: Low-Bit: Pin = 1; Pin = 0; High-Bit: Pin = 1; NOP(); NOP(); Pin = 0; Ich habe eine Taktfrequenz von 8MHz (Interner Oszillator). Daher wäre das ja: 2x(1/(8MHz/4))=500ns. Alles über und um die 500ns High Time sollte eigentlich als 1 interpretiert werden. Das LED schaltet sich dann auch ein, aber immer weiss. Auch wenn ich nur 0-Bits zu senden versuche. Das heisst, jedes Bit wird eigentlich als 1 erkannt, was heissen müsste, dass die Zeit zwischen ein- und ausschalten zu lang wäre. Habe schon überlegt, ob meine Taktfrequenz zu niedrig ist. Mit dem Multimeter messe ich am Ausgangspin um die 33kHz, wenn ich ihn im Programmcode ständig invertiere, was ja viel zu niedrig wäre. Weiss aber nicht, ob das Multimeter was taugt zum Frequenz messen. Daher hier mal meine Konfiguration der Frequenz, vielleicht sieht jemand einen Fehler: #include <xc.h> #include <stdlib.h> #include "../Include/ws2812.h" #define _XTAL_FREQ 8000000 // CONFIG1 #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = ON #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = OFF #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = OFF // CONFIG2 #pragma config BOR4V = BOR40V #pragma config WRT = OFF void main(void) { ANSEL=ANSELH=0x00; OSCCON=0b01110001; } Im Anhang ist noch der entsprechende Datenblatt-Auszug für das OSCCON Register. Hat jemand eine Ahnung, wo das Problem liegen könnte? Wäre sehr dankbar für irgendwelche hilfreichen Tipps. MFG
>Wäre sehr dankbar für irgendwelche hilfreichen Tipps.
Besorg dir einen Arduino.
Kurt Immer schrieb: > Beispiel: > Low-Bit: > Pin = 1; > Pin = 0; > > High-Bit: > Pin = 1; > NOP(); > NOP(); > Pin = 0; So wird das nichts. Siehst du ja selbst. High: Out = 1 Long Delay Out = 0 Short Delay Low: Out = 1 Short Delay Out = 0 Long Delay Die Zeiten für ein ganzes Null- oder Einsbit müssen jeweils etwa gleich lang sein.
Habe das Programm jetzt so geändert wie du gesagt hast. High Bit: OUTPUT = 1; NOP(); NOP(); OUTPUT = 0; NOP(); Low Bit: OUTPUT = 1; NOP(); OUTPUT = 0; NOP(); NOP(); Ein NOP müsste bei einer Frequenz von 8MHz 500ns entsprechen (habe es oben falsch berechnet.) Somit liegt es laut Mikrocontroller.net überall in der Toleranz, sofern meine Taktfrequenz stimmt: High Bit: Th=1us Tl=0.5us Low Bit: Th=0.5us Tl=1us Leider wird die LED nach wie vor nur weiss, was heissen müsste das mindestens der grösste Teil der Bits als 1 interpretiert wird. Leider habe ich mit 8MHz Taktfrequenz keine feinere Auflösung als 500ns.
Forumsuche bemühen. Es gibt ausreichend funktionierenden Code für die WS2812, u.a.: Beitrag "Lightweight WS2811/WS2812 Library"
Wenn du es selber machen möchtest, sprich ohne Lib - was ich durchaus nachvollziehen kann, ist ein Logic Analyzer an dieser Stelle eigentlich Pflicht. So ein Saleae Clone kostet <10€ und mit der Software Sigrok gibt es auch einen passenden WS2812 Dekoder.
Kurt Immer schrieb: > Leider habe ich mit 8MHz Taktfrequenz keine feinere Auflösung als 500ns. Ich kenne deinen Controller nicht, aber das dürfte das Problem sein. Mit einem AVR ohne besondere Tricks in C schaffe ich die Ansteuerung mit min. 6MHz. Ein Instruction Cycle bei 6MHz ist beim AVR aber 167ns lang.
Kurt Immer schrieb: > Ein NOP müsste bei einer Frequenz von 8MHz 500ns entsprechen Thomas E. schrieb: > Mit > einem AVR ohne besondere Tricks in C schaffe ich die Ansteuerung mit > min. 6MHz. Ein Instruction Cycle bei 6MHz ist beim AVR aber 167ns lang. warum ist der PIC so lahm? ich dachte die sind schneller, schliesslich wurden die ersten Propeller Clocks mit PIC gemacht. http://pic-microcontroller.com/analog-digital-propeller-clock-using-pic16c84/
Was ist eigentlich
1 | NOP(); |
? Ist das wie beim AVR
1 | asm volatile ("nop"); |
? Falls ja: Da werden tatsächlich vier Takte verbruzelt?
Ralf G. schrieb: > Falls ja: Da werden tatsächlich vier Takte verbruzelt? Aus dem Datenblatt: Operating speed: - DC – 20 MHz oscillator/clock input - DC – 200 ns instruction cycle 200ns bei 20MHz bedeuten 500ns bei 8MHz.
denn hängt doch einfach einen arduino mini 328p an den PIC und lässt den das Timing machen :)
:
Bearbeitet durch User
Danke für die Antworten. Das Ding ist, dass der Clock beim Pic durch 4 geteilt wird, das ist dann der Instruction Clock, der Grund ist mir auch nicht bekannt. Und Ja, NOP kommt eigentlich vom Assembler, wurde aber beim XC8 Compiler als C Funktion implementiert glaube ich. Sollte also einen Taktzyklus verbrauchen. Werde wohl mal einen Controller mit schnellerem Oszillator suchen und erneut versuchen. Danke noch für den Tipp mit dem Logic Analyzer, werde ich mir anschauen.
Kurt Immer schrieb: > Werde wohl mal einen Controller mit schnellerem Oszillator suchen und > erneut versuchen. 8MHz sollten eigentlich reichen. Kannst du in einem Simulator den Code einfach mal Schritt für Schritt durchgehen und dabei die Takte zählen? Die Zuweisung an 'OUTPUT' dauert ja auch noch (ein paar Takte?).
Thomas E. schrieb: > Aus dem Datenblatt: > > Operating speed: > - DC – 20 MHz oscillator/clock input > - DC – 200 ns instruction cycle > > 200ns bei 20MHz bedeuten 500ns bei 8MHz. Ralf G. schrieb: > 8MHz sollten eigentlich reichen. wie kommst du darauf? Thomas hatte doch schon ins DB geschaut
:
Bearbeitet durch User
Kurt Immer schrieb: > Hat jemand eine Ahnung, wo das Problem liegen könnte? Ohne Oszilloskop wirst Du da wohl das Problem nicht so schnell finden, da das Timing bei den WS2812 kritisch ist.
:
Bearbeitet durch User
Beitrag #5219805 wurde vom Autor gelöscht.
Werde erstmal einen Arduino als Anzeigeprozessor verwenden, damit lief das ganze wie erwartet nach 10 Minuten :P. Habe mir noch den vorgeschlagenen Logic Analyser bestellt, scheint ein extrem geiles Ding zu sein. Dann kann ich mal die Outputs der Arduino Library mit dem Output von meinem PIC vergleichen. Sollte ein Weihnachtsgeschenk werden, daher habe ich keine Lust, mich ewigs mit diesem mühsamen asynchronen Protokoll zu beschäftigen. Gruss
Joachim B. schrieb: > wie kommst du darauf? > Thomas hatte doch schon ins DB geschaut Für den Test könnte es reichen, wenn jeder Befehl nur diese 4 Takte braucht. Hmm, ja, okay, ist natürlich nicht realistisch. Es müssen ja normalerweise zwischendurch auch noch Daten 'nachgeladen' werden.
Habe noch einen PIC18F4685 als Test genommen, damit hätte ich theoretisch mit 32MHz 125ns Auflösung. Damit bekam ich aber das gleiche Resultat: weisse LED, auch wenn ich nur ein NOP() für das High Bit genommen habe. Ich vermute, dass etwas mit meiner Taktfrequenz nicht stimmen muss, sonst müsste es doch gehen! Obwohl ich meinte, dass das OSCCON Register und die Einstellung im Configuration Word eigentlich die einzigen massgebenden Einstellungen für die Taktfrequenz sind. Ohne Logic Analyzer werde ich es wohl nicht herausfinden können, bis ich ihn erhalte. Daher werde ich mal meinen PIC mit den restlichen Aufgaben beschäftigen und das Arduino Nano mit der FastLED Library die Anzeige steuern lassen. Spart erst noch Zeit :).
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.