Hallo ich will eine Wortuhr bauen mit WS2812LED 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
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.
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.
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.
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
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.
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 Testkö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 :).