Arduino + SIM7600 + neo M8N for GPS tracking

I am using arduino + sim7600 + neo M8N gps module to update GPS coordinates real time to a mysql database. I am able to update without any issues, however several times I dont get an update for a long time because I think I am not able to connect to the internet to perform the http request. Below is my code and hardware setup. Am I doing something wrong??

#include <SoftwareSerial.h>
#include <AltSoftSerial.h>
#define DEBUG true
SoftwareSerial mySerial(2, 3); // RX, TX
AltSoftSerial Serial1(8, 9); // RX, TX

uint8_t read_serial_byte, incomming_message[100], number_used_sats=0, fix_type;
uint8_t latitude_north, longiude_east ;
uint16_t message_counter;
int16_t gps_add_counter;
float l_lat_gps, l_lon_gps;
int32_t lat_gps_actual=0, lon_gps_actual=0;
uint8_t new_line_found, new_gps_data_available, new_gps_data_counter;
char UART1_rxBuffer[12]={0};


String latitude,longitude;
char gps[200];
char str[200];
char str2[30];
char str3[20];
char str4[20];
int datawritten=0;
long int time;



int sendData(char* command, const int timeout, boolean debug, char* expected_answer)
{
  char response[200];
  uint8_t x=0;
  uint8_t answer;
  
  memset(response,'\0',200);
  mySerial.println(command);
  
  long int time = millis();
  while ( (time + timeout) > millis())
  {
    while (mySerial.available())
    {
      response[x] = mySerial.read();
      x++;
    }
  }
  if (debug)
  {
    Serial.print(response);
  }
  if (strstr(response,expected_answer)==NULL) {
    answer=0;
  } else {
    answer=1;
  }
  return answer;
}


void startup() {
lat_gps_actual=0;
lon_gps_actual=0;
mySerial.begin(115200);  

time = millis();
while ( (time + 5000) > millis()) {
while (mySerial.available()) {
   Serial.print((char)mySerial.read());
}
}

mySerial.print("AT+IPR=9600\r\n");
time = millis();
while ( (time + 5000) > millis()) {
while (mySerial.available()) {
   Serial.print((char)mySerial.read());
}
}
mySerial.begin(9600);   
int error=1;
while (error==1) {
if (sendData("AT+CCID",5000,true,"OK")==1) {
  if(sendData("AT+CREG?",5000,true,"OK")==1) {
    
    if(sendData("AT+CGATT=1",5000,true,"OK")==1) {  
      if(sendData("AT+CGACT=1,1",5000,true,"OK")==1) {
        if(sendData("AT+CGDCONT=1,\"IP\",\"airtelgprs.com\"",5000,true,"OK")==1) {
          error=0;
        } else {
          error=1;
        }

      } else {
        error=1;
      }

    } else {
      error=1;
    }

  } else {
    error=1;
  }
  
} else {
  error=1;
}

 
}

}

void flu() {
  
long int time1 = millis();
Serial.println("Flushing gps");

while ((time1+1000)>millis()) {
  while (Serial1.available()) {
    char t = char(Serial1.read());
    //Serial.print(t);
  }
}
}


void powercycle() {
long int time1 = millis();
digitalWrite(4,LOW);
//delay(10000);
while ((time1+10000)>millis()) {
  while (Serial1.available()) {
    char t = char(Serial1.read());
    //Serial.print(t);
  }
}
long int time2=millis();
digitalWrite(4,HIGH);
while ((time2+15000)>millis()) {
  while (Serial1.available()) {
    char t = char(Serial1.read());
    //Serial.print(t);
  }
}

  
}
void setup() {
pinMode(4,OUTPUT);
powercycle();
Serial.begin(115200);
Serial1.begin(9600);
startup();
}

