Hello,
The Particle firmware connection process has a major bug in it. (I’m running firmware version release/v0.6.2
)
If you call Cellular.disconnect() and then Cellular.off() while the Electron is attempting to register to the cellular network, it breaks the Particle connection state machine.
A subsequent call to Cellular.on() will fail.
#Here is a simple test program that demonstrates this bug
#include "Particle.h"
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);
/*=============================================>>>>>
= Function forward declarations =
===============================================>>>>>*/
// Forward declarations
void waitForSerialInput();
void printSectionBreak();
void printHeaderBreak();
void Disconnect_Particle();
void Disconnect_Cellular();
void Connect_Particle();
void Connect_Cellular();
void Turn_On_Cellular();
void Turn_Off_Cellular();
SerialLogHandler logHandler(LOG_LEVEL_ALL, //Default logging level for non-application messages
{
{ "app", LOG_LEVEL_ALL }, //Logging level for logs from any application .cpp file not specified below
}
);
static Logger myLog("app.main"); //Logger object used in this "main.cpp" file
void showConnectionBug(){
myLog.info("Demonstrating the bug in the Particle firmware:");
Turn_On_Cellular();
Particle.process();
delay(10000);
Connect_Cellular();
Particle.process();
delay(5000);
myLog.warn("PREMATURE ABANDONMENT OF Cellular.connect() process will cause problems after modem power down/up:");
Disconnect_Cellular();
Particle.process();
delay(5000);
Turn_Off_Cellular();
Particle.process();
delay(15000);
Turn_On_Cellular();
Particle.process();
delay(25000);
Connect_Cellular();
Particle.process();
delay(180000);
}
/*=============================================>>>>>
= SETUP FUNCTION =
===============================================>>>>>*/
void setup() {
Serial.begin(115200);
//Wait for user to open the serial monitor
waitForSerialInput();
//Show the bug with the Particle connection process
showConnectionBug();
}
/*=============================================>>>>>
= MAIN LOOP =
===============================================>>>>>*/
void loop() {
}
//Function that waits for user to input a character via the serial monitor
#define WAIT_FOR_SERIAL_MONITOR_TIMEOUT 10000 //Time after the Electron restarts to wait for a serial character to be entered before proceeding
void waitForSerialInput(){
unsigned long timeStart = millis();
while(!Serial.available()){
if((millis() - timeStart) > WAIT_FOR_SERIAL_MONITOR_TIMEOUT){
myLog.warn("Waiting for serial input timed out!");
return;
}
myLog.warn("Waiting for serial input before proceeding");
delay(500);
}
//Now we need to empty the serial buffer
while(Serial.available()){
/*char uselessChar = */Serial.read();
}
myLog.warn("Received serial input, now proceeding!");
// while(!Serial.isConnected())
// Particle.process();
myLog.info("Serial monitor open! Now proceeding!");
}
void printSectionBreak(){
for(int i = 0; i < 5; i++){
for(int ii = 0; ii < 5; ii++){
Serial.print('~');
}
Serial.print("\r\n");
}
}
void printHeaderBreak(){
for(int i = 0; i < 2; i++){
for(int ii = 0; ii < 25; ii++){
Serial.print('~');
}
Serial.print("\r\n");
}
}
void Disconnect_Particle(){
printHeaderBreak();
myLog.warn("!!!!! CALLING Particle.disconnect() !!!!!");
printHeaderBreak();
Particle.disconnect();
}
void Connect_Particle(){
printHeaderBreak();
myLog.warn("!!!!! CALLING Particle.connect() !!!!!");
printHeaderBreak();
Particle.connect();
}
void Disconnect_Cellular(){
printHeaderBreak();
myLog.warn("!!!!! CALLING Cellular.disconnect() !!!!!");
printHeaderBreak();
Cellular.disconnect();
}
void Connect_Cellular(){
printHeaderBreak();
myLog.warn("!!!!! CALLING Cellular.connect() !!!!!");
printHeaderBreak();
Cellular.connect();
}
void Turn_On_Cellular(){
printHeaderBreak();
myLog.warn("!!!!! CALLING Cellular.on() !!!!!");
printHeaderBreak();
Cellular.on();
}
void Turn_Off_Cellular(){
printHeaderBreak();
printHeaderBreak();
Cellular.off();
}
_
_
_
#Here is the debug output from running the above program:
=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2017.05.24 16:27:34 =~=~=~=~=~=~=~=~=~=~=~=
0000001555 [app.main] WARN: Waiting for serial input before proceeding
0000002055 [app.main] WARN: Waiting for serial input before proceeding
0000002556 [app.main] WARN: Waiting for serial input before proceeding
0000003056 [app.main] WARN: Waiting for serial input before proceeding
0000003556 [app.main] WARN: Waiting for serial input before proceeding
0000004057 [app.main] WARN: Waiting for serial input before proceeding
0000004557 [app.main] WARN: Received serial input, now proceeding!
0000004557 [app.main] INFO: Serial monitor open! Now proceeding!
0000004558 [app.main] INFO: Demonstrating the bug in the Particle firmware:
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000004559 [app.main] WARN: !!!!! CALLING Cellular.on() !!!!!
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
[ ElectronSerialPipe::begin ] = = = = = = = =
[ Modem::powerOn ] = = = = = = = = = = = = = =
4.870 AT send 4 "AT\r\n"
4.880 AT read UNK 3 "AT\r"
4.890 AT read OK 6 "\r\nOK\r\n"
5.100 AT send 7 "AT E0\r\n"
5.110 AT read UNK 6 "AT E0\r"
5.120 AT read OK 6 "\r\nOK\r\n"
5.120 AT send 11 "AT+CMEE=2\r\n"
5.130 AT read OK 6 "\r\nOK\r\n"
5.130 AT send 19 "AT+CMER=1,0,0,2,1\r\n"
5.141 AT read OK 6 "\r\nOK\r\n"
5.141 AT send 15 "AT+IPR=115200\r\n"
5.151 AT read OK 6 "\r\nOK\r\n"
5.251 AT send 10 "AT+CPIN?\r\n"
5.261 AT read + 16 "\r\n+CPIN: READY\r\n"
5.271 AT read OK 6 "\r\nOK\r\n"
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000014560 [app.main] WARN: !!!!! CALLING Cellular.connect() !!!!!
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000014561 [system] INFO: Sim Ready
0000014561 [system] INFO: ARM_WLAN_WD 1
[ Modem::init ] = = = = = = = = = = = = = = =
14.562 AT send 9 "AT+CGSN\r\n"
14.582 AT read UNK 19 "\r\n353162076295659\r\n"
14.592 AT read OK 6 "\r\nOK\r\n"
14.592 AT send 9 "AT+CGMI\r\n"
14.602 AT read UNK 10 "\r\nu-blox\r\n"
14.612 AT read OK 6 "\r\nOK\r\n"
14.612 AT send 9 "AT+CGMM\r\n"
14.622 AT read UNK 13 "\r\nSARA-U260\r\n"
14.632 AT read OK 6 "\r\nOK\r\n"
14.632 AT send 9 "AT+CGMR\r\n"
14.642 AT read UNK 9 "\r\n23.20\r\n"
14.652 AT read OK 6 "\r\nOK\r\n"
14.652 AT send 9 "AT+CCID\r\n"
14.662 AT read + 30 "\r\n+CCID: 8934076500002661015\r\n"
14.673 AT read OK 6 "\r\nOK\r\n"
14.673 AT send 11 "AT+UPSV=1\r\n"
14.683 AT read OK 6 "\r\nOK\r\n"
14.683 AT send 11 "AT+CMGF=1\r\n"
14.693 AT read OK 6 "\r\nOK\r\n"
14.693 AT send 13 "AT+CNMI=2,1\r\n"
14.703 AT read OK 6 "\r\nOK\r\n"
14.703 AT send 9 "AT+CIMI\r\n"
14.713 AT read UNK 19 "\r\n214074300556497\r\n"
14.723 AT read OK 6 "\r\nOK\r\n"
[ Modem::register ] = = = = = = = = = = = = = =
14.723 AT send 10 "AT+CREG?\r\n"
14.734 AT read + 14 "\r\n+CREG: 0,0\r\n"
14.744 AT read OK 6 "\r\nOK\r\n"
14.744 AT send 11 "AT+CGREG?\r\n"
14.754 AT read + 15 "\r\n+CGREG: 0,0\r\n"
14.764 AT read OK 6 "\r\nOK\r\n"
14.764 AT send 12 "AT+CGREG=2\r\n"
14.774 AT read OK 6 "\r\nOK\r\n"
14.774 AT send 11 "AT+CREG=2\r\n"
14.784 AT read OK 6 "\r\nOK\r\n"
14.784 AT send 10 "AT+CREG?\r\n"
14.794 AT read + 14 "\r\n+CREG: 2,0\r\n"
14.804 AT read OK 6 "\r\nOK\r\n"
14.804 AT send 11 "AT+CGREG?\r\n"
14.814 AT read + 15 "\r\n+CGREG: 2,0\r\n"
14.824 AT read OK 6 "\r\nOK\r\n"
0000019562 [app.main] WARN: PREMATURE ABANDONMENT OF Cellular.connect() process will cause problems after modem power down/up:
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000019564 [app.main] WARN: !!!!! CALLING Cellular.disconnect() !!!!!
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
[ Modem::cancel ] = = = = = = = = = = = = = = =
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
[ Modem::powerOff ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
24.567 AT send 12 "AT+CPWROFF\r\n"
24.568 AT read + 12 "\r\n+CREG: 4\r\n"
24.578 AT read + 13 "\r\n+CGREG: 4\r\n"
24.588 AT read + 14 "\r\n+CIEV: 3,0\r\n"
24.598 AT read + 14 "\r\n+CIEV: 7,0\r\n"
24.608 AT read + 14 "\r\n+CIEV: 9,0\r\n"
CIEV matched: 9,0
24.618 AT read + 14 "\r\n+CIEV: 2,1\r\n"
27.988 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000039567 [app.main] WARN: !!!!! CALLING Cellular.on() !!!!!
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
[ Modem::powerOn ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
39.878 AT send 4 "AT\r\n"
41.198 AT send 4 "AT\r\n"
42.518 AT send 4 "AT\r\n"
42.528 AT read UNK 3 "AT\r"
42.538 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
0000044638 [system] WARN: Resetting WLAN due to WLAN_WD_TO()
[ Modem::powerOff ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
44.638 AT send 12 "AT+CPWROFF\r\n"
44.699 AT read UNK 11 "AT+CPWROFF\r"
44.709 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
[ Modem::powerOn ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
45.119 AT send 4 "AT\r\n"
46.439 AT send 4 "AT\r\n"
47.759 AT send 4 "AT\r\n"
47.769 AT read UNK 3 "AT\r"
47.779 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
0000047779 [system] INFO: Sim Ready
0000047779 [system] INFO: ARM_WLAN_WD 1
[ Modem::init ] = = = = = = = = = = = = = = =
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000064568 [app.main] WARN: !!!!! CALLING Cellular.connect() !!!!!
~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~
0000077869 [system] WARN: Resetting WLAN due to WLAN_WD_TO()
[ Modem::powerOff ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
77.870 AT send 12 "AT+CPWROFF\r\n"
77.930 AT read UNK 11 "AT+CPWROFF\r"
77.940 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
[ Modem::powerOn ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
78.350 AT send 4 "AT\r\n"
79.670 AT send 4 "AT\r\n"
80.990 AT send 4 "AT\r\n"
81.000 AT read UNK 3 "AT\r"
81.010 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
0000081010 [system] INFO: Sim Ready
0000081010 [system] INFO: ARM_WLAN_WD 1
[ Modem::init ] = = = = = = = = = = = = = = =
0000111111 [system] WARN: Resetting WLAN due to WLAN_WD_TO()
[ Modem::powerOff ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
111.112 AT send 12 "AT+CPWROFF\r\n"
111.172 AT read UNK 11 "AT+CPWROFF\r"
111.182 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
[ Modem::powerOn ] = = = = = = = = = = = = = =
[ Modem::resume ] = = = = = = = = = = = = = = =
111.592 AT send 4 "AT\r\n"
112.912 AT send 4 "AT\r\n"
114.232 AT send 4 "AT\r\n"
114.242 AT read UNK 3 "AT\r"
114.252 AT read OK 6 "\r\nOK\r\n"
[ Modem::cancel ] = = = = = = = = = = = = = = =
0000114252 [system] INFO: Sim Ready
0000114252 [system] INFO: ARM_WLAN_WD 1
[ Modem::init ] = = = = = = = = = = = = = = =
_
_
_
As you can see, the Particle connection process gets caught in an infinite loop that goes something like:
-
[ Modem::powerOff ]
-
[ Modem::resume ]
-
[ Modem::cancel ]
-
[ Modem::powerOn ]
-
[ Modem::resume ]
-
[ Modem::cancel ]
-
[ Modem::init ]
_
_
_
This is extremely problematic for me since I need to be able to alter the radio access technology (RAT) being used by the modem if Cellular.connect() takes too long or times out.
The only way I have found to do that is to call Cellular.off(), wait, call Cellular.on(), wait, and then make my change with the AT+URAT command.
This flow works perfectly if the Electron can connect to the network, and then I disconnect, power down, change RAT, power up, and connect again.
However, if the Electron doesn’t manage to connect to a network, it appears that there is no way of powering down and powering back up the modem without encountering this bug based on my testing.
#Edit 1:
Even if I change the void showConnectionBug()
function (see below) so that I am no longer turning off/turning on the modem, the premature abandonment of the Cellular.connect()
process results in this same infinite loop behaviour. The subsequent call to Cellular.connect()
fails.
void showConnectionBug(){
myLog.info("Demonstrating the bug in the Particle firmware:");
Turn_On_Cellular();
Particle.process();
delay(10000);
Connect_Cellular();
Particle.process();
delay(5000);
myLog.warn("PREMATURE ABANDONMENT OF Cellular.connect() process will cause problems after modem power down/up:");
Disconnect_Cellular();
Particle.process();
delay(5000);
Connect_Cellular();
Particle.process();
delay(180000);
}