While loop crashing MCU

when i call " strobeFunction(500, 500, 1024, 10);" The esp8266 crashes after 6 serial prints. every time. if i remove the function call the esp does not crash. any ideas why this is happening??


unsigned long now2 = 0;

int counter = 0;

unsigned long strobenow = 0;
unsigned long strobenow2 = 0;
bool strobeoff = true;

const int strobe = 4;


void strobeFunction(int delay1, int delay2, int brightness, int times) {
  // server.send(200, "ok");

  while (counter < times) {
    if (millis() - strobenow >= delay1 && strobeoff) {
      counter++;
      //     analogWrite(strobe, brightness); //turn it on
      Serial.println("strobe on");
      strobeoff = false;
      Serial.println("strobe 1");
      strobenow2 = millis();
      Serial.println("strobe 2");
    }
    if (millis() - strobenow2 >= delay2 && !strobeoff ) {
      Serial.println("strobe 3");
        // analogWrite(strobe, 0); //turn it off
        Serial.println("strobe ff");
        strobenow = millis();
        strobeoff = true;
      }
    }

  }

  void setup(void) {

    pinMode(strobe, OUTPUT);
    digitalWrite(strobe, LOW);
    Serial.begin(115200);

    strobeFunction(500, 600, 1024, 10);
  }
  void loop(void) {

  }

if i only call it like this it does not crash,

strobeFunction(500, 500, 1024, 2);

i dont understand whats wrong

if i call strobeFunction(500, 500, 1024, 2); every 10 seconds like this,

  if (millis() - now >= 10000) {
    //sendStruct();
    Serial.println("started");
    counter = 0;
    strobeFunction(500, 500, 1024, 2);
    now = millis();
  }

it does not crash?

Here is have minimized the code and the problem persists. Someone tell me whats going wrong?


unsigned long now2 = 0;

int counter = 0;

unsigned long strobenow = 0;
unsigned long strobenow2 = 0;
bool strobeoff = true;

const int strobe = 4;


void strobeFunction(int delay1, int delay2, int brightness, int times) {
  // server.send(200, "ok");

  while (counter < times) {
    if (millis() - strobenow >= delay1 && strobeoff) {
      counter++;
      //     analogWrite(strobe, brightness); //turn it on
      Serial.println("strobe on");
      strobeoff = false;
      Serial.println("strobe 1");
      strobenow2 = millis();
      Serial.println("strobe 2");
    }
    if (millis() - strobenow2 >= delay2 && !strobeoff ) {
      Serial.println("strobe 3");
        // analogWrite(strobe, 0); //turn it off
        Serial.println("strobe ff");
        strobenow = millis();
        strobeoff = true;
      }
    }

  }

  void setup(void) {

    pinMode(strobe, OUTPUT);
    digitalWrite(strobe, LOW);
    Serial.begin(115200);

    strobeFunction(500, 600, 1024, 10);
  }
  void loop(void) {

  }
void strobeFunction(int delay1, int delay2, int brightness, int times) {

I wonder which arguments are the wrong datatype.

yield() was the solution. put a yeild in each itteration of the While loop. somthing about the wifi stack and memory corruption.

Hi,
I ran your code on a UNO, and added a serialprint to show the count and it functioned okay.
I put a serialprint in the void loop() to show it had ended.

unsigned long now2 = 0;
int counter = 0;
unsigned long strobenow = 0;
unsigned long strobenow2 = 0;
bool strobeoff = true;
const int strobe = 4;

void strobeFunction(int delay1, int delay2, int brightness, int times) {
  // server.send(200, "ok");
  while (counter < times) {
    if (millis() - strobenow >= delay1 && strobeoff) {
      counter++;
      //     analogWrite(strobe, brightness); //turn it on
      Serial.println("strobe on");
      strobeoff = false;
      Serial.println("strobe 1");
      strobenow2 = millis();
      Serial.print("strobe 2   counter = ");
      Serial.println(counter);
    }

    if (millis() - strobenow2 >= delay2 && !strobeoff) {
      Serial.println("strobe 3");
      // analogWrite(strobe, 0); //turn it off
      Serial.print("strobe ff   counter = ");
      Serial.println(counter);
      strobenow = millis();
      strobeoff = true;
    }
  }
}

void setup(void) {
  pinMode(strobe, OUTPUT);
  digitalWrite(strobe, LOW);
  Serial.begin(115200);
  strobeFunction(500, 600, 1024, 10);
}

void loop(void) {
Serial.println("Finished");
while (1)
{
} 
}

Tom… :grinning: :+1: :coffee: :australia:

Yes but the description says im using esp8266. This not a problem on Arduino board. try it on esp8266

Hi,
Have you tried my code with the extra lines to trace the counter variable?

Tom… :grinning: :+1: :coffee: :australia:

Hello,
I had something similar in the past where the solution was to not to call millis() too many times. But store the value of millis() in a temporary variable each cycle. Second thing you could do is be careful with too many Serial.println() as this might cause some buffer overruns or overload on code sections where interrupts are blocked. Other thing that can be usefull: add delay(10) to your code so the processor has some room to schedule saved interrupt tasks.
Another approach that is much clearer is the use of a timer object instead of the millis().

see Use multiple millis - Using Arduino / Programming Questions - Arduino Forum

yes your code crashes too

so if i had the same program with lots of those while loops, i could add dealy() or yield() in the main loop instead of all the while loops. i mean obviously this would probably not be ideal. but would work?

thanks for sharing the link. it is in my nature to over complicate things

Hi,
It doesn’t end with
“Finished”?
Tom… :grinning: :+1: :coffee: :australia:

02:37:56.066 -> strobe on
02:37:56.066 -> strobe 1
02:37:56.066 -> strobe 2   counter = 1
02:37:56.666 -> strobe 3
02:37:56.666 -> strobe ff   counter = 1
02:37:57.146 -> strobe on
02:37:57.146 -> strobe 1
02:37:57.146 -> strobe 2   counter = 2
02:37:57.759 -> strobe 3
02:37:57.759 -> strobe ff   counter = 2
02:37:58.258 -> strobe on
02:37:58.258 -> strobe 1
02:37:58.258 -> strobe 2   counter = 3
02:37:58.817 -> 
02:37:58.817 -> --------------- CUT HERE FOR EXCEPTION DECODER ---------------
02:37:58.817 -> 
02:37:58.817 -> Soft WDT reset
02:37:58.817 -> 
02:37:58.817 -> >>>stack>>>
02:37:58.817 -> 
02:37:58.817 -> ctx: cont
02:37:58.817 -> sp: 3ffffd40 end: 3fffffc0 offset: 01a0
02:37:58.817 -> 3ffffee0:  00000748 feefeffe feefeffe feefeffe  
02:37:58.857 -> 3ffffef0:  3ffe8664 00000000 0a0d0064 40202891  
02:37:58.857 -> 3fffff00:  0031c977 4bc6a7f0 0031c977 00000000  
02:37:58.857 -> 3fffff10:  0031c977 00000000 4bc6a7f0 00000000  
02:37:58.857 -> 3fffff20:  402011e0 3ffee350 401001d0 4bc6a7f0  
02:37:58.857 -> 3fffff30:  00000000 3ffee350 3ffe8662 402013e9  
02:37:58.857 -> 3fffff40:  000ebca6 00000001 3ffee350 40201418  
02:37:58.857 -> 3fffff50:  000001f4 3ffee350 3ffee350 00000258  
02:37:58.857 -> 3fffff60:  000001f4 3ffee350 3ffee330 40201078  
02:37:58.897 -> 3fffff70:  0000000a feefeffe feefeffe feefeffe  
02:37:58.897 -> 3fffff80:  0001c200 0000001c 00000000 3ffee3b8  
02:37:58.897 -> 3fffff90:  3fffdad0 00000000 3ffee378 4020115a  
02:37:58.897 -> 3fffffa0:  feefeffe feefeffe feefeffe 40201b2c  
02:37:58.897 -> 3fffffb0:  feefeffe feefeffe 3ffe84e4 40100bed  
02:37:58.897 -> <<<stack<<<
02:37:58.897 -> 
02:37:58.897 -> --------------- CUT HERE FOR EXCEPTION DECODER ---------------
02:37:58.897 -> 
02:37:58.897 ->  ets Jan  8 2013,rst cause:2, boot mode:(3,6)
02:37:58.938 -> 
02:37:58.938 -> load 0x4010f000, len 3584, room 16 
02:37:58.938 -> tail 0
02:37:58.938 -> chksum 0xb0
02:37:58.938 -> csum 0xb0
02:37:58.938 -> v2843a5ac
02:37:58.938 -> ~ld

no it did not.

The code i posted was just a test. the code im going to use will be like this with no while loop.

const int ledPin =  A0;// the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
unsigned long previousMillis = 0;        // will store last time LED was updated
unsigned long previousMillis2 = 0;
const long interval = 1000;           // interval at which to blink (milliseconds)
bool strobeoff = true;
int counter = 0;
bool alarm = true;
void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
}

void handleStrobe(int delayOn, int delayOff, int brightness, int times) {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= delayOn && strobeoff) {
    previousMillis = currentMillis;
    counter++;
    strobeoff = false;
    Serial.println("strobe on");
    previousMillis2 = millis();
  }
  if (currentMillis - previousMillis2 >= delayOff && !strobeoff) {
    previousMillis = currentMillis;
    strobeoff = true;
    Serial.println("strobe off");
    previousMillis = millis();
  }
  if (counter >= times) {
    alarm = false;
    strobeoff = true;
    Serial.println("strobe off counter");
    counter = 0;
  }
}
void loop() {
  if (alarm) {
    handleStrobe(500, 500, 1024, 10);
  }
}

which is just blinkWithoutDelay + statechange
and the function arguments will be from a web server.

BUT the whole yield() problem with the wifi stack might explain a lot of problems i have with random crashes

I believe that the ESP stuff uses a watchdog timer that throws exception if it doesn’t get “patted” often enough. I think main calls it.

So if you have something in your code that takes a long time, without letting the watchdog code have some CPU it will fail. Yield gets around that and I expect that the ESP implementation of delay does too.