I believe there is a bug, at least in 0.6.2, and possibly others, if you interrupt a Cellular.connect() by calling Cellular.disconnect() and Cellular.off(). It seems to leave things in a bad state and I can’t get it to connect again. This is easily worked around, and with the code below I can successfully disconnect and reconnect the antenna at various times without problems.
#include "Particle.h"
SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);
SerialLogHandler logHandler;
const unsigned long STARTUP_DELAY_MS = 5000; // To allow for serial connection to be made
const unsigned long CELLULAR_CONNECT_TIMEOUT_MS = 120000;
const unsigned long CLOUD_CONNECT_TIMEOUT_MS = 30000;
const unsigned long PUBLISH_PERIOD_MS = 30000;
const unsigned long RETRY_CONNECT_DELAY_MS = 60000;
enum State {
STARTUP_STATE,
CELLULAR_CONNECT_STATE,
CELLULAR_CONNECT_WAIT_STATE,
CLOUD_CONNECT_STATE,
CLOUD_CONNECT_WAIT_STATE,
CLOUD_CONNECTED_STATE,
CLOUD_DISCONNECT_STATE,
RETRY_WAIT_STATE
};
State state = STARTUP_STATE;
unsigned long stateTime = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
switch(state) {
case STARTUP_STATE:
if (millis() - stateTime >= STARTUP_DELAY_MS) {
state = CELLULAR_CONNECT_STATE;
}
break;
case CELLULAR_CONNECT_STATE:
Log.info("turning cellular on");
Cellular.on();
Log.info("connecting to cellular...");
Cellular.connect();
state = CELLULAR_CONNECT_WAIT_STATE;
stateTime = millis();
break;
case CELLULAR_CONNECT_WAIT_STATE:
if (Cellular.ready()) {
Log.info("connected to cellular");
state = CLOUD_CONNECT_STATE;
}
else
if (millis() - stateTime >= CELLULAR_CONNECT_TIMEOUT_MS) {
Log.info("failed to connect to cellular");
Log.info("disconnecting from cellular");
Cellular.disconnect();
delay(2000);
Log.info("turning cellular off");
Cellular.off();
// There appears to be a bug in 0.6.2 where if you interrupt a cellular connect,
// you can't connect again. Work around this by going into deep sleep for a few
// seconds which will reset the system firmware state. You can tell this is happening
// if you go into breathing dark blue after doing the Cellular.connect().
// https://community.particle.io/t/particle-connection-process-modem-cancel-bug-if-modem-registration-aborted/33138/
Log.info("going into deep sleep to reset device and modem");
delay(2000);
System.sleep(SLEEP_MODE_DEEP, 10);
// Not reached, system will reset and start over with setup and loop again after waking up
}
break;
case CLOUD_CONNECT_STATE:
Log.info("connecting to cloud");
Particle.connect();
state = CLOUD_CONNECT_WAIT_STATE;
stateTime = millis();
break;
case CLOUD_CONNECT_WAIT_STATE:
if (Particle.connected()) {
state = CLOUD_CONNECTED_STATE;
stateTime = millis();
}
else
if (millis() - stateTime >= CLOUD_CONNECT_TIMEOUT_MS) {
Log.info("failed to connect to the cloud");
state = CLOUD_DISCONNECT_STATE;
}
break;
case CLOUD_CONNECTED_STATE:
if (Particle.connected()) {
if (millis() - stateTime >= PUBLISH_PERIOD_MS) {
stateTime = millis();
// We send test events otherwise the device may not realize it has disconnected
// from the cloud
Log.info("sending test event");
Particle.publish("testEvent", "", PRIVATE);
}
}
else {
Log.info("lost cloud connection");
state = CLOUD_DISCONNECT_STATE;
}
break;
case CLOUD_DISCONNECT_STATE:
Log.info("disconnecting from cloud");
Particle.disconnect();
Log.info("disconnecting from cellular");
Cellular.disconnect();
delay(2000);
Log.info("turning cellular off");
Cellular.off();
state = RETRY_WAIT_STATE;
stateTime = millis();
break;
case RETRY_WAIT_STATE:
if (millis() - stateTime >= RETRY_CONNECT_DELAY_MS) {
state = CELLULAR_CONNECT_STATE;
break;
}
}
}