Freeze during put request

Hi,

I am using mkrGSM1400 for a remote sensing project.

The board is using GPRS to send periodically data to my server.

I am sending data with a PUT request incorporating a simple JSON

It is working fine BUT : randomly, the data stops being sent. This occurs after a few tens to a few thousand request.

The console debug shows that the freeze occurs in the beginning or at the middle of the PUT request. (See attache picture)

Does anybody face the same problem ?

Note : I am using a soracom IOT simcard. This simcard connects to the best carrier available at a given point and time

Hi @heligone,

Could you please share a sketch that can reproduce the issue?

Do you have a lipo battery connected to the board?

Hello everybody,

I'm working with Heligone and I just produce a example :

Of course we both use the 2000mA bat.

Thanks for any help

thanks for your reply @sandeepmistry :slight_smile:

For information, here is another sketch with a custom PUT Implementation, without using ArduinoHttpClient library, as was done in the code linked in the previous message from my friend @Marcussacapuces91.

It seems that this custom implementation of PUT is working better, nevertheless, it is still freezing after a random number of request...

NOTE : I am using a LIPO 18650 1S3P 7800mAh

/* adapted from  M. sibert May 2018 */

#  define DEBUG(x) do { Serial.print(x); } while(0)

#include <MKRGSM.h> 

#define PIN_CODE "0000"
#define APN_NAME "soracom.io"
#define APN_USERNAME "sora"
#define APN_PASSWORD "sora"

const String GPRS_APN(F(APN_NAME));
const String GPRS_LOGIN(F(APN_USERNAME));
const String GPRS_PASSWORD(F(APN_PASSWORD));


GSM gsm;
GPRS gprs;
GSMClient gprsClient;

bool put( String path,  String body)  {
    DEBUG("PUT "); DEBUG(path); DEBUG('\n');
    
    GSMClient client;
    String serverName = "httpbin.org";
    if (!client.connect(serverName.c_str(), 80)) {
      Serial.println(F("Erreur de connexion"));
      return false;
    }
    
    client.print(F("PUT "));   client.print(path);   client.println(F(" HTTP/1.0"));
    client.print(F("Host: ")); client.println(serverName.c_str());
    client.println(F("Content-Type: application/json"));
    client.print(F("Content-Length: ")); client.println(body.length());
    client.println(F("Connection: close"));
    client.println();

    String t = body;
    while(t.length() > 0) {
      const unsigned m = (t.length() >= 100 ? 100 : t.length());
      client.print(t.substring(0, m));
      t = t.substring(m);
    }

    String s;
    const unsigned long start = millis();
    while ((client.available() || client.connected()) && (millis() - start) < 30000) {
      if (client.available() > 0) {
        const int c = client.read();
        if (c != -1) s += char(c);
      }
    }
    Serial.println(s);
    return true;
  }

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

  if (GSM_READY != gsm.begin(PIN_CODE)) {
    Serial.println("No GSM conection!");
  }

  if (GPRS_READY != gprs.attachGPRS(GPRS_APN.c_str(), GPRS_LOGIN.c_str(), GPRS_PASSWORD.c_str())) {
    Serial.println("No GPRS connection!");
  }

}


void loop() {
  Serial.println("Making PUT request");

  const String Path = "/put";
  const String putData = "{ \"name\": \"light\", \"age\": 46 }";

  put(Path, putData);
  Serial.println("Wait five seconds");
  delay(5000);
}

Hello,
I have some problems.
For me this is wrong in the design of MKRGSM1400.
at the moment, developers advise to connect the battery. But this does not help, the MKRGSM1400 stops working and needs to be restarted.
We can not find a solution, as in this case, stop the loop and restart the MKRGSM1400 automatically.
For Arduino UNO we use #include <avr / wdt.h>, unfortunately it does not work in MKRGSM1400.

Hello.

