Go Down

Topic: ESP32 WS2812B fehlerhafte Ausgabe (Read 592 times) previous topic - next topic

octarock

Hallo Community,

ich habe ein ESP32 und versuche damit ein WS2812B LED-Strip anzusteuern. Weil mein ESP32 fest verbaut ist habe ich zuvor das Sketch auf den Arduino Nano getestet. Dort läuft das Sketch super und die LED-Strips werden richtig angesteurt, aber wenn ich nun das Sketch auf den ESP32 lade werden die LED-Strips zwar angesteuert aber es passiert null was eigentlich passieren soll. Alles leuchtet Bund und es ist fast nix mehr von der eigentlichen Animation zu erkennen. Anbei das Sketch:
Code: [Select]

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(65 , 14 , NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(65 , 12 , NEO_GRB + NEO_KHZ800);

//Helligkeit des jeweiligen Lichpuntes in der Schlange in Prozent
float Helligkeit[10]={};
//Absolute Helligkeit des ersten Lichtpunktes der Schlange
int Summe_Farbe1 = 100;
//Absolute Helligkeit des letzten Lichtpunktes der Schlange
int Summe_Farbe2 = 100;
//pysische Position der LED auf dem LED-Stip
int LEDid;
//Position der LED auf virtuellen Bereich (0-53)
int pos;
//gibt die Richtung an in die die Schlange wandert
String Richtung;

int leange;

// Speichert die Farbe für die jeweilige Stelle in der "Schlange"
// probeweise befüllt da ColorTable auskommentiert (eigentlich von dieser Funktion befüllt)
int rot[10]   = {0,    51, 77,  76, 51};     
int gruen[10] = {255, 153, 77,  26,  0}; 
int blau[10]  = {255, 204,153, 102, 51}; 
                               

void setup() {
  //Resetet beide Stips
  strip1.begin();
  strip1.show();
  strip2.begin();
  strip2.show();

  Serial.begin(115200);

  // Schlange beginnt links und soll nach rechts wandern
  pos = 0;
  Richtung = "right";
  // Schlange soll aus 5 Lichpunkten bestehen und mit Farbe1 beginnen und mit Farbe2 enden
  leange=6;
  int Farbe1[] = {0,255,255};
  int Farbe2[] = {255,0,255};

}

//////////////////////////////////////////////////////////////////////////////////

void loop() {
  MoveDot();
  delay(20);
}

//////////////////////////////////////////////////////////////////////////////////





//Schaltet LED an der angegeben Position in der Farbe an, die in "place" angegeben wird
//übersetzt die Positionen 0-53 in die LEDid des jeweiligen LED-Bands
//zudem sind zu klein/große Eingaben für die Position nicht möglich (werden nicht beachtet)
//Position von 0-53
//Laufbahn links->rechts: strip1 LEDs 18-44; strip2 LEDs 44-18
void ShowDot(int posLED, int place) {
  //entscheidet ob linkes oder rechtes LED-Band bzw. ob im gültigen Bereich
  if (posLED <= 26 && posLED >= 0){
    LEDid = posLED + 18;
    strip1.setPixelColor(LEDid, strip1.Color(rot[place],gruen[place],blau[place]));
    strip1.show();
    Serial.print("(1)LEDid: ");
    Serial.println(LEDid);
    Serial.print("(1)place: ");
    Serial.println(place);
  }
  else if (posLED >= 27 && posLED <= 53){
    LEDid = 44 - (posLED-27);
    strip2.setPixelColor(LEDid, strip2.Color(rot[place],gruen[place],blau[place]));
    strip2.show();
    Serial.print("(2)LEDid: ");
    Serial.println(LEDid);
    Serial.print("(2)place: ");
    Serial.println(place);
  }
  else{Serial.println("(1)Show: Input außerhalb des Bereiches");}
}

//schaltet LED an angegebener Position aus
//Falsche Positionen (<0 || >53) werden nicht beachtet
//nötig, da wenn Schlange eins weiter gewandert Schlangenende von vorheriger Position sonst weiterleuchten würde
void ClearDot(int posLED){
  //entscheidet ob linkes oder rechtes LED-Band bzw. ob im gültigen Bereich
  if (posLED <= 26 && posLED >= 0){
    LEDid = posLED + 18;
    strip1.setPixelColor(LEDid, strip1.Color(0,0,0));
    strip1.show();
    Serial.print(LEDid);
    Serial.println(" cleared(1)");
  }
  else if (posLED >= 27 && posLED <= 53){
    LEDid = 44 - (posLED-27);
    strip2.setPixelColor(LEDid, strip2.Color(0,0,0));
    strip2.show();
    Serial.print(LEDid);
    Serial.println(" cleared(2)");
  }
  else{Serial.println("(2)Clear: Input außerhalb des Bereiches");}
}



//Erzeugt einen Punkt mit Schwanz abhängig von der Ausrichtung
//Zeigt diese Schlange an und schaltet die LED nach Schwanzende aus
void Dot_Strait() {
  if (Richtung == "right"){ // bewegt sich nach rechts
    for (int i=0; i<leange; i++){
      ShowDot(pos-i, i);
    }
    ClearDot(pos-leange);
  }
  else{ //bewegt sich nach links
    for (int i=0; i<leange; i++){
      ShowDot(pos+i, i);
    }
    ClearDot(pos+leange);
  }
}



//Pos und Richtung müssen in Form einer Variable, welche in Setup deklariert wurde, eingegeben werden
//läast die Schlange abhängig von der Ausrichtung wandern
void MoveDot(){
  Serial.println(Richtung);
  if (Richtung == "right"){
    //Solange Dot mit Schwanz noch im Sichtbaren immer eins nach rechts verschieben
    if (pos < 53+leange){
      Dot_Strait();
      pos += 1;
      //Schlange läuft eigentlich weiter  im ungültigen Bereich -> verschwindet allmählich
      //Rand LED immer in Farbe Place[0], sodass Schlange optisch in Punkt Zusammenläuft
      if (pos >= 54){
        ShowDot(53,0);
      }
    }
    //wenn in einen Punkt zusammengelaufen ändert die Richtung und Position von Startpunkt
    //(ist vorher ja in den ungültigen Bereich weiter gelaufen)
    else{Richtung = "left"; pos = pos-leange;}
  }

  else{ //bewegt sich nach links
  //Solange Dot mit Schwanz noch im Sichtbaren immer eins nach links verschieben
    if (pos > 0-leange){
      Dot_Strait();
      pos -= 1;
      //Schlange läuft eigentlich weiter  im ungültigen Bereich -> verschwindet allmählich
      //Rand LED immer in Farbe Place[0], sodass Schlange optisch in Punkt Zusammenläuft
      if (pos <= -1){
        ShowDot(0,0);
      }
    }
    //wenn in einen Punkt zusammengelaufen ändert die Richtung und Position von Startpunkt
    //(ist vorher ja in den ungültigen Bereich weiter gelaufen)
    else{Richtung = "right"; pos = pos+leange;}
  }   
}

Etwas wirr der Code, deshalb erkläre ich mal was er machen soll. Ich habe in meinen Tisch zwei LED-Bänder verbaut und eine Schlange (mit Farbverlauf und Helligkeitsabfall hin zum Schwanz der Schlange) soll von links nach rechts wandern. Eigentlich berechnen mehrere funktionen den Farbverlauf und so aber ich hab die alle der länge wegen gelöscht und Beispielwerte in die Arrays rot,gruen und blau gepackt. Der Code funktioniert auch auf den Nano und selbst mal probeweise auf den ESP8266 (ob der gekürzte geht kp).
Ich habe keinen Plan wieso das nun auf den ESP32 nicht geht (auch bei mein anderes ES32 ensteht das selbe Problem). Ich hoffe ihr könnt mir weiter helfen :D

Gruß Octarock

HotSystems

Bisher habe ich keine Erfahrung mit den WS2812B am ESP32, vermute aber, es liegt an der falschen Ansteuerung.
Du nimmst 3,3 V um 5V LEDs zu steuern.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Tommy56

Miss mal die Spannung an den LED. Wenn die > 4,7 V ist, erreicht der ESP mit seinen 3,3V nicht die 0,7 * Vcc, die normalerweise als High erkannt wird.

Abhilfe: Levelshifter oder die 1. WS2812 über eine Diode betreiben, die deren Betriebsspannung um ca. 0,7V verringert. Diese regeneriert dann das Signal für den Rest des Stripe.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

octarock

An den LEDs liegt sogar eine Spannung von 5,3V an was mich wundert da ich die 5V-Schiene meines PCs anzapfe und das sollte ja eigentlicg genauer sein, naja kann das der Grund für die Fehler sein?

HotSystems

An den LEDs liegt sogar eine Spannung von 5,3V an was mich wundert da ich die 5V-Schiene meines PCs anzapfe und das sollte ja eigentlicg genauer sein, naja kann das der Grund für die Fehler sein?
Der Grund wurde dir doch genannt.
Sogar wie du es umgehen kannst.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

agmue

#5
Sep 20, 2020, 06:17 pm Last Edit: Sep 20, 2020, 06:29 pm by agmue
Alles leuchtet Bund und es ist fast nix mehr von der eigentlichen Animation zu erkennen.
Ich sehe sowas wie eine Kometenschweif hin- und herlaufen. Ist das die gewünschte Animation?

WS2812B sind kritisch in der Ansteuerung und trotz Levelshifter (74LS245) sehe ich Störungen.

Dies habe ich gerade probiert und funktioniert bei mir: ESP32: timing error every 1ms corrupts LED pixel data

Bessere Ergebnisse liefert die Bibliothek FastLED, da bekomme ich nur Störungen durch WiFi, die ich dann durch Nutzung von OTA, also Spannung vom Netzteil, verhindere.

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

octarock

Wups habe mich verlesen ("<" statt ">") ok ja dann danke für die Lösungsbeschreibung @Tommy56 ich kann nur keine Diode anlöten, weil die Strips in einen Infinity Mirror verbaut sind und das sähe dann schon blöd aus. Jetzt habe ich nur keine Idee was ein Levelshifter ist und wie man den verbaut?
@agume jap so soll das aussehen :D, aber wenn bei dir Störungen auftreten was kannst du mir empfehlen (Hardwareseitig) bzw. was ist OTA, weil das müsste ich dann machen, denn eigentlich will ich den ESP dann noch mal über das WLAN ansteuern können.

Tommy56

Ich bin zwar der Meinung, dass man die Diode auch geschickt anbauen kann, dass sie optisch nicht stört, schließlich musst Du auch die Zuleitungen verbauen.
Du kannst aber auch eine zusätzliche WS2812 vorschalten. Die kannst Du im Hintergrund verbauen und dann immer dunkel steuerst.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

octarock

oh das mit der LED zuvor schalten ist eine super Idee, muss ich bei der Diode auf irgendetwas achten?

Tommy56

Sie muss den Maximalstrom der LED (also 60 mA bei RGB) aushalten. Auch wenn sie im Normalfall dunkel ist, kann man Programmfehler nicht ausschließen und dann soll es ja nicht rauchen ;)

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

