Wemos D1 Mini Neopixel millis() Watchdog

Hello, I am trying to write a code for an Wemos D1 with a neopixel strip connected to it mini pro but i have issues with a function, if I execute the RedSlowPulsing function in my code the Wemos D1 mini is rebooting after executing for once..
here are my code files:


#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncTCP.h>
#include <neopixels.h>
#include <websockets.h>

#define DEBUG
#define WIFI_DE
//#define WIFI_FR

#ifdef WIFI_DE
char ssid[] = "######";
char password[] = "#######";
#endif

#ifdef WIFI_FR
char ssid[] = "#####";
char password[] = "#######";
#endif


void setup()
{
  ESP.wdtDisable();
  ESP.wdtEnable(WDTO_8S);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
#ifdef DEBUG
    Serial.println("Connecting to WiFi..");
#endif
  }

  // Print ESP Local IP Address
#ifdef DEBUG
  Serial.println(WiFi.localIP());
#endif
  initWebSocket();

  // Start server
  server.begin();

  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop()
{

  ws.cleanupClients();


  H2Pixels = h2Amount / 5;
  BMPixels = bmAmount / 5;
  NGPixels = ngAmount / 5;

Serial.println("H2:");
Serial.println(h2Amount);
Serial.println("BM:");
Serial.println(bmAmount);
Serial.println("NG:");
Serial.println(ngAmount);
  while (h2Amount + bmAmount + ngAmount == 300)
  {
    RedSlowPulsing();
  }
  if (H2Pixels + BMPixels + NGPixels < 21  && H2Pixels + BMPixels + NGPixels >=1)
  {
    RunningLights(80);
  }
  if (H2Pixels + BMPixels + NGPixels == 0)
  {
    RedSlowPulsing();
  }
  if (h2Amount + bmAmount + ngAmount == 600)
  {
    setLightsOff();
  }
}

here is my neopixels.h:

const uint8_t PIN = 4;
const uint16_t NUM_LEDS = 172;
#define MAXIMUM_BRIGHTNESS 255
#define MEDIUM_BRIGHTNESS 130
#define LOW_BRIGHTNESS 100

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

unsigned long previousMillis = 0; // declare and initialize previousMillis
const uint32_t interval = 15;
// Variables for RedSlowPulsing
byte maxBrightness = 255;
byte minBrightness = 30;
//////////////////////////////////////////////

// Colours H2 Blue, BM green and NG yellow
byte redH2 = 0;
byte greenH2 = 175;
byte blueH2 = 215;

byte redBM = 132;
byte greenBM = 189;
byte blueBM = 0;

byte redNG = 255;
byte greenNG = 209;
byte blueNG = 0;

// Pixel für die einzelen Farbsegmente
byte H2Pixels = 6;
byte BMPixels = 7;
byte NGPixels = 6;

byte h = 0;
byte bm = 0;
byte ng = 0;

byte pos = 0;

// 20 Reihen 3 Spalten Array
// Pixel für Farben
byte myLEDS[20][3] =
    {
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG}};