void loop() {
  Serial.println("Reading gps");
readgps();
if ((lat_gps_actual>0)&&(lon_gps_actual>0)&&(lon_gps_actual<90000000)) {

Serial.println(lat_gps_actual);
Serial.println(lon_gps_actual);


if (sendData("AT+HTTPINIT",5000,true,"OK")==1) {
        mySerial.print("AT+HTTPPARA=\"URL\"");
        mySerial.print(',');
        mySerial.print('"');
        mySerial.print("http://mywebsite/gps_update.php?");
        mySerial.print("Truck_ID=1&");
        mySerial.print("Latitude=");
        int val_int=(int)l_lat_gps;
        float val_float = (abs(l_lat_gps)-abs(val_int))*1000000;
        uint32_t val_fra = (uint32_t)val_float;
        char sz[20]={' '};
        sprintf(sz,"%d.%6ld",val_int,val_fra);
        mySerial.print(sz);
        mySerial.print("&");
        mySerial.print("Longitude=");
        memset(sz,'\0',20);
        val_int=(int)l_lon_gps;
        val_float = (abs(l_lon_gps)-abs(val_int))*1000000;
        val_fra = (uint32_t)val_float;
        sprintf(sz,"%d.%6ld",val_int,val_fra);
        mySerial.print(sz);
        mySerial.print('"');
        mySerial.print("\r\n\r\n");
        time = millis();
        char response2[200];
        uint8_t y=0;
        memset(response2,'\0',200);
        
        while ( (time + 10000) > millis()) {

        while (mySerial.available()) {
           response2[y]=(char)mySerial.read();
           y++;
        }
    }
    Serial.println(response2);
    if (strstr(response2,"OK")!=NULL) {
          
        sendData("AT+HTTPACTION=0",6000,true,"OK");
        //Serial.println("Reading Header");
        //sendData("AT+HTTPHEAD",20000,true,"OK");
        //Serial.println("Reading Response");
        //sendData("AT+HTTPREAD=0,500",6000,true,"OK");
        Serial.println("Terminating");
              if (sendData("AT+HTTPTERM",5000,true,"OK")==1) {
                Serial.println("database updated");
                lat_gps_actual=0;
                lon_gps_actual=0;
                powercycle();
                startup();
                flu();
              } else {
                powercycle();
                startup();
                flu();
              }
        
        

    
    } else {
      powercycle();
      startup();
      flu();
    }
  
} else {
  powercycle();
  startup();
  flu();
}



}
}