I have the same problems. The device works fine during a few days, but after that fails. I have beed testing different power options, like USB cable, with Vin and a Lipo battery of 2500 mAh connected all time, but the result is always the same. I have been thinking in log the events in a SD card to view more details... I hope the developers give us some indication to resolve that.

Thanks.

Hi to all, @heligone i have tested the sketch of @Marcussacapuces91, and and reproduced the issue, now i take some modifications like introducing a timeout and impose a client.close() and a client.flush() after the put request, the code that i use is the following:

/*
 Simple PUT client for ArduinoHttpClient library
 Connects to server once every five seconds, sends a PUT request
 and a request body

 created 14 Feb 2016
 by Tom Igoe

 update by M. Sibert May 2018

 this example is in the public domain
*/
#include <MKRGSM.h>
#include <ArduinoHttpClient.h>
#include "arduino_secrets.h"

const String serverName(("httpbin.org"));//F("httpbin.org"));
const unsigned serverPort = 80;
const String servicePath(("/put"));//F("/put"));

const String GPRS_APN((APN_NAME));//F(APN_NAME));
const String GPRS_LOGIN((APN_USERNAME));//F(APN_USERNAME));
const String GPRS_PASSWORD((APN_PASSWORD));//F(APN_PASSWORD));

unsigned long initTime = millis();

GSM gsm(true);
GPRS gprs;
GSMClient gprsClient;

HttpClient client = HttpClient(gprsClient, serverName, serverPort);

const String contentType = "application/json";
const String putData = "{ \"name\": \"light\", \"age\": 46 }";


void setup() {
 Serial.begin(9600);
 MODEM.begin();
 boolean connected = false;
 while (!connected) {
   if ((gsm.begin(PIN_CODE) == GSM_READY) &&
       (gprs.attachGPRS(GPRS_APN.c_str(), GPRS_LOGIN.c_str(), GPRS_PASSWORD.c_str()) == GPRS_READY)) {
     connected = true;
   } else {
     Serial.println("Not connected");
     delay(1000);
   }
 }
 Serial.println("Connected");
}
unsigned long int count = 0;
void loop() {

 Serial.println("Making PUT request");
 int ret = client.put(servicePath.c_str(), contentType, putData);
 if (ret < 0) {
   client.flush();
   client.stop();
   return;
 }
 unsigned long looptime = millis();
 while (client.available() <= 0 || millis() - looptime < 5000) {
 }

 // read the status code and body of the response
 const int statusCode = client.responseStatusCode();
 const String response = client.responseBody();
 if (statusCode != 200) {
   client.flush();
   client.stop();
 } else {
   Serial.print("Status code: ");
   Serial.println(statusCode);
   Serial.print("Response: ");
   Serial.println(response);
   Serial.print(count);
   count++;
 }
 Serial.print("battery charge: ");
 Serial.println(String(analogRead(ADC_BATTERY)));

 unsigned long start = millis();
 Serial.print("Time ");
 Serial.println((millis() - initTime) / 1000);
 while (client.connected())
 {

   Serial.println("Connected!!!");
   delay(100);
   if (millis() - start > 5000)
   {
     client.flush();
     client.stop();
   }
 }
}

In my test it run for 3 hours and put around 1000 of request, could you try and let me now if works?, while i proceed to test it more and more, another things could you share the log of the debug mode?

Thank you Riccardo_Rizzo ::slight_smile:

We managed to find a workaround using tinyGSM libray.

We laso needed to manually implement a reconnection if the GPRS goes down in between 2 connections.

Your proposition using mkrgsm library looks good and I will test ASAP and let you know,

Best regards

This known issue may be relevant:

Basically there is an issue that allows the MKRGSM library to get out of sync and lock up waiting dor a reply to a command.

Thank you all for advice.