octarock

Sorry aber das verstehe ich jetzt nicht xD meinst du schon eine Diode, die nicht leutet oder was genau meinst du mit "sie im Normalfall dunkel ist" und wie muss ich die eigentlich verlöten, ich finde keine Anleitungen im Netz

Tommy56

Du hängst eine zusätzliche WS2812 davor.
IN über 220 Ohm an den ESP
OUT an den in der ersten WS2812 Deines Spiegels
Vcc über die Diode (Kathode an die zusätzliche Diode, Anode an Deine 5,3V) anschließen
GND mit den anderen GND verbinden

Wenn Du diese zusätzliche WS2812 nicht für andere Anzeigen nutzen willst, wird sie die Farbe 0, also nicht leuchtend bekommen. Die soll nur das Signal anpassen.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

octarock

wenn das so ist und ich es richtig verstanden habe, kann ich es dann auch so machen ?


agmue

... was kannst du mir empfehlen (Hardwareseitig)
Anderen LED-Typ wie APA102 verwenden, da sind Takt und Daten getrennt und daher darf ein Interrupt die Übertragung unterbrechen.

Sonst eben FastLED verwenden. Siehe auch ESP32: FastLED vs. NeoPixelBus vs. NeoPixel Library

... was ist OTA
Programmübertragung over the air anstelle USB. ESP32 als Access Point mit OTA einrichten. Das sind nur ein paar Zeilen.

Aus meiner Bastelkiste:

Code: [Select]
//#define DEBUGGING             // Auskommentieren wenn keine Serielle Ausgabe erforderlich ist

#ifdef DEBUGGING
#define DEBUG(...) Serial.println(__VA_ARGS__)
#define DEBUG_F(...) Serial.printf("Funktion: %s meldet in Zeile: %d -> ", __PRETTY_FUNCTION__, __LINE__); Serial.println(__VA_ARGS__)
#else
#define DEBUG(...)
#define DEBUG_F(...)
#endif
#include <ArduinoOTA.h>
#include <Adafruit_NeoPixel.h>

#define NUM_LEDS  144 // Number of LEDs in strip
#define DATAPIN    12
//#define CLOCKPIN   14
Adafruit_NeoPixel strip(NUM_LEDS, DATAPIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(115200);
  DEBUG_F("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n\n", __FILE__, __TIMESTAMP__, ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10);
  const char *ssid = "Esp32AP";             // << kann bis zu 32 Zeichen haben
  const char *password = "12345678";        // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen
  WiFi.mode(WIFI_AP);
  if (WiFi.softAP(ssid, password)) {
    DEBUG_F("Verbinde dich mit dem Netzwerk \"%s\"\nGib die IP %s im Browser ein\n\n", ssid, WiFi.softAPIP().toString().c_str());
    DEBUG_F("Hostname des AP = %s\n", WiFi.softAPgetHostname());
    DEBUG("Mac Adresse des AP = " + WiFi.softAPmacAddress());
    DEBUG("Broadcast IP des AP = " + WiFi.softAPBroadcastIP().toString());
  } else {
    DEBUG("Fehler beim Erstellen.");
  }
  ArduinoOTA.begin();

  strip.begin(); // Initialize pins for output
  strip.show();  // Turn all LEDs off ASAP
}