void setMyPixel(byte Pixel, byte red, byte green, byte blue)
{

  if ((Pixel >= 0) && (Pixel <= NUM_LEDS))
  {
    strip.setPixelColor(Pixel, strip.Color(red, green, blue));
  }
}
void setLightsToBrightness(byte brightness)
{

  strip.setBrightness(brightness);
  strip.show();
}
void setLightsOff()
{
  strip.clear();
  strip.show();
}
void RunningLights(byte WaveDelay)
{
  strip.setBrightness(255);
  // Example : H2Pixels = 6; BMPixels = 6; NGPixels = 7;
  // Example : h = 0; bm = 0; ng = 0;

  for (h = 0; h < H2Pixels; h++)
  {
    myLEDS[h][0] = redH2;
    myLEDS[h][1] = greenH2;
    myLEDS[h][2] = blueH2;
  }

  for (bm = h; bm < BMPixels + H2Pixels; bm++)
  {
    myLEDS[bm][0] = redBM;
    myLEDS[bm][1] = greenBM;
    myLEDS[bm][2] = blueNG;
  }

  for (ng = bm; ng < NGPixels + BMPixels + H2Pixels; ng++)
  {
    myLEDS[ng][0] = redNG;
    myLEDS[ng][1] = greenNG;
    myLEDS[ng][2] = blueNG;
  }

  byte Col1Pos = 0;

  for (byte start = 20; start > 0; start--) /// "strip" is 20 leds: 2x5 leds
  {
    for (byte i = -20; i < NUM_LEDS + 20; i = i + 20)
    {
      Col1Pos = i + start;

      setMyPixel(Col1Pos, myLEDS[0][0], myLEDS[0][1], myLEDS[0][2]);
      setMyPixel(Col1Pos + 1, myLEDS[1][0], myLEDS[1][1], myLEDS[1][2]);
      setMyPixel(Col1Pos + 2, myLEDS[2][0], myLEDS[2][1], myLEDS[2][2]);
      setMyPixel(Col1Pos + 3, myLEDS[3][0], myLEDS[3][1], myLEDS[3][2]);
      setMyPixel(Col1Pos + 4, myLEDS[4][0], myLEDS[4][1], myLEDS[4][2]);
      setMyPixel(Col1Pos + 5, myLEDS[5][0], myLEDS[5][1], myLEDS[5][2]);
      setMyPixel(Col1Pos + 6, myLEDS[6][0], myLEDS[6][1], myLEDS[6][2]);
      setMyPixel(Col1Pos + 7, myLEDS[7][0], myLEDS[7][1], myLEDS[7][2]);
      setMyPixel(Col1Pos + 8, myLEDS[8][0], myLEDS[8][1], myLEDS[8][2]);
      setMyPixel(Col1Pos + 9, myLEDS[9][0], myLEDS[9][1], myLEDS[9][2]);
      setMyPixel(Col1Pos + 10, myLEDS[10][0], myLEDS[10][1], myLEDS[10][2]);
      setMyPixel(Col1Pos + 11, myLEDS[11][0], myLEDS[11][1], myLEDS[11][2]);
      setMyPixel(Col1Pos + 12, myLEDS[12][0], myLEDS[12][1], myLEDS[12][2]);
      setMyPixel(Col1Pos + 13, myLEDS[13][0], myLEDS[13][1], myLEDS[13][2]);
      setMyPixel(Col1Pos + 14, myLEDS[14][0], myLEDS[14][1], myLEDS[14][2]);
      setMyPixel(Col1Pos + 15, myLEDS[15][0], myLEDS[15][1], myLEDS[15][2]);
      setMyPixel(Col1Pos + 16, myLEDS[16][0], myLEDS[16][1], myLEDS[16][2]);
      setMyPixel(Col1Pos + 17, myLEDS[17][0], myLEDS[17][1], myLEDS[17][2]);
      setMyPixel(Col1Pos + 18, myLEDS[18][0], myLEDS[18][1], myLEDS[18][2]);
      setMyPixel(Col1Pos + 19, myLEDS[19][0], myLEDS[19][1], myLEDS[19][2]);
    }
    strip.show();
    delay(WaveDelay);
  }
}
void RedSlowPulsing()
{

  for (byte i = 0; i < NUM_LEDS; i++)
  {
    setMyPixel(i, 255, 0, 0);
  }

  // fade in
  for (byte x = minBrightness; x < MAXIMUM_BRIGHTNESS; x++)
  {
    setLightsToBrightness(x);
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval)
    {
      previousMillis = currentMillis; // update previousMillis to currentMillis
    }
  }

  // fade out
  for (int x = MAXIMUM_BRIGHTNESS; x >= minBrightness; x--)
  {
    setLightsToBrightness(x);
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval)
    {
      previousMillis = currentMillis; // update previousMillis to currentMillis
    }
  }
}

and here is my websockets.h:


int h2Amount, bmAmount, ngAmount;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");


void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    #ifdef DEBUG
     Serial.printf("%s\n", (char*)data);
    #endif
        String message = "";
        for (size_t i = 0; i < len; i++) {
          message += (char)data[i];
        }
        // Split the message into separate variables
        sscanf(message.c_str(), "%d,%d, %d", &h2Amount, &bmAmount, &ngAmount);
    }
  }


void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
             void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
    #ifdef DEBUG
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
    #endif
      break;
    case WS_EVT_DISCONNECT:
    #ifdef DEBUG
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
    #endif
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}




this is the serial output:

--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Soft WDT reset

>>>stack>>>

ctx: cont
sp: 3ffffdb0 end: 3fffffd0 offset: 01a0
3fffff50:  00000000 00002c0d 2d0e5604 0032ef3c
3fffff60:  0000000e 3ffe864f 0000012b 3fff0938
3fffff70:  3ffe864f 3fff0934 00000092 40201257  
3fffff80:  3fff08e8 00000001 3fff09ec 3fff08ec
3fffff90:  3fff08e8 3fff08e4 0000012c 4020154d
3fffffa0:  3fffdad0 00000000 3fff0b38 3fff0b64  
3fffffb0:  3fffdad0 00000000 3fff0b38 4020ef7c
3fffffc0:  feefeffe feefeffe 3fffdab0 4010100d
<<<stack<<<

Do you have any suggestions how I can fix this problem?
Thank You! :slight_smile:

You are never changing the value of x within the for loop, so it will loop forever. Since you never reset the watchdog timer within the for loop, it times out and the processor resets.

No but x changes and presumably reaches MAX_BRIGHT at some point…

for (byte x = minBrightness; x < MAXIMUM_BRIGHTNESS; x++)

a7

Ah, apparently I woke up stupid this morning.

The millis code does not appear to do anything, so unlikely that is a problem.

Possibly a power problem, how are the LEDs being powered?

You have nested a while-loop

  while (h2Amount + bmAmount + ngAmount == 300)
  {
    yield();
    RedSlowPulsing();
  }
  if (H2Pixels + BMPixels + NGPixels < 21  && H2Pixels + BMPixels + NGPixels >=1)
  {
    RunningLights(80);
  }
  if (H2Pixels + BMPixels + NGPixels == 0)
  {
    yield();
    RedSlowPulsing();
  }

and inside your function RedSlowPulsing you have a for-loop
this keeps the microcontroller busy for too long

add the function-call yield() inside your for-loop
your neo-pixel.h

const uint8_t PIN = 4;
const uint16_t NUM_LEDS = 172;
#define MAXIMUM_BRIGHTNESS 255
#define MEDIUM_BRIGHTNESS 130
#define LOW_BRIGHTNESS 100

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

unsigned long previousMillis = 0; // declare and initialize previousMillis
const uint32_t interval = 15;
// Variables for RedSlowPulsing
byte maxBrightness = 255;
byte minBrightness = 30;
//////////////////////////////////////////////

// Colours H2 Blue, BM green and NG yellow
byte redH2 = 0;
byte greenH2 = 175;
byte blueH2 = 215;

byte redBM = 132;
byte greenBM = 189;
byte blueBM = 0;

byte redNG = 255;
byte greenNG = 209;
byte blueNG = 0;

// Pixel für die einzelen Farbsegmente
byte H2Pixels = 6;
byte BMPixels = 7;
byte NGPixels = 6;

byte h = 0;
byte bm = 0;
byte ng = 0;

byte pos = 0;

// 20 Reihen 3 Spalten Array
// Pixel für Farben
byte myLEDS[20][3] =
    {
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redH2, greenH2, blueH2},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redBM, greenBM, blueBM},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG},
        {redNG, greenNG, blueNG}};

void setMyPixel(byte Pixel, byte red, byte green, byte blue)
{

  if ((Pixel >= 0) && (Pixel <= NUM_LEDS))
  {
    strip.setPixelColor(Pixel, strip.Color(red, green, blue));
  }
}
void setLightsToBrightness(byte brightness)
{

  strip.setBrightness(brightness);
  strip.show();
}
void setLightsOff()
{
  strip.clear();
  strip.show();
}
void RunningLights(byte WaveDelay)
{
  strip.setBrightness(255);
  // Example : H2Pixels = 6; BMPixels = 6; NGPixels = 7;
  // Example : h = 0; bm = 0; ng = 0;

  for (h = 0; h < H2Pixels; h++)
  {
    myLEDS[h][0] = redH2;
    myLEDS[h][1] = greenH2;
    myLEDS[h][2] = blueH2;
  }

  for (bm = h; bm < BMPixels + H2Pixels; bm++)
  {
    myLEDS[bm][0] = redBM;
    myLEDS[bm][1] = greenBM;
    myLEDS[bm][2] = blueNG;
  }

  for (ng = bm; ng < NGPixels + BMPixels + H2Pixels; ng++)
  {
    myLEDS[ng][0] = redNG;
    myLEDS[ng][1] = greenNG;
    myLEDS[ng][2] = blueNG;
  }

  byte Col1Pos = 0;

  for (byte start = 20; start > 0; start--) /// "strip" is 20 leds: 2x5 leds
  {
    for (byte i = -20; i < NUM_LEDS + 20; i = i + 20)
    {
      Col1Pos = i + start;

      setMyPixel(Col1Pos, myLEDS[0][0], myLEDS[0][1], myLEDS[0][2]);
      setMyPixel(Col1Pos + 1, myLEDS[1][0], myLEDS[1][1], myLEDS[1][2]);
      setMyPixel(Col1Pos + 2, myLEDS[2][0], myLEDS[2][1], myLEDS[2][2]);
      setMyPixel(Col1Pos + 3, myLEDS[3][0], myLEDS[3][1], myLEDS[3][2]);
      setMyPixel(Col1Pos + 4, myLEDS[4][0], myLEDS[4][1], myLEDS[4][2]);
      setMyPixel(Col1Pos + 5, myLEDS[5][0], myLEDS[5][1], myLEDS[5][2]);
      setMyPixel(Col1Pos + 6, myLEDS[6][0], myLEDS[6][1], myLEDS[6][2]);
      setMyPixel(Col1Pos + 7, myLEDS[7][0], myLEDS[7][1], myLEDS[7][2]);
      setMyPixel(Col1Pos + 8, myLEDS[8][0], myLEDS[8][1], myLEDS[8][2]);
      setMyPixel(Col1Pos + 9, myLEDS[9][0], myLEDS[9][1], myLEDS[9][2]);
      setMyPixel(Col1Pos + 10, myLEDS[10][0], myLEDS[10][1], myLEDS[10][2]);
      setMyPixel(Col1Pos + 11, myLEDS[11][0], myLEDS[11][1], myLEDS[11][2]);
      setMyPixel(Col1Pos + 12, myLEDS[12][0], myLEDS[12][1], myLEDS[12][2]);
      setMyPixel(Col1Pos + 13, myLEDS[13][0], myLEDS[13][1], myLEDS[13][2]);
      setMyPixel(Col1Pos + 14, myLEDS[14][0], myLEDS[14][1], myLEDS[14][2]);
      setMyPixel(Col1Pos + 15, myLEDS[15][0], myLEDS[15][1], myLEDS[15][2]);
      setMyPixel(Col1Pos + 16, myLEDS[16][0], myLEDS[16][1], myLEDS[16][2]);
      setMyPixel(Col1Pos + 17, myLEDS[17][0], myLEDS[17][1], myLEDS[17][2]);
      setMyPixel(Col1Pos + 18, myLEDS[18][0], myLEDS[18][1], myLEDS[18][2]);
      setMyPixel(Col1Pos + 19, myLEDS[19][0], myLEDS[19][1], myLEDS[19][2]);
    }
    strip.show();
    delay(WaveDelay);
  }
}
void RedSlowPulsing()
{

  for (byte i = 0; i < NUM_LEDS; i++)
  {
    yield();
    setMyPixel(i, 255, 0, 0);
  }

  // fade in
  for (byte x = minBrightness; x < MAXIMUM_BRIGHTNESS; x++)
  {
    yield();
    setLightsToBrightness(x);
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval)
    {
      previousMillis = currentMillis; // update previousMillis to currentMillis
    }
  }

  // fade out
  for (int x = MAXIMUM_BRIGHTNESS; x >= minBrightness; x--)
  {
    yield();
    setLightsToBrightness(x);
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval)
    {
      previousMillis = currentMillis; // update previousMillis to currentMillis
    }
  }
}

The yield() function is also implemented inside the ESP8266 libraries:

Yielding

This is one of the most critical differences between the ESP8266 and a more classical Arduino microcontroller. The ESP8266 runs a lot of utility functions in the background – keeping WiFi connected, managing the TCP/IP stack, and performing other duties. Blocking these functions from running can cause the ESP8266 to crash and reset itself. To avoid these mysterious resets, avoid long, blocking loops in your sketch.

The amazing creators of the ESP8266 Arduino libraries also implemented a yield() function, which calls on the background functions to allow them to do their things.

That's why you can call yield() from within your main program where the ESP8266 header is included.
vgs

1 Like

thank you so much! that worked :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.