Device get stuck after ~ 10-15 min , can it be becuase of ram ?

Hello ,
I’m working with SIM808 zero
simple code that read GPS and send it to my server
everything is working great for 10-15 min then it’s semms that the code get stuck
the device is still connected to the internet , still get GPS (beacuse of the leds - I can tell it’s working)
but it’s stuck
maybe someone will see something I’m missing?

#include<stdio.h>
#include<string.h>

#define DEBUG true

int POWER_KEY = 9;
int LED6 = 6;

bool SIM808_ON = false;

String answer = "";
int answer_size = 0;
String Rssi = "";
String CIPSEND = "";
String BootCIPSEND = "";
String SIM = "";
String IMEI = "";
String SIMNumber = "";
String BootMSG = "";
int BootMSG_size = 0;
String UnitName = "Device2";
void setup()
{
  pinMode(LED6, OUTPUT);
  pinMode(POWER_KEY, OUTPUT);
  //********Turn on SIM808 when power up*********
  digitalWrite(LED6, HIGH);
  digitalWrite(POWER_KEY, HIGH);
  delay(1000);
  digitalWrite(POWER_KEY, LOW);
  digitalWrite(LED6, LOW);

  SerialUSB.begin(115200);
  delay(2000);


  SerialUSB.println("Start to run! V2_16.8.20 with LED ");
  Serial1.begin(115200);

  //********check open************
  sendData("AT", 1000, DEBUG);
  delay(1000);
  //******************************

  //********if SIM808 off, turn on it*********
  if (!SIM808_ON)
  {
    digitalWrite(POWER_KEY, LOW);
    delay(3000);
    digitalWrite(POWER_KEY, HIGH);
    SerialUSB.println("Turn on SIM808");
    delay(10000);
  }
  digitalWrite(LED6, HIGH);
  //GPS test

  sendData("AT+CGNSPWR=1", 1000, DEBUG);//GNSS POWER CONTROL ON
  delay(1000);
  sendData("AT+CGNSSEQ=\"RMC\"", 1000, DEBUG);//
  delay(1000);
  sendData("AT+CGNSURC=0", 1000, DEBUG);// printf to serial every 1 second
  delay(1000);
  sendData("AT+CFUN?", 1000, DEBUG);// printf to serial every 1 second

  SIMNumber = sendData("AT+CCID", 1000, DEBUG);//get SIM number
  delay(1000);

  sendData("AT+CSTT=internetg", 1000, DEBUG);// Setup APN uinternet - partner , internetg - cellcom
  delay(1000);
  sendData("AT+CGATT=1", 1000, DEBUG);// connected to the GPRS network
  delay(1000);
  sendData("AT+CIICR", 1000, DEBUG);// connected to the GPRS network
  delay(1000);
  sendData("AT+CIFSR", 1000, DEBUG);// Show IP address
  delay(1000);
  sendData("AT+CIPSTART=UDP,123.122.121.1,8888", 1000, DEBUG);//
  delay(1000);

  Rssi = sendData("AT+CSQ", 1000, DEBUG);// get signal RSSI
  int Rssi_Data_Start = Rssi.indexOf(':');
  Rssi = Rssi.substring(Rssi_Data_Start);
  int Rssi_Data_End = Rssi.indexOf('\r');
  Rssi = Rssi.substring(2, Rssi_Data_End);

  IMEI = sendData("AT+GSN", 1000, DEBUG);  //get IMEI Number
  int IMEI_Data_Start = IMEI.indexOf('\r');
  IMEI = IMEI.substring(IMEI_Data_Start);
  IMEI_Data_Start = IMEI.indexOf('\n');
  IMEI = IMEI.substring(IMEI_Data_Start);
  int IMEI_Data_End = IMEI.indexOf('\r');
  IMEI = IMEI.substring(1, IMEI_Data_End);


  int SIMNumber_Data_Start = SIMNumber.indexOf('\r');
  SIMNumber = SIMNumber.substring(SIMNumber_Data_Start);
  SIMNumber_Data_Start = SIMNumber.indexOf('\n');
  SIMNumber = SIMNumber.substring(SIMNumber_Data_Start);
  int SIMNumber_Data_End = SIMNumber.indexOf('\r');
  SIMNumber = SIMNumber.substring(1, SIMNumber_Data_End);

  BootMSG = (UnitName + "!" + IMEI + "!" + SIMNumber + "!" + Rssi);
  BootMSG_size = BootMSG.length();
  BootCIPSEND = ("AT+CIPSEND=" + String( BootMSG_size));

  SerialUSB.println("The BootMSG is going to be");
  SerialUSB.println(BootMSG);
  SerialUSB.println("the size is");
  SerialUSB.println(BootMSG_size);
  SerialUSB.println("*************");

  sendData(BootCIPSEND, 1000, DEBUG);//
  delay(1000);
  // sendData("ON!\n\r", 1000, DEBUG);//HTTP POST   //response: +HTTPACTION: 1,200,1
  sendData(BootMSG, 1000, DEBUG);
  delay(1000);
  sendData("AT+CIPCLOSE", 1000, DEBUG);//
  delay(1000);
  // sendData("AT+CGNSINF", 1000, DEBUG);//
  // delay(1000);



}

