My code stops in void loop()

Hello,
I have a little problem with my code. If someone with a sim800/900 module and a gps, can test my code and see what is wrong.
What it dose: It works just fine when receiving the “Ok”, “Test”, “Voltage” commands, and if i keep sending this sms’s they will always work. But when i send the “Where” sms, the arduino dose that and print that “text” string just fine, but it stops taking any other sms’s. It’s like the software serial for gsm dosen’t receive anything anymore. If i call the reset function, arduino resets just fine and it works, but i don’t want to keep reseting it( not sure if it’s safe for gsm module).
Hope you guy understand what i’m trying to say and can help. Thanks in advance.

Reset function i used:

void(*resetFunc) (void) = 0;  //reset function

My code:

#include<SoftwareSerial.h>
#include <TinyGPS.h>
SoftwareSerial sim900 (3, 2);
SoftwareSerial GPS (5, 6);

TinyGPS gps;
const unsigned int MAX_INPUT = 165;
static unsigned int input_pos = 0;
int SMS_location_number;
int voltage;

float flat, flon, altitude, speed;
String timestamp = "0";

String input=""; // Declare an Empty String Variable
String input_trimmed="";// a variable to store the trimmed string
String substring=""; // a variable to store the substring "PHONE NUMBER"
String txtMessage="";// a variable to store the txtMessage "The inComing Text Message"
int length_before_trim = 0, length_after_trim = 0, length_substring=0; // 3 variables for storing the string lengths

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

void(*resetFunc) (void) = 0;  //reset function

void setup() {
  Serial.begin(115200);
  sim900.begin(4800);
  Serial.print("Start");
  delay(8000);
  config_sim900();
  Serial.println("ready");
  
  
}

void loop() {
  read_sim900();
  
  
}


void config_sim900() {
  sim900.println("AT+CMGF=1");
  delay(500);
  //sim900.println("AT+CNMI=2,1,0,0,1"); //save SMS to sim
  sim900.println("AT+CNMI=2,2,0,0,0"); // Print SMS to serial
  delay(500);
  sim900.println("AT+CMGD=1,4"); //Delete all SMS
  delay(500);
  sim900.println("AT+CHFA=1"); //Set audio to external 0=hedphones 1=external
  delay(500);
  sim900.println("AT+CLIP=1");
  delay(500);
  //sim900.print("AT+CBC");
}


void read_sim900() {
  static char input_line [MAX_INPUT];

  if (sim900.available() > 0) {
    Serial.println("SIM900 OK!");
//    digitalWrite(10, HIGH);
//    delay(1500);
//    digitalWrite(10, LOW);
    while (sim900.available () > 0) {
      char inByte = sim900.read();

      switch (inByte) {

      case '\n':   // end of text
        input_line [input_pos] = 0;  // terminating null byte

        // terminator reached! process input_line here ...
        process_data (input_line);

        // reset buffer for next time
        input_pos = 0;
        break;

      case '\r':   // discard carriage return
        break;

      default:
        // keep adding if not full ... allow for terminating null byte
        if (input_pos < (MAX_INPUT - 1))
          input_line [input_pos++] = inByte;
        break;

      }  // end of switch
    }  // end of while incoming data
  }  // end of if incoming data
}

