ESP32-Wroom32D Ws2812b flackern

Hallo zusammen,

ich hoffe ich bin in dem Arduino Forum richtig, wenn ich eine frage bezüglich des ESP32-Wroom-32D habe :slightly_smiling_face:

Und zwar habe ich das Problem, dass mein LED Streifen mit den Ws2812b zu flackern beginnt, sobald der ESP32 die Internetverbindung verliert. Das flackern ist nicht konstant, sondern tritt in unregelmäßigen Abständen auf und ist sehr kurz sichtbar. Dann läuft die Kette, bis es wieder kurz an zufälligen Positionen mit zufälligen Farben aufleuchtet.
Solange der ESP32 mit dem Internet verbunden ist, oder von vornherein gar nicht verbunden war, läuft alles problemlos. Ich habe mich an alle Design-Rules gehalten:

  1. 1000 uF Kondensator direkt an doe Pole des Streifens
  2. Kabel für Datentransfer möglichst kurz halten
  3. SN74AHCT125D um das Signal von 3.3 auf 5V anzuheben
  4. 330 Ohm Widerstand in das Datenkabel zwischengeschaltet (hat dann komischerweise gar nicht mehr funktioniert)
  5. Alle Massen miteinander verbunden
  6. Ein ausreichend starkes Netzteil (2A, da nur 10 LEDs benutzt werden)

Als sketch habe ich den Strandtest benutzt, der in der Neopixel library enthalten ist und um die Wifi.h library erweitert:

// A basic everyday NeoPixel strip test program.

// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)

#include <WiFi.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    23

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 90

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
  // NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)


// setup() function -- runs once at startup --------------------------------

void setup() {
  Serial.beginln(1152)
 const char* ssid = "BlaBla";
const char* password =  "Passwort";
WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    
  }
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red
  colorWipe(strip.Color(  0, 255,   0), 50); // Green
  colorWipe(strip.Color(  0,   0, 255), 50); // Blue

  // Do a theater marquee effect in various colors...
  theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness

  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}


// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {  // Repeat 10 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    // strip.rainbow() can take a single argument (first pixel hue) or
    // optionally a few extras: number of rainbow repetitions (default 1),
    // saturation and value (brightness) (both 0-255, similar to the
    // ColorHSV() function, default 255), and a true/false flag for whether
    // to apply gamma correction to provide 'truer' colors (default true).
    strip.rainbow(firstPixelHue);
    // Above line is equivalent to:
    // strip.rainbow(firstPixelHue, 1, 255, 255, true);
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}

Also wie gesagt. Alles läuft wie geschmiert, solange er nicht mit dem internet verbunden war und diese Verbindung verliert. nach einem reconnect läuft die Lichterkette wieder problemlos.

Ich hoffe , dass mir einer helfen kann, denn langsam verzweifelt ich daran :grinning:!

Versuch mal das loop() zu erweitern:

void loop()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    WiFi.disconnect();
    WiFi.reconnect();
    // Alternativ:
    // WiFi.begin(ssid, password);
  }
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red

Was mir so auffällt:

  1. Ich sehe keine Internetverbindung, meinst Du Wifi?
  2. Mit delay() habe ich mir im Zusammenhang mit Wifi schon mal Probleme eingefangen.
  3. Warum #define LED_COUNT 90 wenn es nur 10 sind?
  4. Je nach Netzteil für die LEDs hatte ich schon mal Flackern bei verbundenem USB. Daher bin ich auf OTA und die Versorgung des ESP32 mit 5 V vom LED-Netzteil umgestiegen.
  5. Für meine Projekte nutze ich FastLED, das die Daten per DMA rausschicken soll, wäre ein Versuch wert.
  6. Anstelle WS2812b verwende ich WS2815 mit 12 V und weniger Strom, die sind bis 8 V runter für meine Augen farbstabil und subjektiv unempfindlicher gegen Störungen.

Eventuell ist ja ein Ausweg für Dich dabei, es hilft nur probieren :roll_eyes:

