Electron stuck blinking Cyan


#1

My electron usually works fine. Sporadically however, it will demonstrate the following pattern when it tries to connect:

Blinking Green > Rapid Cyan > Breathing Cyan > lock-up while Blinking Cyan (5-10mins.) > Sleep

When this happens, the device connects to the Cloud but no data gets published. I’m using 3rd Party SIMs (Bell).

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
STARTUP(System.enableFeature(FEATURE_RESET_INFO));
STARTUP(cellular_credentials_set("mnet.bell.ca.ioe", "", "", NULL));

void setup() {
...
}

void loop() {
switch(state) { 
...    
case CONNECT:
        Cellular.on();
        for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
        Particle.connect();
        for (uint32_t ms = millis(); millis() - ms < 10000; Particle.process());
    	if (waitFor(Particle.connected, 180000)) {
            for (uint32_t ms = millis(); millis() - ms < 5000; Particle.process());
            stateTime = millis();
            state = PUBLISH;
            break;
            }
        else {
            state = SLEEP;
            break;
            }
        break;
    
    case PUBLISH:
        sig = Cellular.RSSI();
        rsi = sig.rssi;
        snprintf(data, sizeof(data), "{\"xx1\": \"%i\", \"xx2\": \"%i\", \"cll\": \"%i\", \"fd1\": \"%i\", \"fd2\": \"%i\", \"fll\": \"%i\", \"lat\": \"%.02f\", \"lng\": \"%.02f\", \"tmz\": \"%i\", \"rsi\": \"%i\"}", xx1, xx2, cll, fd1, fd2, fll, lat, lng, tmz, rsi);
        Serial.println(data);
        Particle.publish(publish, data, PRIVATE, NO_ACK);
        for (uint32_t ms = millis(); millis() - ms < 5000; Particle.process());
        state = SLEEP;
        break;

    case SLEEP:
	Particle.disconnect(); //turning off modem
	for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
        Cellular.off();
        for (uint32_t ms = millis(); millis() - ms < 2000; Particle.process());
	snprintf(buffer, sizeof(buffer), "until next wake-up: %02i:%02i:%02i", sleepTime / 3600, (sleepTime % 3600) / 60, sleepTime % 60);
	Serial.println(buffer);
	delay(500);
        System.sleep(SLEEP_MODE_DEEP, sleepTime);
        break;
    }
}

The Electron will eventually go to Sleep, but the execution of code is severely delayed.

Does anyone have an idea of what may be going wrong here?


#2

From the docs on Particle.publish()

If the cloud connection is turned on and trying to connect to the cloud unsuccessfully, Particle.publish may block for 20 seconds to 5 minutes. Checking Particle.connected() can prevent this.

You should start by checking Particle.connected() as a condition before publishing, and logging to serial or something to see if that is happening.

You have a lot of unnecessary Particle.process() calls here. System Thread will take care of all the connectivity management for you. Per the docs:

Particle.process() and delay() are not needed to keep the background tasks active - they run independently. These functions have a new role in keeping the application events serviced. Application events are:
cloud function calls
cloud events
system events

I don’t see you using any of these, so there is no need to call it. If you are, then it kinda makes sense, but is a strange way to approach that problem.

Why are you delaying 5 seconds after you connect to the particle cloud before publishing? It probably is best just to try and publish right away, I think.

Have you set the appropriate keepAlive interval for your SIM card?

You also don’t need to call Cellular.on(), you should be able to just call Particle.connect(), which will automatically manage the cellular modem doing everything it needs to do to connect.

These simplifications may help narrow down your problem. I would also recommend tracking the times between various actions in your code. For example see how long your Particle.disconnect takes and log that to Serial. See what the timing of your various state changes are, as well as the order.

Also, traditionally you might use a state machine like this in a non-blocking manner a la the following:

switch(state) {
case CONNECT:
     Particle.connect();
     connection_start_time = millis();
     state = WAIT_FOR_CONNECTION;
     break;
case WAIT_FOR_CONNECTION:
     if ( Particle.connected() ) {
          state = PUBLISH;
          break;
     }
     else if ( (millis() - connection_start_time) > 180000) {
          state = SLEEP;
          break;
     }
     state = WAIT_FOR_CONNECTION;   // just come back to this state to check for changes again later
     break;
case PUBLISH:
        sig = Cellular.RSSI();
        rsi = sig.rssi;
        snprintf(data, sizeof(data), "{\"xx1\": \"%i\", \"xx2\": \"%i\", \"cll\": \"%i\", \"fd1\": \"%i\", \"fd2\": \"%i\", \"fll\": \"%i\", \"lat\": \"%.02f\", \"lng\": \"%.02f\", \"tmz\": \"%i\", \"rsi\": \"%i\"}", xx1, xx2, cll, fd1, fd2, fll, lat, lng, tmz, rsi);
        Serial.println(data);
	if ( Particle.connected() ) {
                Particle.publish(publish, data, PRIVATE, NO_ACK);   // blocking so no need to wait for this to finish
        }
        else {
                Serial.println("ERROR, could not publish, particle not connected");
        }
        state = SLEEP;
        break;
case SLEEP:
        snprintf(buffer, sizeof(buffer), "until next wake-up: %02i:%02i:%02i", sleepTime / 3600, (sleepTime % 3600) / 60, sleepTime % 60);
	Serial.println(buffer);
	System.sleep(SLEEP_MODE_DEEP, sleepTime);  // this automatically already shuts off the network for you
	break;
}