void process_data (char * data) {
  Serial.print("***Data:");
  Serial.println(data);
  
//  if(strstr(data, "+CMTI:")) {   // An SMS has arrived
//    char* copy = data + 12;      // Read from position 12 until a non ASCII number to get the SMS location
//    SMS_location_number = (byte) atoi(copy);  // Convert the ASCII number to an int
//    sim900.print("AT+CMGR=");
//    sim900.println(SMS_location_number);  // Print the SMS in Serial Monitor   
//  }
  
  if(strstr(data, "+CLIP:")) {
    input = "";
    delay(100);
    input += data;
    input_trimmed = input;
    substring = input_trimmed.substring(8, 20); // get the callers number.
    //substring = input_trimmed.substring(10, 21); // 11 char number (cheap simcards);
    Serial.print("Number: ");
    Serial.println("+" + substring);
    delay(500);
    sim900.println("ATA");
    delay(10000);
    sim900.println("ATH");
  }
  
//  if(strstr(data, "+CMGR:")) {
//    input = "";
//    delay(100);
//    input += data;
//    input_trimmed = input;
//    substring = input_trimmed.substring(22, 34); // get the callers number.
//    Serial.print("Number: ");
//    Serial.println(substring);
//  }
  
  if(strstr(data, "Test")) {
    Serial.println("Sending SMS.");
    sim900.print("AT+CMGS= \"+");
    delay(100);
    sim900.print(substring);
    delay(100);
    sim900.println("\"");
    delay(100);
    sim900.print("test");
    delay(100);
    sim900.println((char)26);
    delay(100);
  }
  
  if(strstr(data, "Voltage")) {
    delay(100);
    sim900.println("AT+CBC");
    delay(100);
  }
  
  if(strstr(data, "+CBC:")) {   
    char* volt = data + 8;
    voltage = (byte) atoi(volt);
    Serial.print("Voltage: ");
    Serial.println(voltage);
    Serial.println("Sending SMS.");
    sim900.print("AT+CMGS= \"+");
    delay(100);
    sim900.print(substring);
    delay(100);
    sim900.println("\"");
    delay(100);
    sim900.print(voltage);
    delay(100);
    sim900.println((char)26);
    delay(100);     
  }
  
  if(strstr(data, "+CMT:")) { // get the phone number if the sms is displayed on Serial, not saved on SIM.
    input = "";
    delay(100);
    input += data;
    input_trimmed = input;
    substring = input_trimmed.substring(8, 20); // get the callers number.
//    Serial.print("Number: ");
//    Serial.println(substring);
  }
  
  if(strstr(data, "Ok")) {  
    Serial.println("Tel:+" + substring);
  }
  
  if(strstr(data, "Send")) {
    Serial.println("Sending SMS.");
    sim900.print("AT+CMGS= \"+");
    delay(100);
    sim900.print(substring);
    delay(100);
    sim900.println("\"");
    delay(100);
    sim900.print("test");
    delay(100);
    sim900.println((char)26);
    delay(100);
  }
  
  if(strstr(data, "Balance")) {
    sim900.println("ATD*101#;");
  }
  
  if(strstr(data, "Where")) {
    gps_sms();
    Serial.println("Where"); //Arduino stops here
    read_sim900();
    sim900.println("ATI"); //This line dosen't show the sim800 version
    Serial.println(freeRam()); //This line works
    //resetFunc();
  }
}

void gps_sms() {
  Serial.println("Start");
  GPS.begin(9600);
  delay(100);
  GPS.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
  delay(500);
  bool newData = false;
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (GPS.available()) {
      char c = GPS.read();
      if (gps.encode(c))
        newData = true;
    }
  }
  if (newData) 
  {
    Serial.println("FIX!");
    gps.f_get_position(&flat, &flon);
    speed = gps.f_speed_kmph();
    altitude = gps.f_altitude();
    
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
    
    
    timestamp = String("");
    timestamp += hour + 1 ;
    timestamp += ":";
    if (minute<10)
    {
    timestamp += "0";
    timestamp += minute;
    }
    else if (minute>=10)
    {
    timestamp += minute;
    }
    Send();
  }
}
  void Send() {
    String text = String();
    text += "Full SMS -  ";
    text += " Altitude: ";
    text += floatToString(altitude, 2);
    text += " Speed: ";
    text += floatToString(speed, 2);
    text += " Time(GMT + 2): ";
    text += timestamp;
    text += " Map: http://maps.google.com/?q=";
    text += floatToString(flat, 8);
    text += ",";
    text += floatToString(flon, 8);
    
    Serial.println(text);
    Serial.println(freeRam()); //this line works
    GPS.flush();
    GPS.end();
  }

String floatToString(double number, uint8_t digits) {
  String resultString = "";
  // Handle negative numbers
  if (number < 0.0) {
    resultString += "-";
    number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i = 0; i < digits; ++i)
    rounding /= 10.0;

  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  resultString += int_part;

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    resultString += ".";

  // Extract digits from the remainder one at a time
  while (digits-- > 0) {
    remainder *= 10.0;
    int toPrint = int(remainder);
    resultString += toPrint;
    remainder -= toPrint;
  }
  return resultString;
}

final.ino (7.6 KB)

http://arduino.cc/en/Reference/SoftwareSerial "Limitations The library has the following known limitations: If using multiple software serial ports, only one can receive data at a time."

You could use an Arduino Leonardo to get a spare hardware serial port (Serial1).

I'll try to swap software serial on gps with hardware serial. is it ok to use software serial for debuging?

It is working with the GPS on hardware serial and debug on Software Serial. but i have to send an sms two times, because there are some weird characters on serial monitor.