Okay ich habe deinen Vorschlag ausprobiert und es funktioniert teilweise. Wenn ich es genauso übernehme, wie du beschrieben hast, dann ist das flackern deutlich weniger geworden, aber leider nicht komplett verschwunden.
Daraufhin habe ich das if-statement in jede for-Schleife gepackt. Das flackern ist zwar komplett weg, doch der ESP32 verbindet sich nicht erneut mit dem Internet...

  1. Ja genau ich meine Wifi. Entschuldige bitte meine unpräzise Formulierung
  2. ich habe eine verschiedene Anzahl an LEDs ausprobiert. Das ist wohl noch hängen geblieben aus einem Versuch 90 LEDs anzusteuern.
  3. FastLED hatte ich davor ausprobiert und das gleiche Problem festgestellt. Einzelne LEDs leuchten scheinbar willkürlich auf

Na dann bin ich doch auf der richtigen Spur.

Bau mal ein:

void checkWlan()
{
  const unsigned long connectDelay = 1000;
  static unsigned long lastConnect = 0;
  if (millis() - lastConnect > connectDelay)
    if (WiFi.status() != WL_CONNECTED)
    {
      WiFi.disconnect();
    }
  if (WiFi.status() == WL_DISCONNECTED)
  {
    if (millis() - lastConnect > connectDelay * 10UL)
    {
      WiFi.reconnect();
    }
    lastConnect = millis();
  }
}
// loop() function -- runs repeatedly as long as board is on ---------------
void loop()
{
  checkWlan();
  // Fill along the length of the strip in various colors...

Das habe ich nun probiert aber es scheint auch nicht zu funktionieren. Die FunktionWifi.reconnect() tut nicht was es soll. Die ist im Gegensatz zu Funktion WiFi.disconnect() auch nicht in gelb dargestellt.

Ich frage mich nur woran genau das Flackern liegt, denn wenn eine Wifi Verbindung besteht ist alles Bestens. Liegt das an der WiFi.h library oder woran?

Dafür hatte ich die Alternative bereits vorgeschlagen:

Also ich habe es nun mit der Alternativen Methode probiert. Ich musste wie gesagt jedoch die Funktion checkWlan() in jede for Schleife packen, da sonst das flackern wieder auftritt. Denn Wenn die Wifi Verbindung getrennt wird in während der for Schleife, wird ja checkWlan() nicht ausgeführt oder? Jedenfalls ist das flackern so weg. Ich poste mal den Code unten. Deine Funktion checkWlan() habe ich etwas ergänzt und mir die Aktionen im Monitor anzeigen zu lassen. Wenn die Verbindung getrennt wird, wird als "Disconnected" angezeig, was ja auch gut ist, jedoch springt er nicht in den Teil, wo er sich erneut verbinden soll.

Code:

// A basic everyday NeoPixel strip test program.

// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)
#include <WiFi.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    23

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 60

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)


// setup() function -- runs once at startup --------------------------------

void setup() {
  Serial.begin(115200);
  const char* ssid = "";
const char* password =  "";
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    
  }
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  checkWlan();
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red
  colorWipe(strip.Color(  0, 255,   0), 50); // Green
  colorWipe(strip.Color(  0,   0, 255), 50); // Blue

  // Do a theater marquee effect in various colors...
  theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness

  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}


// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) {checkWlan(); // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) { checkWlan(); // Repeat 10 times...
    for(int b=0; b<3; b++) {checkWlan(); //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {checkWlan();
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {checkWlan();
    // strip.rainbow() can take a single argument (first pixel hue) or
    // optionally a few extras: number of rainbow repetitions (default 1),
    // saturation and value (brightness) (both 0-255, similar to the
    // ColorHSV() function, default 255), and a true/false flag for whether
    // to apply gamma correction to provide 'truer' colors (default true).
    strip.rainbow(firstPixelHue);
    // Above line is equivalent to:
    // strip.rainbow(firstPixelHue, 1, 255, 255, true);
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {checkWlan();  // Repeat 30 times...
    for(int b=0; b<3; b++) { checkWlan();//  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {checkWlan();
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}




void checkWlan(){
const char* ssid = "";
const char* password =  "";
  const unsigned long connectDelay = 1000;
  static unsigned long lastConnect = 0;
  if (millis() - lastConnect > connectDelay)
    if (WiFi.status() != WL_CONNECTED)
    {
      Serial.println("Disconnected");
      WiFi.disconnect();
    }
  if (WiFi.status() == WL_DISCONNECTED)
  {
    if (millis() - lastConnect > connectDelay * 10UL)
    {
      Serial.println("Reconnect");
      WiFi.begin(ssid,password);
    }
    lastConnect = millis();
  }
}

Ja, das ist notwendig, da das mit den Schleifen nicht blockadefrei ist.
Du solltest Dir in checkWlan() ausgeben lassen, was das Problem ist.

void checkWlan()
{
  const char *ssid = "";
  const char *password =  "";
  const unsigned long connectDelay = 1000;
  static unsigned long lastConnect = 0;
  if (millis() - lastConnect > connectDelay)
    byte wlStatus = WiFi.status();
  if (wlStatus != WL_CONNECTED)
  {
    Serial.print(F("Disconnected: "));
    Serial.println(wlStatus);
    WiFi.disconnect();
  }
  if (WiFi.status() == WL_DISCONNECTED)
  {
    if (millis() - lastConnect > connectDelay * 10UL)
    {
      Serial.println(F("Reconnect"));
      WiFi.begin(ssid, password);
    }
    lastConnect = millis();
  }
}

Die entsprechende Nummernausgabe kannst Du mit dem enum aus wl_status_t vergleichen und ggfls. abstellen.

Gut also es hat mir status 5 ausgegeben und nach dem reconnect status 1 weshalb ich das in das if statement mit reingenommen habe. Danach konnte ich mich zwar wieder verbinden, aber.... die LEDs haben wieder geflackert. Das automatische wieder-verbinden funktioniert auch nur ein Mal.

void checkWlan(){
 
const char* ssid = "";
const char* password =  "";
  const unsigned long connectDelay = 1000;
  static unsigned long lastConnect = 0;
  byte wlStatus = WiFi.status();
  if (millis() - lastConnect > connectDelay)
  
    if (WiFi.status() != WL_CONNECTED)
    {
      Serial.println("Disconnected");
      Serial.println(wlStatus);
      WiFi.disconnect();
    }
  if (WiFi.status() == WL_DISCONNECTED  || WiFi.status() ==WL_CONNECTION_LOST || WiFi.status() ==WL_CONNECT_FAILED || WiFi.status() ==WL_NO_SSID_AVAIL )
  {
    if (millis() - lastConnect > connectDelay * 10UL)
    {
      Serial.println("Reconnect");
      WiFi.begin(ssid,password);
    }
    lastConnect = millis();
  }
}

ist connection _lost und 1 no_SSID.
Da ist wohl deine Verbindung so schlecht, das die erst abreisst und dann das Netzwerk nicht mehr gefunden wird.

Es könnte natürlich auch sein, das der Accesspoint/Router einfach das Wlan resettet.

Das heisst es abzustellen.

Alles andere kommt dann automatisch.

Was das 1malige Wiederverbinden angeht, könntest versuchen das 10UL auf 20UL oder mehr zu stellen....
Und dein zusätzliches if-Statement ist unsinnig.
Wenn in der Bedingung davor nicht festgestellt wird, das ein connect besteht, wird gefragt warum und auf disconnect gelegt.

Die Folgebedingung fversucht dann einen Neustart. Wenn der nicht gelingt, wird wieder auf disconnect gestellt usw.

Also ich benutze den Hotspot meines Handys, um die Funktionalitäten zu überprüfen. Das liegt direkt neben dem ESP32 (dementsprechend müsste es eine starke Verbindung geben). Den Verbindungsverlust simuliere ich, indem ich den Hotspot einfach ein- und ausschalte. Das erneute Verbinden klappt ja auch alles super.
Ich kenn mich da wirklich wenig aus, aber ich glaube das flackern kommt daher, dass der ESP32 als versucht ein reconnect herzustellen. Denn wie gesagt, solange der ESP32 verbunden ist oder nie verbunden war, klappt alles super. Ich kann mir vorstellen, dass irgendwas in der WiFi.h lib das flackern hervorruft...aber das sind nur Vermutungen.

Steht das nicht an der falschen Stelle?

Ja. müsste mit einer Zeile höher getauscht werden.
Sehe ich aber zwischenzeitlich entspannt.

Ich kann mir nicht erklären, warum das Teil blinkt.
Und erst jetzt kommt raus, das da absichtlich das Wlan gekappt wird.

Ich bin kein ESPler; Das war rein aus der Logik gemacht. Vielleicht liegt es am Core, vielleicht am Pin.
Im Eingangspost heisst es er braucht nur 10 LED da reicht das Netzteil. Initialisiert aber 90.
Das sind soviele Unwägbarkeiten - ich denke, wenn das blockadefrei programmiert ist, ist das vielleicht ganz anders.

Macht das denn einen Unterschied, wenn ich es kappe und dann wieder einschalte ?

Ja wie gesagt, das kommt daher, dass ich es mit 10/20/30...90 LEDs probiert habe. Und immer hat es geflackert.

Wie wird das denn blockadefrei programmiert? :grinning:

Schleifen, die länger laufen als einen Umlauf auflösen und alle delays() raus.
Am Beispiel colorWipe: Wenn Du 90 LED ansteuerst und jede LED eine Pausenzeit von 50ms benötigt, bist Du mit dem restlichen Code 4,55 Sekunden blind. Dazu kommt noch die Zeit, die die lib braucht um die Pixel anzusteuern.
So sehe das bei mir aus, wenn ich die Blockade auflösen müsste - aber dazu muss auch der gesamte andere Code passen, also nicht allein das ausstauschen reicht...

bool colorWipe(const uint32_t color, const uint32_t pause)
{
  bool isFertig = false;
  static uint32_t lastTime = 0;
  static uint8_t isPixel = 0;
  if (millis() - lastTime >= pause)
  {
    strip.setPixelColor(isPixel, color);
    strip.show();
    isPixel++;
    lastTime = millis();
  }
  if (isPixel >= strip.numPixels())
  {
    bool isFertig = true;
    isPixel = 0;
  }
  return isFertig;
}

Also ich habe zwischenzeitlich ebenfalls ein sehr einfaches Minimalbeispiel gefunden:

#include <Adafruit_NeoPixel.h>
#include <WiFi.h>
#define PIXELSPIN   6
#define NUMPIXELS   60
#define CALIBRATIONTIME 20000

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELSPIN, NEO_GRB + NEO_KHZ800);

unsigned long pixelsInterval=50;  // the time we need to wait

unsigned long rainbowPreviousMillis=0;
unsigned long rainbowCyclesPreviousMillis=0;


int rainbowCycles = 0;
int rainbowCycleCycles = 0;

uint16_t currentPixel = 0;// what pixel are we operating on

void setup() {
  const char* ssid = "";
const char* password =  "";
WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    
  }
  currentPixel = 0;
  
  pixels.begin(); // This initializes the NeoPixel library.
  pixels.show(); // This sends the updated pixel color to the hardware.
      
}

void loop () {
  
       
        if ((unsigned long)(millis() - rainbowPreviousMillis) >= pixelsInterval) {
          rainbowPreviousMillis = millis();
          rainbow();
        }
      
        

}


void rainbow() {
  for(uint16_t i=0; i<pixels.numPixels(); i++) {
    pixels.setPixelColor(i, Wheel((i+rainbowCycles) & 255));
  }
  pixels.show();
  rainbowCycles++;
  if(rainbowCycles >= 256) rainbowCycles = 0;
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

hier ist kein delay() eingebaut! Trotzdem flackern die LEDs, wenn das Internet weg ist. Das kann doch nicht sein!

Ich auch noch nicht, aber möglicherweise hilft eine Analyse.

Hardware: ESP32 mit WS2815 an Fritz!Box
Animation: Regenbogen ohne delay(), weil man da Störungen gut sehen kann.
Programm: Die Zugangsdaten habe ich in der Datei zugangsdaten.h ausgelagert, damit ich sie nicht immer anonymisieren muß. "STA" steht für Station, also Anmeldung am Router. Es geht auch "AP" als Access Point, so unterscheide ich die Zugänge.

Wifi wird nur im setup() angemeldet, checkWlan() zeigt WiFi.status() an, Auflösung entsprechend Get Wi-Fi Connection Status.

#include <WiFi.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN    23
#define LED_COUNT 60
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
#define LED_BUILTIN 13
#include "zugangsdaten.h"
const char * ssid = STA_SSID;
const char * password =  STA_PASSWORD;

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN, 1);
    delay(250);
    digitalWrite(LED_BUILTIN, 0);
    delay(250);
  }

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  checkWlan();
  rainbow(10);             // Flowing rainbow cycle along the whole strip
}