Unfortunately, none of the solutions tried is working :

  • use of tinyGSM resulted in 5 freeze during a 2 mont test in a remote location

  • Riccardo_Rizzo : I have tried your code but it still freeze if I emulate a network glitch by removing and then putting pack the antenna (see attached pic)

  • I have tried code from SORACOM team
    GitHub - alexissusset/soracom-mkrgsm1400: Soracom Air and Harvest services with Arduino MKR GSM 1400 project example
    --> freeze after few iteration

  • I have tried code form francmunoz
    GitHub - FrancMunoz/MKRGSM
    who forked mkrgsm library to patch delay issue with SARA and programmed an asynchronous connection exemple. The board does not freeze anymore , BUT sometimes gsm.begin() gets stuck and the board is unable to reconnect to GSM (even though other functionnalities in the loop are still running)

It is unfortunate that an arduino board necessitates advanced low level programming skill to establish a simple GPRS connection without a glitch ...

freeze
froze
frozen ...

Is there any high level way to introduce a function in your code that monitors for timeout's or errors and if a function doesn't complete within x number of seconds then it resets the module?

Interested to help in any further testing you might be doing too.

Hi smgs,

Thanks for your interest.

I am currently diving deeper into libraries up to AT commands

Currently, even a simple test sketch like GSMScanNetwork is not working (From MKRGSM Lib, see below)

I have tried 2 boards, i am using a soracom iot simcard AND i have tried several loaded lipo batteries.

I have activated the AT debug option line 26, passing the TRUE parameter to the gsmAccess object constructor : GSM gsmAccess(true);

It gets stuck with console showing :

...
AT+CREG?

+CREG: 0,0

OK
AT+CREG?

+CREG: 0,0

OK
AT+CREG?

+CREG: 0,0

OK

If the board gets no signal, or if there is a problem with AT+CREG?, there should be time out and the loop should continue...AM I WRONG ?

// libraries
#include <MKRGSM.h>

//#include "arduino_secrets.h"
// Please enter your sensitive data in the Secret tab or arduino_secrets.h
// PIN Number
const char PINNUMBER[] = "";

// initialize the library instance
GSM gsmAccess(true); // include a 'true' parameter to enable debugging
GSMScanner scannerNetworks;
GSMModem modemTest;

// Save data variables
String IMEI = "";

// serial monitor result messages
String errortext = "ERROR";

void setup() {
// initialize serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

MODEM.debug();

Serial.println("GSM networks scanner");
scannerNetworks.begin();

// connection state
boolean connected = false;

// Start GSM shield
// If your SIM has PIN, pass it as a parameter of begin() in quotes
while (!connected) {
if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
connected = true;
} else {
Serial.println("Not connected");
delay(1000);
}
}

// get modem parameters
// IMEI, modem unique identifier
Serial.print("Modem IMEI: ");
IMEI = modemTest.getIMEI();
IMEI.replace("\n", "");
if (IMEI != NULL) {
Serial.println(IMEI);
}
}

void loop() {
// scan for existing networks, displays a list of networks
Serial.println("Scanning available networks. May take some seconds.");
Serial.println(scannerNetworks.readNetworks());

// currently connected carrier
Serial.print("Current carrier: ");
Serial.println(scannerNetworks.getCurrentCarrier());

// returns strength and ber
// signal strength in 0-31 scale. 31 means power > 51dBm
// BER is the Bit Error Rate. 0-7 scale. 99=not detectable
Serial.print("Signal Strength: ");
Serial.print(scannerNetworks.getSignalStrength());
Serial.println(" [0-31]");

}

Hi Heligone

I uploaded the GSM scan example from the Examples > MKRGSM > tools > GsmScanNetworks
out put is included below, I've tagged it with the code format to make it clearer and easier to read

GSM networks scanner
Modem IMEI: 111000012345670
Scanning available networks. May take some seconds.

Current carrier: YES OPTUS
Signal Strength: 18 [0-31]
Scanning available networks. May take some seconds.
> Optus AU
> vodafone AU

Current carrier: YES OPTUS
Signal Strength: 18 [0-31]
Scanning available networks. May take some seconds.
> Optus AU
> Telstra Mobile
> vodafone AU

