Forum: Mikrocontroller und Digitale Elektronik WS2812 mit abweichendem Timing?


von Mike (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe ein kleines Programm zur Ansteuerung einesFarb-LED-Streifens 
geschrieben. Das Ding stammt vom Chinesen und enthält laut Beschreibung 
LEDs vom Typ WS2812B. Ich nutze den UART eines Pic32 zur Ansteuerung. 
Der UART ist auf eine Baudrate von 4 MBaud und auf 8bit + 1 Start- und 
Stopbit eingestellt. Jeweils 5 UART-Bits erzeugen 1 bit für die WS2812B. 
Pro Byte werden daher 2 Bits für die LEDs gesendet. Der Ausgang TX des 
UARTs ist über einen Transistor als Pegelwandler und Inverter mit DIN 
der ersten LED verbunden (s. Anhang).

Nun funktioniert das Ganze prima, wenn ich den LED-Streifen das erste 
Mal beschreibe. Sende ich unmittelbar danach einen zweiten Datenstring, 
kommen die Farben durcheinander und es leuchten LEDs auf, die gar nicht 
angesteuert wurden.
Interessanterweise lässt sich das Problem lösen, wenn ich die 
Reset-Pause zwischen zwei Schreibvorgängen von 50 auf 100µs erhöhe. Ich 
dachte zunächst, dass ich mich verrechnet habe, aber Nachmessen mit dem 
Oszilloskop zeigte, dass das Timing stimmt. Es sieht so aus, als dass 
die nach der 50µs-Pause gesendeten neuen Daten an die folgenden LEDs 
weitergereicht werden anstatt von der ersten LED "geschluckt" zu werden. 
Alles spricht dafür, dass 50µs nicht als Reset-Signal ausreichen.

In der Praxis ist das nicht allzu schlimm, denn es macht wenig Sinn, 
nach 50µs gleich wieder ein neues Farbmuster zu senden.

Kann es sein, dass hier LEDs mit abweichendem Timingverhalten verbaut 
wurden?
1
#define  SYS_FREQ 48000000 // 48 MHz
2
#define DELAY_US 50       // 50 us gap delay
3
void ws2812(unsigned int* grb, unsigned int numLeds) 
4
{
5
    unsigned int timer;
6
    unsigned int i,j;
7
    unsigned int ledColor;
8
//UART codes for bit pairs 00, 01, 10, 11
9
    const unsigned char ColorCode[4] = {0xEF,0x8F,0xEC,0x8C}; 
10
  
11
    while (BusyUART1()); //wait until previous write operation has terminated
12
    while ((ReadCoreTimer()-timer) < (SYS_FREQ/2000000UL)*DELAY_US); //delay 50µs
13
14
    for (i=0;i < numLeds;i++)
15
    {
16
        ledColor = grb[i];
17
        for (j=0;j<12;j++)
18
        {
19
           ledColor &= 0x00FFFFFF; //mask out last 24 bits
20
           ledColor <<=2 ;     //shift 2 bits
21
22
           while (BusyUART1());
23
           WriteUART1(ColorCode[ledColor>>24]); //send 2 bits to LED
24
        }
25
    }
26
    timer = ReadCoreTimer(); // beginning of 50µs reset period
27
}

von Guest (Gast)


Lesenswert?

Wenn ich mich nicht ganz irre ist die Reste Zeit doch mindestens 50us. 
Es würde mich jetzt nicht wirklich wundern wenn die 50us nicht 
zuverlässig funktionieren. Ich hab immer 60us genommen und nie Probleme.

von Falk B. (falk)


Lesenswert?

Mike schrieb:

> Pro Byte werden daher 2 Bits für die LEDs gesendet. Der Ausgang TX des
> UARTs ist über einen Transistor als Pegelwandler und Inverter mit DIN
> der ersten LED verbunden (s. Anhang).

Tu dir selber einen Gefallen und nimm einen RICHTIGEN Inverter, 
irgendein Gatter der HCT Serie. Dein Pegelwandler taugt nicht viel, auch 
wenn er hier anscheinend funktioniert.

> Alles spricht dafür, dass 50µs nicht als Reset-Signal ausreichen.

Es gibt viele dieser LEDs mit sehr unterschiedlichen Reset-Zeiten, 
einige sogar UNTER 5 (FÜNF) Mikrosekunden!

> Kann es sein, dass hier LEDs mit abweichendem Timingverhalten verbaut
> wurden?

JA!

von c-hater (Gast)


Lesenswert?

Mike schrieb:

> Alles spricht dafür, dass 50µs nicht als Reset-Signal ausreichen.

Bei originalen WS28xx genügen viel weniger als 50µs für den Latch. Das 
ist eher so bei 6µs.

> Kann es sein, dass hier LEDs mit abweichendem Timingverhalten verbaut
> wurden?

Würde ich nicht völlig ausschließen wollen, aber sehr viel verdächtiger 
ist ja wohl diese schräge Inverterstufe...

Hast du die mal simuliert? Was passiert, wenn du die mal durch ein 
schnödes Logik-Gatter ersetzt?

von Mike (Gast)


Lesenswert?

c-hater schrieb:
> ... aber sehr viel verdächtiger ist ja wohl diese schräge Inverterstufe...
Was ist daran schräg? Es handelt sich um eine normale Emitterschaltung 
mit Schottky-Clamping. Die ansteigende Flanke hat damit etwa 40ns 
Anstiegszeit, die fallende ist etwas schneller. Allerdings ist mein 
Oszilloskop (Hameg 205-3) auch nicht das schnellste. An den Ausgängen 
der LEDs sieht es aber auch nicht viel anders aus.
> Was passiert, wenn du die mal durch ein schnödes Logik-Gatter ersetzt?

Kann ich mal probieren, irgendwo in der Bastelkiste müsste noch ein 
74LS00 o.ä. rumliegen. Ich glaube aber nicht, dass da das Pröblem liegt, 
denn mit 100µs Reset passt es ja. Wenn es an den Schaltflanken läge, 
würde es zuerst an den viel kürzeren Pulsen für T0H und T1L scheitern.

von Teo D. (teoderix)


Lesenswert?

Mike schrieb:
> enthält laut Beschreibung
> LEDs vom Typ WS2812B.

Welche Version?!
Gug mal V5:
http://www.world-semi.com/DownLoadFile/108

von Mike (Gast)


Lesenswert?

Teo D. schrieb:
> Mike schrieb:
>> enthält laut Beschreibung
>> LEDs vom Typ WS2812B.
>
> Welche Version?!
> Gug mal V5:
> http://www.world-semi.com/DownLoadFile/108


Danke, das passt exakt zu meinen Messungen. 500ns, obwohl innerhalb der 
Spezifikation der Standard WS2812B werden definitv nicht als T0H erkannt

Am Ausgang der Dioden ist der T0H-Puls 250ns, T1H 500ns lang. Mit 250nS 
für T0H und 750nS für T1H bin ich auf jeden Fall auf der sicheren Seite. 
Den Reset Puls werde ich mal auf 300µs erhöhen.

Schön ist auch, dass jetzt V_IHmin bei 2.7V liegt. Da müsste man 
eigentlich auf den Pegelwandler von 3.3 auf 5V verzichten können. Die 
Invertierung des UART-Ausgangs läßt sich beim PIC32 per Software 
realisieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.