Gps tracking with gsm feedback on command

hello arduino world, This problem might sound similar but i bet it is not the same. i am working on this gps tracking system where the system receives sms commands and send responds accordingly. at this point, the gsm faction of the code works so well but it does not return any gps data in the responses. i am convince its a software problem because i have tested hardware with other codes and they work just fine.
i am not exactly good at this. PLEASE HELP ME!!! I am using a arduino uno, sim900Amini and neo6 gps.

PS.
When i send the comands which requires that the system sends the gps coordinates, it responds that the information is not yet available as seen in the attach photo.
in a bit to trouble shoot, i used a code that works for gps only and with the same hardware setup i am able to receive precise location

i hope this is enough for me to get help...

here is my code

#include <SoftwareSerial.h>
#include <TinyGPS++.h>
//at this time, this code works so well but for the fact that the gps does not pic up the signal that is being received by the module
SoftwareSerial gpsSerial(4, 3);  // GPS TX → 4, RX → 3
SoftwareSerial simSerial(7, 8);  // SIM900A TX → 7, RX → 8

TinyGPSPlus gps;
String predefinedNumber = "************";  // Trusted number
bool sendLocationFlag = false;
String incomingData = "";
float lastLatitude = 0, lastLongitude = 0;
unsigned long lastUpdateTime = 0;
float totalDistance = 0.0;
String Seekernumber = "";

// Function prototypes
float calculateSpeed(unsigned long currentTime, float lat, float lon);
void sendSMS(String number, String message);
void checkIncomingSMS(String inputString);

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

  delay(1000);
  Serial.println("System initializing...");

  // Initialize GSM module
  simSerial.println("AT");
  delay(500);
  simSerial.println("AT+CMGF=1\r");  // Set SMS mode to text
  delay(500);
  simSerial.println("AT+CNMI=2,2,0,0,0\r");  // Auto-show SMS
  delay(500);
  simSerial.println("AT+CMGL=\"REC UNREAD\"");  // Read unread messages

  Serial.println("GPS Tracker ready!");
}

void loop() {
  // Process GPS data
  bool newdata = false;
  while (gpsSerial.available()) {
    char c = gpsSerial.read();  //introduce the char c to replace the gpsserial.read() in the line below.
    Serial.println(c);
    if (gps.encode(c)) { newdata = true; }
  }

  // Process incoming SMS data
  if (simSerial.available()) {
    delay(100);  // Wait for complete message
    incomingData = "";

    while (simSerial.available()) {
      char incomingByte = simSerial.read();
      incomingData += incomingByte;
      delay(5);
    }

    if (incomingData.length() > 0) {
      checkIncomingSMS(incomingData);
      incomingData = "";
    }
  }

  // Send location if tracking is active
  if (sendLocationFlag && gps.location.isValid()) {
    unsigned long currentTime = millis();

    // Send location updates at 2-minute intervals
    if (currentTime - lastUpdateTime >= 120000) {  // 2 minutes in milliseconds
      float lat = gps.location.lat();
      float lon = gps.location.lng();
      float speed = calculateSpeed(currentTime, lat, lon);

      String gpsLink = "https://www.google.com/maps?q=" + String(lat, 6) + "," + String(lon, 6);
      String message = "\nSeeker ID: " + Seekernumber + "\nLoc:" + gpsLink + "\nSpeed: " + String(speed, 2) + " km/h" + "\nTotal Distance: " + String(totalDistance, 2) + " km";

      sendSMS(predefinedNumber, message);
      lastUpdateTime = currentTime;
    }
  }
}

void checkIncomingSMS(String inputString) {
  // Find the phone number
  int index = inputString.indexOf('"') + 1;
  if (index <= 0 || index >= inputString.length()) return;

  inputString = inputString.substring(index);
  index = inputString.indexOf('"');
  if (index <= 0 || index >= inputString.length()) return;

  Seekernumber = inputString.substring(0, index);
  Serial.println("Seeker ID: " + Seekernumber);

  // Find the message content
  index = inputString.indexOf("\n") + 1;
  if (index <= 0 || index >= inputString.length()) return;

  String receivedSMS = inputString.substring(index);
  receivedSMS.trim();
  Serial.println("COMMAND: " + receivedSMS);

  // Process commands (convert to uppercase for case-insensitive comparison)
  receivedSMS.toUpperCase();

  if (receivedSMS.indexOf("REV53") > -1) {
    sendLocationFlag = true;
    sendSMS(predefinedNumber, "GPS tracking activated.");
  } else if (receivedSMS.indexOf("CON34") > -1) {
    sendLocationFlag = false;
    sendSMS(predefinedNumber, "GPS tracking deactivated.");
  } else if (receivedSMS.indexOf("ST67") > -1) {
    if (gps.location.isValid()) {
      String gpsLink = "https://www.google.com/maps?q=" + String(gps.location.lat(), 6) + "," + String(gps.location.lng(), 6);
      sendSMS(predefinedNumber, "Current Location:\n" + gpsLink);
    } else {
      sendSMS(predefinedNumber, "GPS location not available yet.");
    }
  }
}

float calculateSpeed(unsigned long currentTime, float lat, float lon) {
  if (!gps.location.isValid() || (lastLatitude == 0 && lastLongitude == 0)) {
    lastLatitude = lat;
    lastLongitude = lon;
    return 0.0;
  }

  float distance = TinyGPSPlus::distanceBetween(lastLatitude, lastLongitude, lat, lon) / 1000.0;  // km
  totalDistance += distance;

  float timeElapsed = (currentTime - lastUpdateTime) / 1000.0 / 3600.0;  // hours

  lastLatitude = lat;
  lastLongitude = lon;

  return (timeElapsed > 0) ? (distance / timeElapsed) : 0.0;  // km/h
}

void sendSMS(String number, String message) {
  Serial.println("Sending SMS to " + number);

  simSerial.println("AT+CMGF=1");
  delay(500);

  simSerial.println("AT+CMGS=\"" + number + "\"");
  delay(500);

  simSerial.print(message);
  delay(500);

  simSerial.write(26);  // CTRL+Z to send SMS
  delay(2000);

  Serial.println("SMS Sent!");
}

Please describe and post examples of what it does instead. Also mention what you have done to debug the problem.

1 Like

The UNO does not support more then one SoftwareSerial.

1 Like

Thank you very much sir for your insight, please is the a way of using the una and having the expected results or do i have to change my board; which development board or maybe ATMega chip in this case can i use to replace the uno/ATMega328p?

here is a screenshot of the message i receive in place of the cordiinates.
i have updated my initial post

That doesn't tell me anything about your problem with coordinates.

Put in some serial.print statements that allow you to track down the problem, but maybe there is none. You need to be outdoors, with a clear view of the sky, to get a location fix.

Other helpers know more controllers that manages this. I know the Mega has several hardware serial ports. Use Serial1 and Serial2!

This way of reading the GPS could well fail.

A typical GPS outputs about 9 different sentences, but only 2 contain the GPS location data the library reads.

With the code above, when one of the 9 sentences, that has no location data, is read the program goes off and does a pile of stuff related to the SIM.

By the time the SIM stuff is finished and the code gets back to reading the GPS, you could well have missed the GPS sentences that contain the GPS location data. More info here;

https://stuartsprojects.github.io/2024/09/21/How-not-to-read-a-GPS.html

1 Like