Serial Monitor with weird characters:

***Data:Š+ƒMT: "+436604178904","","14/12/16,21:16:26+04"
***Data:Where
Start
FIX!
Full SMS -   Altitude: 1000000.00 Speed: 0.83 Time(GMT + 2): 21:16 Map: http://maps.google.com/?q=48.25056838,14.29034996
514
Where
712
SIM900 OK!
SIM900 OK!
***Data:Š+ÃMT: "+436604178904","","14/12/16,21:16:37+04"
***Data:Ok
Tel:++43660417890
SIM900 OK!
SIM900 OK!
***Data:Š+CMT: "+436604178904","","14/12/16,21:16:46+04"ŠW¨ere
SIM900 OK!
SIM900 OK!
***Data:Š+ÃMT: "+436604178904","","14/12/16,21:17:02+04"
***Data:Ok
Tel:++43660417890
SIM900 OK!
SIM900 OK!
***Data:Š+CMT: "+436604178904","","14/12/16,21:17:13+04"ŠW¨ere
SIM900 OK!
SIM900 OK!
***Data:Š+CMT: "+436604178904","","14/12/16,21:17:22+04"
***Data:Where
Start
FIX!
Full SMS -   Altitude: 1000000.00 Speed: 1.17 Time(GMT + 2): 21:17 Map: http://maps.google.com/?q=48.25053024,14.29028034
514
Where
712

So, the problem is here:

***Data:Š+CMT: "+436604178904","","14/12/16,21:16:46+04"ŠW¨ere

and in some lines it dosen’t show “+CMT:” it shows like this:

***Data:Š+ÃMT: "+436604178904","","14/12/16,21:17:02+04"
***Data:Ok
Tel:++43660417890

Thanks.

final_hard.ino (7.62 KB)

I think Serial.println("+" + substring); has a problem.

If you think what the default value for substring is and then ADD it to a constant char pointer, you may understand what I mean.

(you'll note I said ADD not concatenate)

Thanks for the answer, that's not the problem. I'm only using it that way because i don't know how this ** character works on **serial.println("Sending SMS."); ** sim900.print("AT+CMGS= \"+");** ** delay(100);** ** sim900.print(substring);**, so thats why i trimmed that string just after the +. Anyway, i kept changing the baundrate and it only made it worse. I'm really stuck now.

sim900.print("AT+CMGS= \"+"); Is simply embedding a "+" symbol within a string. That's not what's happening in the example I gave above.

I can only get rid of Serial.println("+" + substring); and change it to Serial.println(substring); if i can make something like,

that substring is the telephone number+43XXXXXXXXXX
and i need to:
sim900.print("AT+CMGS=substrig);
    sim900.println("\"");
    delay(100);
    sim900.print("test");
    delay(100);
    sim900.println((char)26);
    delay(100);

i don't get it why two commas at the end sim900.println("\"");. But thats not the problem. I'm searching now for a way to increase the buffer size on software serial. maybe that will help to get rid of weir characters.

You can change Serial.println("+" + substring); to two lines consisting of Serial.print("+"); Serial.println(substring);

This would sort out the problem I'M talking about. Which has nothing to do with escaping characters within a string.

the backslash inside a string tells the compiler to take the following character as a character within a string, instead of what it would do otherwise.

ie if you want to include an inverted comma within a string you put a backslash before it such as Serial.println("LOOK \"This is inside inverted commas\" end of quote");

Without the backslash, the inverted comma following the LOOK would mark the end of the string that you're trying to print. With the backslash the inverted comma becomes a character WITHIN the string.

Thanks for that, I get it now. i did change the buffer size on RX from 64 to 128, didn't help. I didn't have this problem with the GPS and the sim800 on Software Serial and keep the Hardware Serial for debug. I think it must be something with the baundrate or timing. Thanks again for explaining that.

I can't belive it works just perfect on my leonardo. Now i have to redesign everything on my board to use it with atmega32u4, and i need to find a way to lower the crystal to 8mhz because i'm using it with LiPo battery. Here is my board with atmega328p microcontroller. https://oshpark.com/shared_projects/IYA2Qf4a Any suggestions for a bootloader for atmega32u4 8mhz 3.3V?

It works perfect with ATmega328p, no need to move to ATmega32u4. After a lot of debugging and research i fund the solution all i had to do is write si900.listen() at the beging of void read_sim900()