ESP8266 + ESP8266WebServer - Freezing

Hi everyone,

I'm new to this forum and I have a (little) question. I developed an ESP8266 with an WebServer to control an LED-Strip.

With the help of the GET-Parameters I chosse the mode in which the LEDs should light up different.

Everything works fine, as long as I have no for-loop (like the rainbow-mode). If I start the rainbow mode the leds change their color, but if I want to change the mode, nothing happens.

Do you know what's wrong with this or have I missed something?

If you need more information just let me know. Thanks.

Here's the sketch:

void loop() {
  // Rufe die Methode auf, die in server.onNotFound() gesetzt wurde
  server.handleClient();
}
void getHook() {
  // Prüfe, ob ein Mode angegeben wurde
  if(server.hasArg("mode") && server.arg("mode") != ""){
    // Prüfe den Mode
    if(server.arg("mode") == "normal"){
      if(server.hasArg("color") && server.arg("color") != ""){
        for(int i = 1; i <= ledsCount; i++){
          setLED(i, getColor(server.arg("color")));
        }
      }
    }else if(server.arg("mode") == "rainbow"){
      // Client-Status auf 200 setzen

      uint16_t i, j;
      for(j=0; j<256; j++) {
        for(i=0; i<pixels.numPixels(); i++) {
          pixels.setPixelColor(i, Wheel((i*1+j) & 255));
        }
        pixels.show();
        delay(200);
      }
      getHook();
    }else if(server.arg("mode") == "debug"){
      if(server.hasArg("color") && server.arg("color") != ""){
          // LEDs aufwärts gehen
          uint32_t color = getColor(server.arg("color"));
          
          for(int i = 1; i <= ledsCount; i++){
            setLEDOnOff(i, color, 200);
          }
      }
      if(server.hasArg("color2") && server.arg("color2") != ""){
          // LEDs abwärts gehen
          uint32_t color2 = getColor(server.arg("color2"));
          
          for(int i = ledsCount; i >= 1; i--){
            setLEDOnOff(i, color2, 200);
          } 
      }  
    }else{
      // Alle LEDs ausschalten
      for(int i = ledsCount; i >= 1; i--){
        setLED(i, off);
      }
    }

    // Ende der Seite
    setServerEnd();
  }else{
    // Ende der Seite
    server.send(200, "text/plain", "Nix zu tun!");
  }
}

Bye
Joggi

I can spot two problems with your code, the first being this:

for(j=0; j<256; j++) {
        for(i=0; i<pixels.numPixels(); i++) {
          pixels.setPixelColor(i, Wheel((i*1+j) & 255));
        }
        pixels.show();
        delay(200);
      }

The outer for loop runs 256 iterations, each having a call to pixels.show() and delay(200). pixels.show() is slow and 256 times a delay of 200 gives about 51 seconds of blocking, that's not ideal..

But what might be a killer is that you recursively call getHook() which may cause a stack overflow that will cause the ESP to freeze.

this might write out of your array boundary.
a) the first pixel is 0 (not 1) and the last pixel is ledsCount -1 and not ledsCount.
so

for(int i = 0; i <ledsCount; i++)

is safer.
further more, see the fill method of the library which can fill a strip with one single line without a loop

please post full compileable code, not just code parts...

P.S.: there is also a very active German subforum here on arduino.cc ... for your next question ...

Hi you two,

thanks for your answers.

@Danois90:

  • is there a solution for the use of pixels.show()?
  • I call getHook() because if I don't do it, I can send antoher command via GET but the rainbow-effect will shown only once and I have to send the request again. Is there a better way to do it?

@noiasca:

  • In my setLEDOnOff-Method the i will be decreased by 1, but I will change that!
  • I'll use the fill()-Method...thank you :slight_smile:
  • Is my english that bad? :smiley:

Joggi

And here is the complete sketch:

// Einbinden externer Dateien
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Adafruit_NeoPixel.h>

// LEDs
#define ledsCount 54
#define dataPin 4
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(ledsCount, dataPin, NEO_GRB + NEO_KHZ800);

// Wifi
const char* ssid = "mySSID";
const char* pwd = "myPWD";

// Webserver
ESP8266WebServer server(80);

// Colors
uint32_t off = pixels.Color(0, 0, 0);
uint32_t nearlyOff = pixels.Color(10, 10, 10);
uint32_t red = pixels.Color(255, 0, 0);
uint32_t green = pixels.Color(0, 255, 0);
uint32_t blue = pixels.Color(0, 0, 255);
uint32_t turquoise = pixels.Color(0, 197, 205);
uint32_t orange = pixels.Color(255, 165, 0);
uint32_t white = pixels.Color(255, 255, 255);