Current carrier: YES OPTUS
Signal Strength: 18 [0-31]
Scanning available networks. May take some seconds.

So not sure whats happening with yours, does your SIM card have a PIN number?

You have an Aerial plugged in too right?

I suggest you load up the SerialGSMPassthrough sketch from the examples and enter "AT" which should be followed by the prompt returning with OK. If that works then try the "AT+CIND?"

which will return a series of values to indicate your battery status, sim card status etc etc.

AT+CIND=?

+CIND: ("battchg",(0-5)),("signal",(0-5)),("service",(0-1)),("sounder",(0-1)),("message",(0-1)),("call",(0-1)),("roam",(0-1)),("smsfull",(0-1)),("gprs",(0-2)),("callsetup",(0-3)),("callheld",(0-1)),("simind",(0-2))

OK
AT+CIND?

+CIND: 5,3,1,0,0,0,0,0,2,0,0,1

OK

Further information available in the u-blox AT command manual.

https://www.u-blox.com/sites/default/files/u-blox-CEL_ATCommands_(UBX-13002752).pdf

you could also make your own sketch and send this command rather than using the pass through option, whatever works for you.

Thank you for your interest @smgs :slight_smile:

I am using a soracom IOT multioperator Simcard, and yes I am using an aerial and yes I know I can tag code BUT there is a BUG in the interface here : depending on the code you want to post, some part of it might not be included in the code box.

Even though the battery had a voltage >4V, I changed it with anew one and now AT+CREG is not freezing.

Here is the return for "AT+CIND?"

AT

OK
AT+CIND?

+CIND: 5,2,1,0,0,0,1,0,2,0,0,1

OK

Also the gsm scan :

Scanning available networks. May take some seconds.
AT+COPS=?

+COPS: (2,"F SFR","SFR","20810",2),(1,"Free","Free","20815",2),(1,"F-Bouygues Telecom","BYTEL","20820",2),(1,"Orange F","Orange","20801",2),(2,"F SFR","SFR","20810",0),(1,"Orange F","Orange","20801",0),(1,"F-Bouygues Telecom","BYTEL","20820",0),,(0-6),(0-2)

OK
> F SFR
> Free
> F-Bouygues Telecom
> Orange F
> F SFR
> Orange F
> F-Bouygues Telecom

Current carrier: AT+COPS?

+COPS: 0,0,"F SFR",2

OK
F SFR
Signal Strength: AT+CSQ

+CSQ: 16,3

Here are my views concerning this infamous AT+CREG? freeze.

I have several battery packs LI-ION 18650 1S3P, 3.7V 7800mAh.

I check the battery voltage before use.

But I have noticed that even if the battery voltage is correct, which means >4V, if the battery has not been charged for sometimes, the freeze can occur.

This does not happen with a new battery or a just recharged battery.

I understand that the board needs to draw much current when establishing the connection, and that requires a plugged in battery : USB power or solar power is not enough.

BUT what I dont understand is : If there is no battery connected, or if the battery cannot furnish enough current, the board should not freeze during the initial AT+CREG? loop.

Indeed, for a remote and autonomous IOT project, requiring periodic reconnexion to GSM network, it can always happen that the battery has become a bit weak.

In that case, the freeze will occur at GSM reconnexion and the whole board will freeze and need a manual or watchdog reset.

Maybe this can be adressed progammatically in the gsm.begin() or other parts pof the library

If it is a hardware limitation of SARA chip : time to look for another board ?

concerning AT+CREG? freeze at GSM reconnection please check also :

https://forum.arduino.cc/index.php?topic=565177.0

Hi @heligone, i have modified the sketch proposed before:

  • Now it is able to retry the connection when the antenna disconnect or loose signal; consider that my code actually (in the sketch) don't have timeout or counter for count the number of re-connection, it try to reconnect forever until when the modem return registered status, you could manage this simply adding in the loop() a counter and choose to do nothing or what you need;
  • When you disconnect the antenna it try to open a new socket, if not possible it return on the sketch, the time required for this action seems long but each time that i have tried to disconnect the antenna, it always was able to:
  1. follow to run and restart to communicate with the server if i reconnect the antenna;
  2. goes in the else condition of if (gsm.isAccessAlive()) in the main loop;

