Forum: Mikrocontroller und Digitale Elektronik ESP8266 und WS2812-Streifen


von Christoph S. (mcseven)


Angehängte Dateien:

Lesenswert?

Liebes Forum,

ich krieg das einfach nich gebacken. Hab einen ESP8266 (WROOM-02 und 
AIThinker ESP-12e), der mit Arduino (1.6.7) in "Native-C" Arduino SDK 
Version 2.0.0 einen WS2812-Streifen (60 LEDs) füttern soll.

Dazu hab ich ein popeliges Programm geschustert, das einfach seriell 180 
Bytes entgegennimmt und diese mit der folgenden Routine auf den GPIO 
schreibt:
1
static inline uint32_t _getCycleCount(void) {
2
  uint32_t cycles;
3
  __asm__ __volatile__("rsr %0,ccount":"=a" (cycles));
4
  return cycles;
5
}
6
static void ICACHE_RAM_ATTR ws2812_write(uint8_t *pixels, uint32_t len) {
7
  uint8_t *p, *end, pixel, mask;
8
  uint32_t t, t0h, t1h, ttot, c, start_time, pin_mask;
9
  pin_mask = 1 << LEDOUT_PIN;
10
  p =  pixels;
11
  end =  p + len;
12
  pixel = *p++;
13
  mask = 0x80;
14
  start_time = 0;
15
  t0h  = (1000 * system_get_cpu_freq()) / 3022;  // 0.35us (spec=0.35 +- 0.15)
16
  t1h  = (1000 * system_get_cpu_freq()) / 1477;  // 0.70us (spec=0.70 +- 0.15)
17
  ttot = (1000 * system_get_cpu_freq()) /  800;  // 1.25us (MUST be >= 1.25)
18
  while (true) {
19
    if (pixel & mask) {
20
        t = t1h;
21
    } else {
22
        t = t0h;
23
    }
24
    while (((c = _getCycleCount()) - start_time) < ttot); // Wait for the previous bit to finish
25
    GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pin_mask);      // Set pin high
26
    start_time = c;                                       // Save the start time
27
    while (((c = _getCycleCount()) - start_time) < t);    // Wait for high time to finish
28
    GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pin_mask);      // Set pin low
29
    if (!(mask >>= 1)) {                                  // Next bit/byte
30
      if (p >= end) {
31
        break;
32
      }
33
      pixel= *p++;
34
      mask = 0x80;
35
    }
36
  }
37
}

Die Funktion rufe ich wie folgt auf:
1
uint8_t ledBuf[180];
2
//...
3
noInterrupts();
4
ws2812_write( ledBuf, sizeof(ledBuf) );
5
interrupts();

Das funktioniert meistens. Leider kommen treten sporadisch LED-Glitches 
auf, bei denen Farbwerte teilweise in die Farbe der nächsten LED 
rutschen (also blau 1->grün2 usw.), insbesondere (aber nicht nur) bei 
den mittleren bis hinteren LEDs. Und gefühlt tritt es beim schnellen 
Senden häufiger auf.

Es liegt wohl nicht an Fehlern an der seriellen (PC->ESP) Übertragung, 
das ganze passiert auch, wenn ich einfach einen statischen Buffer mit 
100Hz sende, Hardcore-Test mit:
1
memset(ledBuf, 0xAA, sizeof(ledBuf));
2
noInterrupts(); ws2812_write( ledBuf, sizeof(ledBuf) ); interrupts();
3
memset(ledBuf, 0x55, sizeof(ledBuf));
4
noInterrupts(); ws2812_write( ledBuf, sizeof(ledBuf) ); interrupts();

Ich kann das mangels Logic-Analyser nicht elektrisch in ganzer Länge 
debuggen. Am Oszi schaut das Timing mit 330ns kurz,  680ns lang und 
insgesamt 1,2µs gut (siehe 1.jpg) aus, ich habe aber viel Ringing (siehe 
2.jpg).

Mit 50 Ohm in Reihe ist das Ringing weg, das Signal schaut "perfekt" 
aus, nur der Streifen tut nichts mehr.

Deswegen die Frage: Hat schon mal jemand diese Kombination erfolgreich 
und "langzeitstabil" am Laufen und könnte sagen, wie das elektrisch und 
wie in Software gelöst ist?

Danke, Christoph

von Speckbert (Gast)


Lesenswert?

Hallo,

mal eine ganz doofe Frage, mit welcher Spannung betreibst du die WS2812? 
Laut Datenblatt brauchen die 5V, damit ergibt sich für den High-Pegel 
eine Mindest-Spannung von 0.7 * 5V = 3,5V. Im Oszi sieht es aber so aus, 
als wenn dein Steuersignal nur einen Pegel von 3,3V hat.

Gruß
Specki

von Christoph S. (mcseven)


Lesenswert?

Richtig, 5V und ESP-Spannung ist 3,3V. Daher die Frage nach der 
elektrischen Verbindung, ob jemand das mal stabil hinbekommen hat, und 
wie dann der Anschluß aussieht. Präziser: Muß da ein BSS123 mit ???kOhm 
PullUp gegen +5V rein, damit das funktioniert?

von Axel L. (axel_5)


Lesenswert?

Ich betreibe den ESP8266 mit 3,6V und schliesse den WS... direkt an, das 
klappt sehr gut selbst mit 2m langem Kabel.

Gruss
Axel

von Christoph S. (mcseven)


Lesenswert?

Ahhh, ihr habt recht, das wars. Jetzt gehts. DANKE!

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.