void loop()
{

  answer = sendData("AT+CGNSINF", 1000, DEBUG);// get GPS data
  delay(1000);
  int GPS_Data_Start = answer.indexOf(':');
  answer = answer.substring(GPS_Data_Start);
  int GPS_Data_End = answer.indexOf('\r');
  answer = answer.substring(2, GPS_Data_End);

  Rssi = sendData("AT+CSQ", 1000, DEBUG);// get signal RSSI
  int Rssi_Data_Start = Rssi.indexOf(':');
  Rssi = Rssi.substring(Rssi_Data_Start);
  int Rssi_Data_End = Rssi.indexOf('\r');
  Rssi = Rssi.substring(2, Rssi_Data_End);

  answer = (UnitName + ',' + answer + Rssi);
  // answer = answer.substring(2);
  answer_size = answer.length();
  // answer = (answer + "\n\r");
  SerialUSB.println(F("the replay from the modem was - \n\r"));
  SerialUSB.println(answer);
  SerialUSB.println(F("the size is - \n\r"));
  SerialUSB.println(answer_size);
  SerialUSB.println("*************");
  sendData("AT+CIFSR", 1000, DEBUG); //just to be sure there is IP address - can remove after
  delay(500);
  CIPSEND = ("AT+CIPSEND=" + String(answer_size));
  // SerialUSB.println("size of msg is - " + CIPSEND);
  sendData("AT+CIPSTART=UDP,123.122.121.1,8888", 1000, DEBUG);//
  delay(500);
  sendData(CIPSEND, 1000, DEBUG);
  delay(500);
  sendData(answer, 1000, DEBUG);
  delay(500);
  sendData("AT+CIPCLOSE", 1000, DEBUG);
  //delay(1500);

}


String sendData(String command, const int timeout, boolean debug)
{
  String response = "";
  Serial1.println(command);

  String commandpre = getcommand_pref(command);
  //SerialUSB.println(commandpre);

  long int time = millis();
  while ( (time + timeout) > millis())
  {
    if (commandpre == "AT") {
      if (Serial1.find("OK")) {
        SIM808_ON = true;
        SerialUSB.println("SIM808 opened");
      }
    }
    
    while (Serial1.available())
    {
      String c = Serial1.readString();
      response += c;
    }
  }

  if (debug)
  {
    SerialUSB.println(response);
  }
  return response;
}


String getcommand_pref(String command) {

  String command_pref = "";
  char *cstr = new char[command.length() + 1];
  strcpy(cstr, command.c_str());
  char * token = strtok(cstr, "=");
  int i = 0;
  while (token != NULL) {
    //SerialUSB.print(token);
    //SerialUSB.println("  line" + (String)i);

    switch (i) {
      case 0:
        command_pref = token;
        break;

      default:
        break;
    }

    token = strtok(NULL, ",");
    i = i + 1;
  }

  if (command_pref == "")
    command_pref = command;

  return command_pref;
}

I notice that when it get stuck
it get stuck after it print this line

"AT+CIPSEND=99"

*** just to be clear , if I look at the serial monitor output it send many times 99 ,
*** also it get stuck when the number is 100 \ 98 \102
*** so I don’t think it have something to do with the value

maybe something in the flash \ RAM need to be clean?

Thanks ,

Your use of the String class may be the problem. See the Evils of Strings for more information.

What Arduino board are you using?

Maduino Zero SIM808

if not use the String class , what else I can do ?

save the answer as char string[];?

Thanks ,

david1234: Maduino Zero SIM808

if not use the String class , what else I can do ?

Thanks ,

You can use C strings, otherwise known as 'character arrays' instead. Another mistake people often make, is to do a lot of concatenation of strings that get sent to a sequential device like a file or a terminal.

Serial.print("hel"); Serial.println("lo");

is the same as

Serial.println("hello");

So you never need to do

String wasteOfTime = "hel" + "lo"; Serial.println(wasteOfTime);

can you explain more what I need to do? and I will try it ? beacuse the "sendData" function return a String and I have no idea what to do(this is not my function , got it from the wiki of them)

also - you think this may cause the problem , the big string I have created?

Did you read the evils of Strings page that I linked?

also - you think this may cause the problem , the big string I have created?

I do not know, but it is a possible cause that should be investigated. I have zero experience with that board so cannot be of much more help.

yes , I have read it , but couldn't understand what to do If the repaly from the function is string - what do I need to change ? this is what I asked