void rainbow(const unsigned long wait) {
  static unsigned long vorhin = 0;
  static unsigned long firstPixelHue = 0;
  if (millis() - vorhin >= wait) {
    vorhin = millis();
    strip.rainbow(firstPixelHue);
    strip.show(); // Update strip with new contents
    firstPixelHue += 256;
  }
}

void checkWlan() {
  const unsigned long connectDelay = 1000;
  static unsigned long lastConnect = 0;
  static byte wlStatus_alt = 255;

  if (millis() - lastConnect > connectDelay)
  {
    lastConnect = millis();
    byte wlStatus = WiFi.status();
    if (wlStatus_alt != wlStatus) {
      wlStatus_alt = wlStatus;
      Serial.print("WiFi.status ");
      Serial.print(wlStatus);
      Serial.print('\t');
      switch (wlStatus) {
        case 0: Serial.print("WL_IDLE_STATUS");      // temporary status assigned when WiFi.begin() is called
          break;
        case 1: Serial.print("WL_NO_SSID_AVAIL");    // when no SSID are available
          break;
        case 2: Serial.print("WL_SCAN_COMPLETED");   // scan networks is completed
          break;
        case 3: Serial.print("WL_CONNECTED");        // when connected to a WiFi network
          break;
        case 4: Serial.print("WL_CONNECT_FAILED");   // when the connection fails for all the attempts
          break;
        case 5: Serial.print("WL_CONNECTION_LOST");  // when the connection is lost
          break;
        case 6: Serial.print("WL_DISCONNECTED");     // when disconnected from a network
          break;
        default: Serial.print("WL unbekannt");
      }
      Serial.println();
    }
  }
}