This approach may help you yield more CPU time to the System Thread. In general, though SYSTEM_THREAD helps mitigate the effects of blocking code a lot, It’s usually poor practice to block extensively in loop() and sometimes can cause poor performance. It’s also harder to identify corner cases IMO. Maybe give the above a shot if it makes sense to you.


#3

I added that now, can’t believe I missed it.With my 5s delay between connecting and publishing I can see how it can potentially create weird situations.

It’s mainly that I wanted to have some delays here and there (particularly for cellular powering up/down and waiting for OTA updates) and was under the impression Particle.process() is useful to call continuously whenever dealing with anything connectivity-related.

This should normally not be needed as my Electron will never remain connected for more than about 5-10s, but I will add it anyway for the ocassional OTA update I’ll need to do.

Noted, I have removed the call.


#4

This should normally not be needed as my Electron will never remain connected for more than about 5-10s, but I will add it anyway for the ocassional OTA update I’ll need to do.

True, but yeah, I’d add that to a System event handler for a successful cloud connection just to be safe.

It’s mainly that I wanted to have some delays here and there (particularly for cellular powering up/down and waiting for OTA updates) and was under the impression Particle.process() is useful to call continuously whenever dealing with anything connectivity-related.

Makes sense, but that only applies in single threaded mode. Either way, if you take the delay-averse approach I used in my example above, that processing code gets called every loop iteration anyways.

Plus those delays may or may not actually be sufficient, since all those tasks take variable time. I recommend either using a waitFor approach or better yet, just keep looping around in a more pure state machine approach. Delays like you have just abstract the intent of waiting, IMO. Shouldn’t be the cause of your issues though, just a style thing.

Hope you’re able to narrow this down - stuff like this is always frustrating.


#5

Just a heads-up: When using SYSTEM_MODE(MANUAL) w/o SYSTEM_THREAD(ENABLED) that won’t be the case.


#6

Fascinating - does this apply to v0.6.4? If so I’m not seeing it. app_setup_and_loop calls app_loop which has:

if (!threaded)
        Spark_Idle();

And then that seems to directly call all the relevant sub-processes.

That said, you certainly know more than I about this so I’ll take it as fact if I ever find myself using that combination! :smiley:


#7

I continue to have the same problem; Electron still may blink cyan for a long time. Occasionally, it may also be stuck breathing blue (not cyan) for a while.

Really wish control issues over Particle hardware (specifically related to connectivity) was less of a problem. Feels like I’ve been fiddling around for ages now without getting any closer to a solution.

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
STARTUP(System.enableFeature(FEATURE_RESET_INFO));
STARTUP(cellular_credentials_set("mnet.bell.ca.ioe", "", "", NULL));

void setup() {
Particle.keepAlive(30);
...
}

void loop() {
switch(state) { 
...    
case CONNECT:
        Particle.connect();
        for (uint32_t ms = millis(); millis() - ms < 10000; Particle.process());
    	if (waitFor(Particle.connected, 180000)) {
            state = PUBLISH;
            break;
            }
        else {
            state = SLEEP;
            break;
            }
        break;
    
    case PUBLISH:
        snprintf(data, sizeof(data), "{\"xx1\": \"%i\", \"xx2\": \"%i\", \"cll\": \"%i\", \"fd1\": \"%i\", \"fd2\": \"%i\", \"fll\": \"%i\", \"lat\": \"%.02f\", \"lng\": \"%.02f\", \"tmz\": \"%i\", \"rsi\": \"%i\"}", xx1, xx2, cll, fd1, fd2, fll, lat, lng, tmz, rsi);
        Serial.println(data);
        if (Particle.connected()) Particle.publish(publish, data, PRIVATE, NO_ACK);
        for (uint32_t ms = millis(); millis() - ms < 5000; Particle.process()); //Necessary for OTA
        state = SLEEP;
        break;

    case SLEEP:
	Particle.disconnect(); //turning off modem
	for (uint32_t ms = millis(); millis() - ms < 1000; Particle.process());
        Cellular.off();
        for (uint32_t ms = millis(); millis() - ms < 2000; Particle.process());
        System.sleep(SLEEP_MODE_DEEP, sleepTime);
        break;
    }
}