void loop() {
  ArduinoOTA.handle();
  theaterChase(0xff, 0, 0, 100);
}

void theaterChase(byte red, byte green, byte blue, int SpeedDelay) {
  static uint32_t vorhin = 0;
  static uint16_t led = 0;
  if (millis() - vorhin >= SpeedDelay) {
    vorhin = millis();
    if (led < 4) {
      setPixel(0, red, green, blue);  //turn every third pixel on
    } else {
      setPixel(0, 0, 0, 0);
    }

    showStrip();

    for (uint16_t j = NUM_LEDS; j > 0; j--) {
      strip.setPixelColor(j, strip.getPixelColor(j - 1));
    }
    led = (1 + led) % 10;
  }
}

void showStrip() {
  strip.show();
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
  strip.setPixelColor(Pixel, strip.Color(red, green, blue));
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

PC beim Access Point anmelden und in der IDE dann den Port wechseln.

Entscheidend ist vermutlich keine Spannungversorgung über USB. Ob es bei Dir geht, mußt Du probieren.

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

HotSystems

wenn das so ist und ich es richtig verstanden habe, kann ich es dann auch so machen ?
Tommy sprach davon, das nur die erste Led des Stripes über die Diode versorgt wird.
Also du hast einen Stripe mit 100 Leds, die erste davon wird über die Diode versorgt, die darauf folgenden 99 Leds werden direkt mit den 5 Volt verbunden.
Das gilt dann für beide Stripes, ok ?
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Go Up