do I need to change the sendData function ? (which I didn't wrote?) or I can do something else ?

or can I use somehow the

free()

also is there any whay to check and see this is the problem ? that something in the memory management is wrong ?

Thanks ,

Get yourself a copy of the freemem or freememory function. It'll let you see if you have a memory leak. It's academic really though, your code uses String objects a lot so it's going to be leaking.

OK I have never used String objecty - so I didn't know it cause so much problems :-)

in order to save time - do you know where I can download the free memory lib?

It's not a library, just a function. Adafruit has one.

I don't know how to get it can you explain please ? I never had to use something I didn't find in the library

Thanks ,

One can make a String variable that does not fragment memory through proper use.

One can create String sString; In setup one can assign the string a spicific RAM buffer by doing sString.reserve(XX) where XX is the size of the buffer. The sString=""; clears the String Ram buffer. One can add a String to the cleared buffer by sString="new String stuff". If one wants to add " more String Stuff" one would use sString.concate(" more String Stuff"); See https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/. One can safely use Strings with a Uno if one does proper String management. In example, I have a Uno that uses String that's been running for 2.5+ years doing its thing day after day.

Strings its all about management, something one'll have to learn to do if one is going to use them.

Look here. Just copy their code snippet into your program and then call the function periodically to see how much space there is between the stack & the heap.

If it reduces over time, you have a leak.

Idahowalker this is the first time I use the String , so I didn't know it will casue so much problems .....

if I understand you correct 1. If I want\need to create a string it is best to give it size

sString.reserve(XX)

question : how do I know the size? is it the same as length()? meaning that if the max string.length() will be 100 , I need to setup string.reserve(100)? 2. in order to add data into string I will need to use sString.concate("+data2") ? then sString will be "string+data2" ?it's the same as (sString+"+"+data2)? but much better way to add? 3. after I finish with the sString in the loop , it will be best to clear it ? The sString=""; 4. to know how much RAM I have left , I need to use what wildbill say? the Freememory fuction ? that way I will know if I'm doing it correct ?

I'm asking in order to know and learn

Thanks,

david1234:
question : how do I know the size? is it the same as length()?
meaning that if the max string.length() will be 100 , I need to setup string.reserve(100)?
2. in order to add data into string I will need to use sString.concate("+data2") ?
then sString will be “string+data2” ?it’s the same as (sString+"+"+data2)? but much better way to add?
3. after I finish with the sString in the loop , it will be best to clear it ?
The sString="";
4. to know how much RAM I have left , I need to use what wildbill say? the Freememory fuction ?
that way I will know if I’m doing it correct ?

I’m asking in order to know and learn

Thanks,

  1. I, initially, do not use reserve and during operations print out the length of the string. I can then get an idea of how long the string reserve needs to be add 100 or so bytes and go from there.
  2. Yes.
  3. Yes.
  4. I do not know.

And I only answer so many questions, especially when one has the device sitting there in front of them and can try this cht out for themselves.

of course first to run the code 2-3 times to see the length before reserving space . from the last 4 days I know the size is no more then 102 chars when I print

answer.length();

the biggest resualt is

102

so this is the question - if I know the max size is 102 what do I need to reserve? 202?

Thanks,

If you know the absolute maximum size, reserve that much. Otherwise you are sort of saying you don't know the maximum.

david1234: of course first to run the code 2-3 times to see the length before reserving space . from the last 4 days I know the size is no more then 102 chars when I print

answer.length();

the biggest resualt is

102

so this is the question - if I know the max size is 102 what do I need to reserve? 202?

Thanks,

Go with your gut. If you believe the buffer will never ever get more then 102, then go for it but shrug.

I will try to reserve

I have start to use the FreeMemory function and I can see I have a leak after everyloop the value is getting low at least now I know what is the problem

now I have try to clear the string as suggested

 SerialUSB.println("*************");
  SerialUSB.println("Before cleaning :");
  SerialUSB.println(freeMemory());
  ///clear the memory
  answer = "";
  Rssi = "";
  FullUDP = "";
  CIPSEND = "";
  SerialUSB.println("*************");
  SerialUSB.println("After cleaning :");
  SerialUSB.println(freeMemory());

but the resualt is the same and after another loop it get lower

17:19:16.661 -> Before cleaning :
17:19:16.661 -> 14455
17:19:16.762 -> *************
17:19:16.762 -> After cleaning :
17:19:16.762 -> 14455
.
.
.
.
.
17:19:26.836 -> Before cleaning :
17:19:26.836 -> 14335
17:19:26.937 -> *************
17:19:26.937 -> After cleaning :
17:19:26.937 -> 14335

how could it be ? what else is missing

also when I try to use reserve I get an error

String answer;
answer.reserve(110);
Arduino: 1.8.13 (Windows 7), Board: "Arduino Zero (Native USB Port)"

SIM808_Working_SendUDP_WithLED.ino:12:1: error: 'answer' does not name a type

 answer.reserve(110);

 ^~~~~~

Before you fix the problem, you should identify the problem. Shotgun troubleshooting seldom is successful.

WildBill, in reply #12, links to a page that would help you find if the problem is, in fact, a memory leak. Did you try that?