In the sketch that i propose following i have added some comments, if you look in the loop all the action is subordinated to if (gsm.isAccessAlive()) this check the CREG value and if it is different from a value that represent the registered status to the network it return false, in this way if +CREG=0 case happen when you are in the main loop it allow you to impose your condition in the main sketch, consider that the modem manage automatically the value of CREG, then could you try the code from your side and let me know if work?

/*
  Simple PUT client for ArduinoHttpClient library
  Connects to server once every five seconds, sends a PUT request
  and a request body

  created 14 Feb 2016
  by Tom Igoe

  update by M. Sibert May 2018

  this example is in the public domain
*/

#include <MKRGSM.h>
#include <ArduinoHttpClient.h>
#include "arduino_secrets.h"



const String serverName(("httpbin.org"));
const unsigned serverPort = 80;
const String servicePath(("/put"));

const String GPRS_APN((APN_NAME));
const String GPRS_LOGIN((APN_USERNAME));
const String GPRS_PASSWORD((APN_PASSWORD));

unsigned long initTime = millis();

GSM gsm(true);
GPRS gprs;
GSMClient gprsClient;

HttpClient client = HttpClient(gprsClient, serverName, serverPort);

const String contentType = "application/json";
const String putData = "{ \"name\": \"light\", \"age\": 46 }";
unsigned long int count = 0;

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

  MODEM.begin();
  boolean connected = false;
  while (!connected) {
    if ((gsm.begin(PIN_CODE) == GSM_READY) &&
        (gprs.attachGPRS(GPRS_APN.c_str(), GPRS_LOGIN.c_str(), GPRS_PASSWORD.c_str()) == GPRS_READY)) {
      connected = true;
    } else {
      Serial.println("Not connected");
      delay(1000);
    }
  }
  Serial.println("Connected");
}

void loop() {
  
  /* Here is checked if the connection is lost, simply check the CREG status
     there you can also count the tentative number until when you could stop to reconect and do other
     you could do somthing like this also in the setup() imposing some condition in the line:45 in the "while (!connected)"
  */
  if (gsm.isAccessAlive()) {

    Serial.println("Making PUT request");
    int ret = client.put(servicePath.c_str(), contentType, putData);
    if (ret < 0) {
      client.flush();
      client.stop();
      return;
    }
    unsigned long looptime = millis();
    /*
      changing the condition here the sketch don't freeze when the connection is lost and the antenna is detached 
    */
    while (client.available() <= 0 && millis() - looptime < 5000) {
    }

    // read the status code and body of the response
    const int statusCode = client.responseStatusCode();
    const String response = client.responseBody();
    if (statusCode != 200) {
      client.flush();
      client.stop();
    } else {
      Serial.print("Status code: ");
      Serial.println(statusCode);
      Serial.print("Response: ");
      Serial.println(response);
      Serial.print(count);
      count++;
    }

    unsigned long start = millis();
    Serial.print("Time ");
    Serial.println((millis() - initTime) / 1000);
    while (client.connected())
    {

      Serial.println("Connected!!!");
      delay(100);
      if (millis() - start > 5000)
      {
        client.flush();
        client.stop();
      }
    }
  } else {
    /*
      here you can implement all the actions that could be done if the connection is lost 
    */
    Serial.println("not connected, loop:sketch "); 
    delay(1000);
  }

}

in my actual test, it run from 4 days, i have disconnected random the antenna and each time that i have reconnected, it was able to establish again the connection with the server, all the problem was managed from sketch, be sure to have the last library version, the only condition that i have change is that in the MKRGSM library in file Modem.cpp in the last line i change the baudrate to 115200 in my test, soon i'll report the results of a long run test with the highest speed possible.