Ausgabe:

Zeit Status Bedeutung Kommentar
15:46:12.482 -> WiFi.status 3 WL_CONNECTED Reset
15:46:57.549 -> WiFi.status 5 WL_CONNECTION_LOST WLAN am Router aus
15:46:59.550 -> WiFi.status 1 WL_NO_SSID_AVAIL
15:48:57.669 -> WiFi.status 0 WL_IDLE_STATUS
15:48:58.672 -> WiFi.status 1 WL_NO_SSID_AVAIL
15:49:04.655 -> WiFi.status 3 WL_CONNECTED kurz vorher WLAN am Router ein
16:01:23.557 -> WiFi.status 5 WL_CONNECTION_LOST nichts gemacht!
16:01:26.565 -> WiFi.status 3 WL_CONNECTED nichts gemacht!

Wertung:

  • Ohne eine programmierte Neuverbindung wird die Wifi-Verbindung dennoch wiederhergestellt, das verwundert mich.
  • Ohne Verbindung flackern die LEDs, eventuell ja wegen automatischer Verbindungsversuche? Bei 60 programmierten Pixeln werden beim Flackern auch Pixel dahinter farbig, die Übertragung geht also schief.

Bislang fehlt eine Datenübertragung per Wifi, denn eventuell gibt es die Störungen auch dabei.

Lösung: keine Idee :roll_eyes:

@additong: Was macht mein Programm auf Deinem ESP32?

Wäre auch FastLED eine Option für Dich? Wenn ja, würde ich damit nochmal einen Versuch starten.

Ich hatte das schon in Vorbereitung...

#include <WiFi.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

const byte LED_PIN = 22;
const byte LED_COUNT = 90;

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  Serial.begin(115200);
  const char *ssid = "BlaBla";
  const char *password =  "Passwort";
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
  }
  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


void loop()
{
  colorWipe(strip.Color(255,   0,   0), 50);
}
bool colorWipe(const uint32_t color, const uint32_t pause)
{
  bool isFertig = false;
  static uint32_t lastTime = 0;
  static uint8_t isPixel = 0;
  if (millis() - lastTime >= pause)
  {
    strip.setPixelColor(isPixel, color);
    strip.show();
    isPixel++;
    lastTime = millis();
  }
  if (isPixel >= strip.numPixels())
  {
    bool isFertig = true;
    isPixel = 0;
    strip.clear();
    strip.show();
  }
  return isFertig;
}

Kannst mal einspielen. ABER! Ich habe den LED_PIN auf 22 gelegt.
Den sollste auch nutzen.