// Methoden
void setLEDBlink(int ledPosition, uint32_t color, int duration, int counter){
  /* Prüfe, ob ledPosition okay ist */
  if(ledPosition != 0){
    ledPosition -= 1;
    /* Prüfe, ob ledPosition okay ist */
    if(ledPosition >= 0 && ledPosition < ledsCount){
      for(int i = 0; i < counter; i++){
        pixels.setPixelColor(ledPosition, color);
        pixels.show();
        delay(duration);
        pixels.setPixelColor(ledPosition, off);
        pixels.show();
        delay(duration);
      }
    }
  }  
}
void setLEDOnOff(int ledPosition, uint32_t color, int duration) {
  /* Prüfe, ob ledPosition okay ist */
  if(ledPosition != 0){
    ledPosition -= 1;
    /* Prüfe, ob ledPosition okay ist */
    if(ledPosition >= 0 && ledPosition < ledsCount){
      pixels.setPixelColor(ledPosition, color);
      pixels.show();
      delay(duration);
      pixels.setPixelColor(ledPosition, 0, 0, 0);
      pixels.show();
    }
  }  
}
void setLED(int ledPosition, uint32_t color) {
  /* Prüfe, ob ledPosition okay ist */
  if(ledPosition != 0){
    ledPosition -= 1;
    /* Prüfe, ob ledPosition okay ist */
    if(ledPosition >= 0 && ledPosition < ledsCount){
      pixels.setPixelColor(ledPosition, color);
      pixels.show();
    }
  }  
}
void setServerEnd(){
  server.send(200, "text/plain", "OK");
}
uint32_t getColor(String color){
  // Farben prüfen
  if(color == "off"){
    return off;
  }else if(color == "nearlyOff"){
    return nearlyOff;
  }else if(color == "red"){
    return pixels.Color(255, 0, 0);
  }else if(color == "green"){
    return green;
  }else if(color == "blue"){
    return blue;
  }else if(color == "turquoise"){
    return turquoise;
  }else if(color == "orange"){
    return orange;
  }else if(color == "white"){
    return white;
  }else{
    return off;
  }
}
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } 
  else {
    WheelPos -= 170;
    return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
void getHook() {
  // Prüfe, ob ein Mode angegeben wurde
  if(server.hasArg("mode") && server.arg("mode") != ""){
    // Prüfe den Mode
    if(server.arg("mode") == "normal"){
      if(server.hasArg("color") && server.arg("color") != ""){
        for(int i = 1; i <= ledsCount; i++){
          setLED(i, getColor(server.arg("color")));
        }
      }
    }else if(server.arg("mode") == "rainbow"){
      // Client-Status auf 200 setzen

      uint16_t i, j;
      for(j=0; j<256; j++) {
        for(i=0; i<pixels.numPixels(); i++) {
          pixels.setPixelColor(i, Wheel((i*1+j) & 255));
        }
        pixels.show();
        delay(100);
      }
      
    }else if(server.arg("mode") == "debug"){
      if(server.hasArg("color") && server.arg("color") != ""){
          // LEDs aufwärts gehen
          uint32_t color = getColor(server.arg("color"));
          
          for(int i = 1; i <= ledsCount; i++){
            setLEDOnOff(i, color, 200);
          }
      }
      if(server.hasArg("color2") && server.arg("color2") != ""){
          // LEDs abwärts gehen
          uint32_t color2 = getColor(server.arg("color2"));
          
          for(int i = ledsCount; i >= 1; i--){
            setLEDOnOff(i, color2, 200);
          } 
      }  
    }else{
      // Alle LEDs ausschalten
      for(int i = ledsCount; i >= 1; i--){
        setLED(i, off);
      }
    }

    // Ende der Seite
    setServerEnd();
  }else{
    // Ende der Seite
    server.send(200, "text/plain", "Nix zu tun!");
  }

  
}

// Main
void setup() {
  // LED-Strip starten
  pixels.begin();
  pixels.show();
  
  // ESP8266 mit WiFi verbinden
  WiFi.begin(ssid, pwd);
  // Warte, bis die Verbindung hergestellt wurde
  while (WiFi.status() != WL_CONNECTED) {
    // 1 LED rot aufleuchten lassen, solange nicht verbunden
    setLED(1, red);
    delay(200);
  }
  // Sobald Verbindung hergestellt wurde, 1 LED kurz aufleuchten lassen
  setLED(1, green);
  // Starte den Server und warte kurz
  server.begin();
  delay(5000);
  // Sobald Verbindung hergestellt wurde, 1 LED 3x kurz aufleuchten lassen
  setLEDBlink(1, blue, 200, 3);

  // Definiere die Methode, wenn alles passt
  server.onNotFound([]() {
    getHook();
  });

  // Debug
  Serial.begin(9600);
}
void loop() {
  // Rufe die Methode auf, die in server.onNotFound() gesetzt wurde
  server.handleClient();
}

You should un-block your code, remove all the delay and use millis() for timing instead. That would make the execution much more fluid.

Thank you Danois90!
Using millis() and rewrite the code helps a lot and now everything works fine!

Bye
Joggi