WS2812B datenkompatibel zu WS2812?

Gast #3833280
Lesenswert?

Hi,

ich habe einen LED-Streifen mit 4 x WS2812 aufgebaut, funktioniert seit 
Monaten wunderbar am ATtiny.

Habe dann bei Amazon einen Streifen mit 60 Stück WS2812B gekauft. 
Betreibe beide Streifen parallel, bei dem im Internet gekauften Streifen 
ist nix zu sehen!!! Wie kann das sein?
Mit dem Oszilloskop sehe ich, wie die Datenpakete von LED zu LED 
weitergereicht werden und das jeweils erste Datenpacket wird 
einbehalten.

(Ist quasi wie in der Schule, wenn Zettel verteilt werden:
"Einen nehmen, Rest weitergeben")

Ist der bei Amazon gekauft Streifen Schrott, oder haben der WS2812 und 
der WS2812B unterschiedlichen Datenformate?
Die Zeiten für T0H, T1H, T0L unterscheiden sich laut den Datenblättern 
für den WS2812 und den WS2812B minimal um jeweils 0,05us während die 
Abweichung bei T1L 0,15us beträgt.
ich habe diese WS2812_send_array Routine, eine Änderung um 0,05us bzw. 
0,15us scheint recht schwierig zu sein, ein NOP sind bei 8MHz ja schon 
0,125us!
1
//*********************************************************************
2
#define ws2812_port 0x02 // Number of the data port register
3
#define ws2812_pin 2 // Number of the data out pin
4
void ws2812_sendarray_8Mhz(void)
5
{
6
  unsigned char *data = &color[0];
7
  unsigned char curbyte;
8
  unsigned char ctr;
9
  unsigned char datlen = 12;
10
  while (datlen--) {
11
    curbyte = *data++;
12
    asm volatile(
13
    " ldi %0,8    \n\t"
14
    "loop%=:    \n\t"
15
    " ROL %1    \n\t"
16
    " dec %0    \n\t"
17
    " sbi %2, %3  \n\t"
18
    " brcs .+2    \n\t"
19
    " cbi %2, %3  \n\t"
20
    " brcc .+2    \n\t"
21
    " cbi %2, %3  \n\t"
22
    " brne loop%=  \n\t"
23
    : "=&d" (ctr)
24
    : "r" (curbyte), "I" (ws2812_port), "I" (ws2812_pin)
25
    );
26
    // loop overhead including byte load is 6+1 cycles
27
  }
28
}
29
//*********************************************************************
SOS
Angehängte Dateien:
Gast #3833335
Lesenswert?

Conny G. schrieb:
> Hast auch Spannung und Masse richtig angeschlossen?

Ich denke mal ja, sonst könnte ich auf dem Oszilloskop ja nicht so schön 
sehen, wie die Datenpackete weitergereicht werden.

> Liefert das Netzteil genug Strom?
Der neue LED-Streifen braucht kaum Strom, es leuchtet ja überhaupt nix.
Nur der alte LED-Streifen blinkt munter vor sich hin.
#3833462
Lesenswert?

Du könntest mal versuchen die erste LED abzuschneiden. Ich habe schon 
öfter gelesen (mir noch nicht passiert), dass die gerne kaputt geht.
U.a. soll man nie das Datensignal anlegen, bevor die Spannung am 
Streifen ist, wenn ich mich richtig erinnere.

Was allerdings dagegen spricht, dass Du das weiterreichen des Signals am 
Oszi siehst. Das würde nicht geschehen, wenn die erste LED kaputt wäre.
Gast #3834684
Lesenswert?

Marc Vesely schrieb:
> Dann hänge mal den alten LED-Streifen einfach hinter den neuen und
> prüfe ob es immer noch leuchtet.

Genau das habe ich jetzt probiert und tatsächlich, nachdem das Signal 
durch einen WS2812B durch ist, enthält es nur noch "0" siehe Bild!
Der ATtiny10 sendet immer "0x0F"
Das gelbe Signal ist vor dem WS2812B, das blaue dahinter.
Habe das mit WS2812B aus verschiedenen Lieferungen probiert, immer das 
selbe!
Was tun?
Angehängte Dateien:
Gast #3834719
Lesenswert?