void readgps() {
  
while (Serial1.available()&& new_line_found==0) {
  UART1_rxBuffer[0]=char(Serial1.read());
  //char read_serial_byte = Serial1.read();                                                              //Load a new serial byte in the read_serial_byte variable.

  if (UART1_rxBuffer[0] == '$') {                                                                       //If the new byte equals a $ character.
      for (message_counter = 0; message_counter <= 99; message_counter ++) {                             //Clear the old data from the incomming buffer array.
        incomming_message[message_counter] = '-';                                                        //Write a - at every position.
      }
      message_counter = 0;                                                                               //Reset the message_counter variable because we want to start writing at the begin of the array.
    }
    else if (message_counter <= 99)message_counter ++;                                                   //If the received byte does not equal a $ character, increase the message_counter variable.
    incomming_message[message_counter] = UART1_rxBuffer[0];                                               //Write the new received byte to the new position in the incomming_message array.
    if (UART1_rxBuffer[0] == '*') new_line_found = 1;                                                     //Every NMEA line end with a *. If this character is detected the new_line_found variable is set to 1.
  }
  if (new_line_found==1) {
  new_line_found = 0; 
  /*
    if (incomming_message[4] == 'L' && incomming_message[5] == 'L' && incomming_message[7] == ',') {     //When there is no GPS fix or latitude/longitude information available.
      //HAL_GPIO_TogglePin (LD3_GPIO_Port, LD3_Pin);                                                       //Change the LED on the STM32 to indicate GPS reception.
      //Set some variables to 0 if no valid information is found by the GPS module. This is needed for GPS lost when flying.
      l_lat_gps = 0;
      l_lon_gps = 0;
      lat_gps_previous = 0;
      lon_gps_previous = 0;
      number_used_sats = 0;
    }
*/
  if (incomming_message[3] == 'R' && incomming_message[4] == 'M' && incomming_message[5] == 'C' && incomming_message[17] == 'A') {
      Serial.println ("Newline Found");
      for (int h=0;h<=99;h++) {
      Serial.print (char(incomming_message[h]));
      }
      Serial.println("");
      delay(100);
      //Serial.println(lat_gps_actual);
      lat_gps_actual = ((int)incomming_message[21] - 48) *  (long)10000000;                              //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[22] - 48) * (long)1000000;                               //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[24] - 48) * (long)100000;                                //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[25] - 48) * (long)10000;                                 //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[26] - 48) * (long)1000;                                  //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[27] - 48) * (long)100;                                   //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[28] - 48) * (long)10;                                    //Filter the minutes for the GGA line multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual /= (long)6;                                                                         //To convert the minutes to degrees we need to divide the minutes by 6.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[19] - 48) *  (long)100000000;                            //Add the degrees multiplied by 10.
      //Serial.println(lat_gps_actual);
      lat_gps_actual += ((int)incomming_message[20] - 48) *  (long)10000000;                             //Add the degrees multiplied by 10.
      lat_gps_actual /= 10;         
      //Serial.println(lat_gps_actual); 
      //Divide everything by 10.

      lon_gps_actual = ((int)incomming_message[35] - 48) *  (long)10000000;                              //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual += ((int)incomming_message[36] - 48) * (long)1000000;                               //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual += ((int)incomming_message[38] - 48) * (long)100000;                                //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual += ((int)incomming_message[39] - 48) * (long)10000;                                 //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual += ((int)incomming_message[40] - 48) * (long)1000;                                  //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual += ((int)incomming_message[41] - 48) * (long)100;                                   //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual += ((int)incomming_message[42] - 48) * (long)10;                                    //Filter the minutes for the GGA line multiplied by 10.
      lon_gps_actual /= (long)6;                                                                         //To convert the minutes to degrees we need to divide the minutes by 6.
      lon_gps_actual += ((int)incomming_message[32] - 48) * (long)1000000000;                            //Add the degrees multiplied by 10.
      lon_gps_actual += ((int)incomming_message[33] - 48) * (long)100000000;                             //Add the degrees multiplied by 10.
      lon_gps_actual += ((int)incomming_message[34] - 48) * (long)10000000;                              //Add the degrees multiplied by 10.
      lon_gps_actual /= 10;
      
      //Divide everything by 10.

      if (incomming_message[30] == 'N')latitude_north = 1;                                               //When flying north of the equator the latitude_north variable will be set to 1.
      else latitude_north = 0;                                                                           //When flying south of the equator the latitude_north variable will be set to 0.
      
      if (incomming_message[44] == 'E')longiude_east = 1;                                                //When flying east of the prime meridian the longiude_east variable will be set to 1.
      else longiude_east = 0;                                                                            //When flying west of the prime meridian the longiude_east variable will be set to 0.
      //Serial.println(lat_gps_actual);
      //Serial.println(lon_gps_actual);
 
      l_lat_gps = lat_gps_actual/1000000.0;
      l_lon_gps=lon_gps_actual/1000000.0;
      
      //number_used_sats = ((int)incomming_message[46] - 48) * (long)10;                                   //Filter the number of satillites from the GGA line.
      //number_used_sats += (int)incomming_message[47] - 48;                                               //Filter the number of satillites from the GGA line.
    
    }

    //If the line starts with SA and if there is a GPS fix we can scan the line for the fix type (none, 2D or 3D).
    //if (incomming_message[4] == 'S' && incomming_message[5] == 'A')fix_type = (int)incomming_message[9] - 48;
    


  }
 }

What do you see in Serial Monitor when one of these "dont get an update for a long time" event occurs? I see you have a few cases with:

{
  powercycle();
  startup();
  flu();
}

You should probably put some serial output in those cases so you know what errors are happening.

I don’t have access to the system because it is installed in a truck. However I suspect that the loop keeps repeating I am am probably getting errors while AT commands are being sent to sim7600 because it can’t get a lock on the Internet.

You don't have access to the truck?

Can you have your device send you an SMS when an error occurs?

Have you thought of recording the locations where the network is not available and sending them later?

I will look into both those suggestions.

Below is an example of missing gps coordinates I am talking about. Straight lines represent those missing coordinates. Sometimes I don’t get an update for over 1 hour.

In addition I was wondering if I am doing something wrong with the sequence of AT commands. I read about these two AT commands which I am not currently using

AT+NETOPEN
AT+CGSOCKCONT=1,"IP",”APN”

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