BigNumber removing decimal places

Hello,
I wanted to use 6 decimal places for values and store them in variables. However, BigNumber is removing all decimal values. Project is using Neo-6M GPS data to my phone through SIM800L. ESP-32 as controller. Everything works fine except the above stated problem.

Expected output:

Coordinates: 38.675234, 89.098712

Current output:

Coordinates: 38,89

Here is my code with relevant part indicated with "// <===":

#include <TinyGPSPlus.h>
#include "HardwareSerial.h"
#include "BigNumber.h"



HardwareSerial GPSSerial1(1);
TinyGPSPlus gps;
char Received_SMS;
short SMS_OK = -1;
short SMS_Battery = -1;
short SMS_LOC = -1;
char battery_status[27];
String Data_SMS;

void setup() {


  Serial.begin(9600);

  Serial2.begin(9600);

  GPSSerial1.begin(9600,SERIAL_8N1, 14,15);
  
  BigNumber::begin (); // <===
  
    
  delay(3000);
  ReceiveMode();

}


void loop() {
String RSMS;


  while (GPSSerial1.available() > 0){
    if (gps.encode(GPSSerial1.read()))
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
  }}
  
  while (Serial2.available()) {


    Received_SMS = Serial2.read();  
    Serial.println(Received_SMS);   
    RSMS.concat(Received_SMS);
    SMS_OK = RSMS.indexOf("Send");
    SMS_Battery = RSMS.indexOf("Bat");
    SMS_LOC = RSMS.indexOf("GPS");
  }
  if (SMS_OK != -1) {
    Serial.println("Found matching SMS");
    Data_SMS = "Message received";

    Send_Data();
    ReceiveMode();
    Data_SMS = "";    
    SMS_OK = -1;
  }
if (SMS_LOC != -1) {
    Serial.println("Found location SMS");
    Serial.println(gps.location.lat(),6);    
    Serial.println(gps.location.lng(),6);
    
    BigNumber::setScale (6); // <===
    BigNumber GPS_lat; // <===
    BigNumber GPS_lng; // <===
    GPS_lat = BigNumber (gps.location.lat()); // <===
    GPS_lng = BigNumber (gps.location.lng()); // <===
    Data_SMS = "Coordinates:"; // <===
    Data_SMS = Data_SMS + GPS_lat + "," + GPS_lng; // <===
    Serial.println("Data SMS is:");
    Serial.println(Data_SMS);
    Serial.println("End of Data SMS");
    Send_Data();
    ReceiveMode();
    Data_SMS = "";
    SMS_LOC = -1;
  }  
  if(SMS_Battery != -1){
    
    Serial.println("Found Battery SMS");
    
    Serial2.print("AT+CBC\r");
    
    for(int i = 0 ; i<27 ; i++) {
    battery_status[i] = Serial2.read(); 
     Serial.println("Battery status is:");
     Serial.println(battery_status[i]);
     if(battery_status[i] == ',' && battery_status[i-3] == ','){
    Data_SMS.concat(battery_status[i-2]);
    Data_SMS.concat(battery_status[i-1]);    
    }
    
    Serial.println("Data SMS is:");
    Serial.println(Data_SMS);
    Serial.println("End of Data SMS");
    Data_SMS.concat('%');
    Serial.println(gps.location.lat(),6);    
    Serial.println(gps.location.lng(),6);
    Send_Data();
    ReceiveMode();
    Data_SMS = "";
     SMS_Battery = -1;
  }
  
}






void ReceiveMode() {
  Serial2.println("AT\r");  
  updateSerial();
  Serial2.println("AT+CMGF=1\r");  
  updateSerial();
  Serial2.println("AT+CNMI=2,2,0,0,0\r");  
  updateSerial();
}

void Send_Data() {
  Serial.println("Sending Data...");  
  Serial2.print("AT+CMGF=1\r");       
  delay(100);
  Serial2.print("AT+CMGS=\"+xxxxxxxxxxxxxx\"\r"); 
  delay(500);
  Serial2.print(Data_SMS);  
  delay(500);
  Serial2.print((char)26);  
  delay(500);
  Serial2.println();
  Serial.println("Data Sent.");
  delay(500);
}

void updateSerial() {
  delay(500);
  while (Serial.available()) {
    Serial2.write(Serial.read());  
  }
  while (Serial2.available()) {
    Serial.write(Serial2.read());  
  }
}

Don't use Strings to format the numbers. Use Serial.print(number, 6); instead.

In fact, using Strings is not advised on AVR-based Arduinos, as they cause memory problems and program crashes.

On non-AVR based Arduinos, use type double to get 15 decimal digits of precision. The BigNumber library is not useful in this case.

Which Arduino are you using?

I am no t familiar with the HW platform you use.
But as a hint: 6 decimal places, like "999999" is in hex: 0xF_423F
If you have a platform where the "int" is just 16bit (not 32bit) - it will not fit!

So, think about if you need on your platform "long long" as type (e.g. here to deal with 32bits, if platform is 16bit oriented).
Or: consider to use fix-point math (and instructions) ...

Just do a cross-check: when platform is 16bit oriented - what is the max. value you could store?
Often, there is a macro for "MAX_VALUE" (as max. value possible at this platform).

Any larger types might be possible via "long long" or as your own implementation of "BigNumber".

I am using an ESP-32. Editing the post to include that part.

The requirement is to send coordinates via SMS, not print to screen (which I can already do).

The ESP32 supports type double, so declare coordinates and other floating point variables as double, which is the default for TinyGPS++.

Use Serial2.print(number, N) to get N (0-15) decimal places on output to the phone module. That greatly exceeds the precision of the data in the NMEA sentences.

There is no need to use Strings.

1 Like

I did try both float and double. The result was the same: only two decimal places. Thats why I tried BigNumber.

Okay I will try Serial2.print to directly send data. Will report the result here.Thanks

This is where you are losing decimals.

    Data_SMS = "Coordinates:"; // <===
    Data_SMS = Data_SMS + GPS_lat + "," + GPS_lng; // <===
    Serial.println("Data SMS is:");
    Serial.println(Data_SMS);

Replace the above (using Serial2) with

    Serial2.print ("Coordinates:");
    Serial2.print(gps.location.lat(),6);
    Serial2.print( ",");
    Serial2.println(gps.location.lng(),6);
2 Likes

Works perfectly. Thanks

Glad to hear that!

1 Like

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