Konnte den Bug jetzt fixen  :-)

Ein kleines nop verändert das Timing so,
das WS2812 und WS2812B das Signal verstehen.
1
//*********************************************************************
2
#define ws2812_port 0x02 // Number of the data port register
3
#define ws2812_pin 2 // Number of the data out pin
4
void ws2812_sendarray_8Mhz(void)
5
{
6
  unsigned char *data = &color[0];
7
  unsigned char curbyte;
8
  unsigned char ctr;
9
  unsigned char datlen = 12;
10
  while (datlen--) {
11
    curbyte = *data++;
12
    asm volatile(
13
    " ldi %0,8    \n\t"
14
    "loop%=:    \n\t"
15
    " ROL %1    \n\t"
16
    " dec %0    \n\t"
17
    " sbi %2, %3  \n\t"
18
    " brcs .+2    \n\t" 
19
    " cbi %2, %3  \n\t"
20
    " brcc .+2    \n\t"
21
    " nop         \n\t" // dieses kleine nop macht Daten auch für WS2812B verständlich!!!
22
    " cbi %2, %3  \n\t"
23
    " brne loop%=  \n\t"
24
    : "=&d" (ctr)
25
    : "r" (curbyte), "I" (ws2812_port), "I" (ws2812_pin)
26
    );
27
  }
28
}
29
//*********************************************************************
YO
Angehängte Dateien:
Gast #3834875
Lesenswert?

>Ist sowas nicht besser mit nem Timer erledigt? Toggle on compare +
>OCR-Interrupt, der nen nächsten OCR-Wert schreibt?

Damit bekommt man kein ausreichend genaues Timing hin.
Alleine der Aufruf des Interrupts hängt doch schon davon ab
welcher OP Code mit wievielen Takten noch zuende geführt wird.

Am besten ist eine Hardware die das ganze komplett selbst
erledigen kann. Z.B. per DMA. Hat der AVR ja nun aber nicht.

Ich bevorzuge LED Stripes mit LPD8806. Die sind zwar teuer,
aber um Timings braucht man sich da nicht die Bohne Gedanken machen.
Einfach per SPI die Daten reinprügeln. Da ist es auch völlig
Wurst ob da noch ein Timer oder UART massiv mit Interrupts reinhaut.
Gast #3835497
Lesenswert?

Simon K. schrieb:
> Warum auch immer man dort Assembler braucht... Angst, dass C zu langsam
> ist? ;-)
1
//*********************************************************************
2
#define ws2812_pin 2 // Number of the data out pin
3
void ws2812_sendarray_8Mhz(uint8_t curbyte)
4
{
5
  for(uint8_t bit_counter = 8;bit_counter;bit_counter--)
6
  {
7
    PORTB |= (1 << ws2812_pin);
8
    if((curbyte & 0x80) == 0)
9
    {
10
      PORTB &= ~(1 << ws2812_pin);
11
    }
12
    else
13
    {
14
      asm volatile("NOP");
15
      asm volatile("NOP");
16
      PORTB &= ~(1 << ws2812_pin);
17
    }
18
    curbyte <<= 1;
19
  }
20
}
21
//*********************************************************************
dies funktioniert jetzt auch ohne Assembler Voodoo sehr schön.
Nur hat man im Hinterkopf die Angst, das der Compiler das anders 
compilieren könnte und schon ist das exakte Timing futsch.
#3835714
Lesenswert?

Da kann ein Compiler nicht besonders viel variieren würde ich sagen.

Wieso eigentlich nicht so?
1
//*********************************************************************
2
#define ws2812_pin 2 // Number of the data out pin
3
void ws2812_sendarray_8Mhz(uint8_t curbyte)
4
{
5
  for(uint8_t bit_counter = 8;bit_counter;bit_counter--)
6
  {
7
    PORTB |= (1 << ws2812_pin);
8
    if((curbyte & 0x80) != 0)
9
    {
10
      asm volatile("NOP");
11
      asm volatile("NOP");
12
    }
13
    PORTB &= ~(1 << ws2812_pin);
14
    curbyte <<= 1;
15
  }
16
}
17
//*********************************************************************

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren