P1 module create a SOS when Wifi lost and reset system

Hi,

Sorry for modifying my question but after doing more debugging, I see a SOS with 9 red blinks, 1 red blinks, 9 red blinks, 1 red blink and reset of systems.

From the status led reference page, it said SPI over-run. Any idea how to debug a SPI over-run? Does SPI over-run cause a reset?

My situation is everything works without WIFI and with a stable WiFi but with a flaky wifi, SOS happen fellow by reset. When I debug my code its when I do a check wifi connection with Particle.connected().

Any suggestion will be great. Thanks

I think you're looking at a "Hard Fault", especially if your "9 red blinks" is the SOS pattern:

... - - - ...

A pattern of more than 10 red blinks is caused by the firmware crashing. The pattern is 3 short blinks, 3 long blinks, 3 short blinks (SOS pattern), followed by a number of blinks that depend on the error, then the SOS pattern again.

https://docs.particle.io/reference/led/photon/#red-flash-sos

@HEng, thanks for replying. You are right, its a “Hard Fault”. I misread the SOS, I thought the 9 blinks was the error code. Is there a flag to tell when the wifi is lost, so I would not go into another code until the wifi is stable base on the flag? When I comment out my check connection code, I will not get a “Hard Fault”.

Another question, why would wifi lost create a “Hard Fault” vs no wifi or stable wifi?

What firmware rev are you running?
I was getting red blinking when running v7.0, when I use v0.6.3 that never happened.

@seulater, I am using v0.7.0. Let me try v0.6.3 and see if I get the same SOS.

@seulater, I tried v0.6.3 but still have the same SOS. Version of firmware maybe not the issue, I am facing. Back to more debugging, only if I have a way to tell wifi is lost.

My code:

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);
STARTUP(System.enableFeature(FEATURE_RESET_INFO));
...

void loop()
{
...

  if (Particle.connected() && islistenMd == true)
    {
      // RGB.control(true);
      // RGB.color(0, 0, 0);
      islistenMd = false;
    }

  // check wifi connection
  if (WiFi.listening() == false && WifiCount == 0)
  {
     checkConnection();     <----- causing the SOS "HARD Fault" when wifi lost

  } else
  {
    if (WiFi.listening() == true )
    {
      // turn off listening mode if wifi set off in menu
      if (WifiCount == 1)  // 1 = off wifi
      {
        // SYNTAX - exit listening mode
        WiFi.listen(false);
        delay(10);
        WiFi.off();
      } else {
          // RGB.control(false);
          islistenMd = true;
      }
    } else
    {
      if (WifiCount == 1)  // 1 = off wifi
      {
        WiFi.off();
      }
    }
  }

...
}

// check wifi connection function
void checkConnection()
{
  if (Particle.connected() == false && millis() - lastDisconnect >= disconnectDelay)
  {
    WiFi.off();
    if (enDebugMode == 1) Serial.printlnf("(checkConnection) wifi disconnected lastDisconnect %d",lastDisconnect);
    lastDisconnect = millis();
  }
  if (Particle.connected() == false && millis() - lastAttempt >= checkInterval)
  {
    WiFi.on();
    Particle.connect();
    if (enDebugMode == 1) Serial.printlnf("(checkConnection) check wifi lastAttempt: %d",lastAttempt);
    lastAttempt = millis();
  }
  if (millis() - lastAttempt >= disconnectDelay)
  {

    tft.setFont(ARIAL_18);
    tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
    tft.setTextSize(1);
    DrawWifi();

    // load back isTimeEnable setting from eeprom
    if (powerDownNoWifi == true && Particle.connected() == true )
    {
      EEPROM.write(504,'0');
      powerDownNoWifi = false;
      DrawTime();
    }

  }
}

Hard fault often is in connection with uninitialised pointers, buffer overrun and such.

WiFi.ready() would tell you about the state of your WiFi connection (independently of the cloud connection).
You can also look at System.on() to subscribe to system events that may inform you about status changes asynchronously.

After debugging some more, I think I found the cause of my problem. After a wifi lost, my code calls

//void drawIcon(int x, int y, int wh, int color, int dimColor, int signalStrength)
void drawIcon(int x, int y, int wh, int color, int dimColor)
{
    int dist = wh  / 5; // distance between blocks
    int sect = 127 / 5; //

    int signalStrength;

  //  int rssi = WiFi.RSSI();
  Serial.printlnf("wifi rssi");
  Serial.println(WiFi.RSSI());    <---- problem 

    int rssi = 1;
...

According to the document:

WiFi.RSSI() returns the signal strength of a Wi-Fi network from -127 (weak) to -1dB (strong) as an int. Positive return values indicate an error with 1 indicating a Wi-Fi chip error and 2 indicating a time-out error.

In my case, I was expecting a 1 or 2 with the Wifi.RSSI(). Any one encounter this issue before?

@ScruffR, could WiFi.RSSI() cause an overrun issue? After a wifi lost, the print statement is empty on my screen for WiFi.RSSI(). If I comment out the Serial.println(WiFi.RSSI()); everything is running smoothly.

Am I not suppose to use WiFi.RSSI() with a wifi disconnect?

This test code will create the SOS:

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

#define disconnectDelay 17000
unsigned long lastAttempt;

// setup() runs once, when the device is first turned on.
void setup() {
  // Put initialization like pinMode and begin functions here.
  Serial.begin(9600);
  WiFi.on();
  Particle.connect();
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
  // The core of your code will likely live here.
  if (!WiFi.listening())
  {
    Serial.printlnf("rssi right away testing");
    Serial.println(WiFi.RSSI());     //<-- this will cause the SOS
  }

  if (millis() - lastAttempt >= disconnectDelay)
  {
  //  Serial.printlnf("wifi rssi");
  //  Serial.println(WiFi.RSSI());     <-- this will not cause the SOS
    lastAttempt = millis();
  }
}

Base on the test, calling WiFi.RSSI() right after a wifi lost will create a Hard fault SOS. Maybe someone can confirm this or not. What I did is connect the P1 module to wifi, then shut off the wifi on the network. Any feedback will be great.

It’d be safest to only call WiFi.RSSI() after you checked for WiFi.ready().

@ScruffR, Wifi.ready() will return a 1 during a WiFi disconnect. Below is my test case modify from above:

void loop() {
  // The core of your code will likely live here.
  if (!WiFi.listening())
  {
    if (WiFi.ready())
    {
      Serial.printlnf("wifi ready");
      Serial.println(WiFi.ready());
      Serial.printlnf("rssi right away testing");
      Serial.println(WiFi.RSSI());
    }
  }

output:

wifi ready
1
rssi right away testing
-32
wifi ready
1
rssi right away testing
-32
wifi ready
1
rssi right away testing
                                  <---- crash and reset
C:\>

Could there a bug inside the WiFi.RSSI() function causing a hard fault? WiFi.ready() still return 1 even the wifi crashes. Any other suggestion to catch a wifi disconnect? I was looking at System.on() but there is not much document on the subject on the reference web page. In my situation, I just need to figure out how to catch a wifi disconnect to prevent the SOS.

Could someone explain to me or point me to a reference table on what the id 129 and value 64,32,16384 refer to? System Events Reference on the web page does not contain any information on these value. Thanks.

 System.on(all_events, handle_all_the_events);
...
void handle_all_the_events(system_event_t event, int param)
{
    Serial.printlnf("got event %d with value %d", event, param);
}

output:

got event 129 with value 64
got event 129 with value 16384
got event 129 with value 32

After trying different options, it seem using a millis timer is the only way that work for me. WiFi.ready(), System.On() does not get trigger when the hard fault happens, it get trigger after reset. Maybe a Particle software engineer can comment on this.

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

#define connectDelay 5000
unsigned long lastAttempt;

// setup() runs once, when the device is first turned on.
void setup() {
  Serial.begin(9600);
  WiFi.on();
  Particle.connect();
}

void loop() {
 if (millis() - lastAttempt >= connectDelay)
  {
    Serial.printlnf("wifi ready");
    Serial.println(WiFi.ready());
    if (WiFi.ready())
    {
      Serial.printlnf("wifi rssi");
      Serial.println(WiFi.RSSI());
    }
    lastAttempt = millis();
  }
}

Here is the file where system events are defined: