Data Truncation Issue When Sending GPS Coordinates to Database

Hello Everyone, I'm working on a project where I'm using an Arduino to gather GPS coordinates and then send them to a database via a server. However, I'm facing an issue where the GPS coordinates get truncated during transmission. I'm not really expert on this and I really need your help.

Below is my arduino code

#include "WiFiEsp.h"
#include <TinyGPS++.h>

// Define your Wi-Fi network credentials
const char* ssid = "...";         // Replace with your Wi-Fi network SSID
const char* password = "12345678";        // Replace with your Wi-Fi network password

// Define your server details
const char* serverAddress = "192.168.234.21";  // Replace with your server's IP address
const int serverPort = 80;                      // Assuming your server is running on port 80

WiFiEspClient client;   // Create a client object to communicate with the server
TinyGPSPlus gps;        // Create a TinyGPS++ object to handle GPS data

void setup() {
  Serial.begin(9600);     // Initialize serial communication for debugging
  Serial1.begin(9600);    // Initialize hardware serial communication with ESP module
  Serial2.begin(9600);    // Initialize hardware serial communication with GPS module

  // Initialize ESP module
  WiFi.init(&Serial1);

  // Connect to Wi-Fi
  connectToWiFi();
}

void loop() {
  // Update GPS data
  while (Serial2.available() > 0) {
    gps.encode(Serial2.read());
    // Check if GPS data is valid
    if (gps.location.isValid()) {
      // Store latitude and longitude as doubles
      double latitude = gps.location.lat();
      double longitude = gps.location.lng();
      Serial.print("Latitude: ");
      Serial.println(latitude, 15);
      Serial.print("Longitude: ");
      Serial.println(longitude, 15);

      // Convert latitude and longitude to strings
      String latitudeString = String(latitude, 15);
      String longitudeString = String(longitude, 15);

      // Send GPS data to the server
      sendDataToServer(latitudeString, longitudeString);
      delay(10000);
    }
  }
}

void connectToWiFi() {
  Serial.println("Connecting to WiFi");

  // Attempt to connect to Wi-Fi network
  int status = WiFi.begin(ssid, password);
  int attempts = 0;

  while (status != WL_CONNECTED && attempts < 5) {
    delay(1000);
    Serial.println("Attempting to connect to Wi-Fi...");
    status = WiFi.begin(ssid, password);
    attempts++;
  }

  if (status == WL_CONNECTED) {
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("Failed to connect to WiFi");
  }
}

void sendDataToServer(String latitude, String longitude) 
{
  // Check if client is connected to the server
  if (client.connect(serverAddress, serverPort)) 
  {
    Serial.println("Connected to server."); 
    
    // Construct the HTTP POST request
    String postRequest = "POST /Arduino_server/arduino_gps.php HTTP/1.1\r\n";
    postRequest += "Host: " + String(serverAddress) + "\r\n";
    postRequest += "Content-Type: application/x-www-form-urlencoded\r\n";

    // Calculate content length
    long int contentLength = latitude.length() + longitude.length() + 40; // "latitude=" and "longitude=" prefixes length
    postRequest += "Content-Length: " + String(contentLength) + "\r\n";
    postRequest += "Connection: close\r\n\r\n";
    postRequest += "latitude=" + latitude + "&longitude=" + longitude;
    
    // Send the POST request
    client.println(postRequest);
    Serial.println("Request sent");
    Serial.println("Latitude: " + latitude);
    Serial.println("Longitude: " + longitude);

    // Wait for the server response
    delay(20000);

    // Read and print the server response
    while (client.available()) 
    {
      char c = client.read();
      Serial.print(c);
    }

    // Close the connection
    client.stop();
  } 
  else 
  {
    Serial.println("Connection to server failed");
  }
}

And this is the output of my code

```
Latitude: 8.655395507812500
Longitude: 123.420051574707031
Connected to server.
Request sent
Latitude: 8.655395500000000
Longitude: 123.420050000000000
```

I don't know what to do and I don't know how to fix this problem

Only meaningful digits are shown below, so there is no problem. Consumer grade GPS coordinates are accurate to about 7 decimal digits, so the ones below are already a bit "optimistic".

Latitude: 8.655395500000000
Longitude: 123.420050000000000

Note: the Arduino Serial.print() command is happy to invent bogus digits.

1 Like

thanks, but how can i increase it a bit more? cause my gps is neo8m and i want to make its coordinates change even a walk cause when i try to test my gps its too slow to update its coordinates so maybe if i can make the digits increase the changes will also faster

You can buy an RTK GPS unit at Sparkfun, for example. You need a reference station, which is usually a paid service. With a lot of effort, you can get about 3 extra digits for 10 cm positional accuracy.

All the bold digits in the printouts below simply nonsense, invented by Serial.print():

Latitude: 8.655395507812500
Longitude: 123.420051574707031

1 Like

Hello iankristoper

Take a view in the GPS receiver datasheet to get some information about positie accurance provided.

1 Like

oh sad to say, I don't have the resources now and my project deadline is next day and I don't know what to do so maybe fixing the program is my only option now

There is NO PROBLEM. The GPS data are what they are. You simply have to learn more about how GPS works.

Mmmm I thought it is data from the gps

thankyou, ill check it!

thanks man, i really appreciate it

Computers can and do invent arbitrary amounts of completely meaningless data.

1 Like

ill try to test it again how sensitive my gps when i change my location

Hello iankristoper

On the other hand, you can also use a Kalman filter to "optimise" the position information received.

Try it out.

IF the GPS is outdoors and has a clear view of the sky, you can expect about +/- 5 meters of positional accuracy.

Sometimes you can do better, maybe +/- 3 m, depending on how many satellites are visible and where they are in the sky.

first time heard of it, much appreciated. maybe ill try it out later

i test it yesterday and it so later to response but its not the visible to the sky, ill try to figure out this later maybe ill expose it without cover.

You might make some position data logging to see what happens.

1 Like

okay, thankyou

The "blame" goes to IEEE-754. For a 32-bit float, the closest you can get to 8.6553955 is the longer number you see there, without the two zeroes on the end. If you want to store exactly 8.6553955078125, you're in luck because that would be the actual value in the bits. Try it out yourself.

The "next smaller" and "next bigger" numbers in comparison are
8.65539455413818359375
8.6553955078125
8.65539646148681640625
Those are the only values that are available as a 32-bit float; you get the closest one to the "actual value".

Given that the "resolution" -- when there is one digit (an 8) to the left of the decimal point -- is only six digits to right, it's self-deceiving to ask for more than seven; you want that extra digit. Compare rounding 7 digits to 6:
8.6553946 _ _ 8.655395
8.6553955 _ _ 8.655396
8.6553965 _ _ 8.655396
Each "increment" is a distinct value with 7, but rounding to 6 periodically causes the results to be the same.

It's interesting that on your board -- what is it? -- String(latitude, 15) actually "pre-rounds" to 8 significant digits, and then pads with zero to the requested 15 digits; whereas Serial.println(latitude, 15) results in the "raw" value, with only two zeroes to pad to 15 decimal places. Is this indicative of a board where double is actually the same as float. That can also be checked with

Serial.printf("double: %d bytes\n", sizeof(double));
Serial.printf("float: %d bytes\n", sizeof(float));

If you look here: TinyGPS++ | Arduiniana
you can find information about how to get the GPS data down to billionths of a degree (even though of course the last couple of digits will be bogus).