ArduinoCloud.update cant reconnect - MQTT client connection lost

Hello, I’ve been having a difficult time with the ArduinoCloud.update() function and its reliability. I have to use both cell (sms) and cloud to get my application working. I have to reset the GSM roughly every hour at this point to make sure the device can receive the sms. This works well and the receive is dependable. However, in the reset, the MQTT client connection is lost. By re-running ArduinoCloud.update() in a loop, it re-connects after about 4 loops. This works only once. Next time around, it runs to 3 loops and no response. I’ve tried other methods (seeing if I can turn off powersave on the Ublox. My hardware is a MKR GSM 1400, on a grove shield. The Ublox is a SARA-U201 03B-00 and on page 532 of the ublox spec, it indicates powersave is off by default. Since I cant do an “AT” command in code for some reason, I have to assume the AdruinoCloud doesnt change that. So, cant used that method, so I reset the GSM by shutdown and reconnect - works fine).
Here is my code that sometimes works, sometimes not. I’ve tried some other methods found in https://forum.arduino.cc/index.php?topic=654299.0 but the compiler rejected the .update on ArduinoIoTPreferredCloud so substituted ArduinoCloud.update() to no effect. In this code if the “on DISCONNECT” call back is used, the onNetworkDisconnect call is made and it never gets reconnected, so eventually does the reboot. Not very useful.

In summary, this code works until the gsm is reset, it reconnects once, and next time, halts. Am I using ArduinoCloud.update() wrong? Does it need any “time” to recover? Are there any other routines I could use to re-connect? As I understand, the ArduinoCloud.update() is supposed to re-connect, but it seems to do that only once and never “comes back”.

Should anything be done before the re-connect to GSM ? Or after? Quite at a loss at this point. Pls forgive code construct. Had to remove some to get withing 9000char limit in forum

Deets:
My signal level is good. Info:
***** Arduino IoT Cloud - configuration info *****
Device ID: 6e649599-6fae-4f7b-a65d-4696e8ca3e87
Thing ID: 7b9f26a3-d47d-4afb-b40e-150f75168c35
MQTT Broker: mqtts-sa.iot.arduino.cc:8883
Carrier is : BELL
SignalStrength(dBm) = 31
SIM card ok
GPRS.attachGPRS(): 4
aSending PING to outer space…
GPRS.ping(): 210
Connected to GPRS Network
Connected to Arduino IoT Cloud

CONNECTED to network

#include "thingProperties.h"

// Include the GSM library
#include <MKRGSM.h>


// initialize the library instance
GSM gsmAccess;
GSM_SMS sms;
GSMLocation location;
GPRS gprs;
GSMScanner carrier;

bool netstate = true;
int netFailState = 1;

#ifdef DEBUG
#define DEBUG_PRINTLN(x)  Serial.println(x)
#define DEBUG_PRINT(x)  Serial.print(x)
#else
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINT(x)
#endif

bool gsmConnected = false; 

bool causeFailFlag = false;



void setup() {
  Serial.begin(9600);

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // Defined in thingProperties.h
  initProperties();


  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  setDebugMessageLevel(4);
  ArduinoCloud.printDebugInfo();
  ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, onNetworkConnect);
  ArduinoCloud.addCallback(ArduinoIoTCloudEvent::DISCONNECT, onNetworkDisconnect);

  // Start GSM shield.  This starts the GSM.  Then ArduinoCloud.update() connects to the cloud. It takes a while.
  // If your SIM has PIN, pass it as a parameter of begin() in quotes
  gsmConnected = connectGSM();


  if (!CLDEBUG) {  // This usually works. Takes about 4 loops

    while (ArduinoCloud.connected() != 1) {
      ArduinoCloud.update();
      delay(500);
    }

  }



}

void loop() {

  ArduinoCloud.update();

  // Lots of code goes here


  smsThere = checkSerial() ;  // (routine removed for forum)

  if (!smsThere) {


    oks = gsmAccess.isAccessAlive();

    if (causeFailFlag) {  // flag is set via sending an 'f' on sms

      oks = 0;   // *** fake failure to test mqtt alive after gsmconnect
      causeFailFlag = false;
    }


    if (!oks) {   // Either cell is down or its reset time
      // Note: this will cause the MQTT connection to fail. 02.17
      // it seems to recover only once.
      //
      gsmAccess.shutdown();   // shut it all down to allow proper restart
      delay(3000);

      // reconnect GSM then cloud
      gsmConnected = connectGSM();
      if (gsmConnected) DEBUG_PRINT(" Success ! ");  // this works pretty much all the time.
      else DEBUG_PRINTLN(" argh. failed. ");

      delay(500);  // wait a bit. MQTT will become disconnected at some point.

      // This works the first time in about 4 loops and reconnects.
      // The second time its run via another 'f' fail invoked, it runs 3 loops then never recovers.
      while (ArduinoCloud.connected() != 1) {
        ArduinoCloud.update();
        delay(500);
      }

    }
    else {  // ok, check

      if (gprs.status() != GPRS_READY) {
        if (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)
          DEBUG_PRINT("mainLoop: GPRS ready!");
        else
          DEBUG_PRINT("mainLoop: GPRS not ready!");
      }
    }
  }
  else {
    DEBUG_PRINTLN("received sms");
    sms.flush();
  }

}


bool connectGSM() {
  gprs.setTimeout(180000);
  gsmAccess.setTimeout(180000);
  boolean connected = false;
  while (!connected) {

    if ((gsmAccess.begin() == GSM_READY) &&
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
      connected = true;
    }
    else {
      delay(1000);
    }
  }
  return connected;
}


void onNetworkDisconnect() { // (void *_arg) {
  // from jbloam (2019) https://forum.arduino.cc/index.php?topic=654299.0 but modified to fit
  // This never seems to recover.  It will always just reboot eventually.
  Serial.println(">>>> DISCONNECTED from network");
  netstate = false;
  digitalWrite(LED_BUILTIN, HIGH);

  delay(30000);
  if ((netstate == false) && (netFailState == 1)) {
    Serial.println("Attempting first GPRS reconnect");
    netFailState = 2;
    // ArduinoIoTPreferredConnection.update();
    ArduinoCloud.update();
  }
  delay(30000);
  if ((netstate == false) && (netFailState == 2)) {
    Serial.println("Attempting second GPRS reconnect");
    // ArduinoIoTPreferredConnection.update();
    netFailState = 3;
    ArduinoCloud.update();
  }
  delay(120000);
  if (netstate == false) {
    reboot();
  }
}

void reboot() {
  Serial.println("Rebooting...");
  NVIC_SystemReset();
}

Update: I've found that by gsmAccess(true), setting debug, that it sends AT+UPSV=3, which sets the power saving mode to 3, which is ON, and its (page 532 of ublox manual) --
3: power saving is controlled by UART DTR line:
o If the DTR line state is set to OFF, the power saving mode is allowed
o If the DTR line state is set to ON, the module shall exit from power saving (mode =3) is allowed regardless the flow control setting on the UART interface. In particular, the HW flow control can be set on UART during this mode.

With (mode =3) the DTE can start sending data to the module without risk of data loss after having asserted the UART DTR line (DTR line set to ON state)

So, I have to set the DTR line to ON state. Nice, but How to do that?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.