Issue with precision with SdFat library

Hi,

A small issue with the library SdFat.

I tried to record gps coordinates on a SD card with a line like this one:
file.print(gps.location.lng());

However, I cannot slect the nuber of digit.
Like this, I jsut record 2 digit precision.
I would like to record more accurata coordiantes, but when I tried a line like that:
file.print(gps.location.lng(), 10);
I got several "." in the value, not where I expect them.

so the question is basci, but I cannot solve it:
How can I record gps cooredinate, with, e.g., 6 digits precision while using the SdFat library.

Kind regards

replace that by

file.print(gps.location.lng(),6); // 6 decimal digits

if you get more dots, it's coming from the code you did not share

Hi @ardethernet

I've never used sketching with GPS, hence the reason for my question.
What data type does the "gps.location.lng()" function return?

The sdFat library only writes data in the following formats:
" byte, char, or string (char *) ".

Ref: Arduino - FileWrite

RV mineirin

@ruilviana

it returns a double

you are right for write, but @ardethernet uses print() which knows how to do this (inherited from the Print class capability)

Hi all,

here is the code:

/* Chargement des bibliothèques*/
#include <TinyGPS++.h>
#include "RTClib.h"
#define TCAADDR 0x70
#include <Wire.h>
#include <SdFat.h>
#include <sdios.h>
#include <SPI.h>

/*GPS*/
TinyGPSPlus gps;
int i;
int32_t starttime;

/*RTC*/
RTC_DS3231 rtc;

/* Noms des fichiers*/
char fname[24] = "00000000_000000_Data.csv";
const char* SEP = "_";

/*Carte SD*/
SdFat sd;
SdFile file;

bool getGPSdata()
{
  bool gotFix = false;
  while (Serial2.available()) {
    if ((gotFix = gps.encode(Serial2.read()))) break;
  }
  return gotFix;
}

void setup()
  {  
    
    while (!Serial);
    delay(1000);
    Wire.begin();
    Serial.begin(115200);
    Serial2.begin(9600);
    smartDelay(1000);

    if(rtc.begin())
    {
    }
    while (gps.satellites.value() == 0)
      {
        smartDelay(1000);
      }
    rtc.adjust(DateTime(gps.date.year(),gps.date.month(),gps.date.day(),gps.time.hour(),gps.time.minute(),gps.time.second()));
    delay(1000);
    starttime = millis();
    
    DateTime now = rtc.now();
    int YY_N = now.year();
    int MO_N = now.month();
    int DD_N = now.day();
    int HH_N = now.hour();
    int MI_N = now.minute();
    int SEC_N = now.second();
    
    if (!sd.begin(4, SPI_HALF_SPEED))
      {
      }
      
    sprintf(fname,"%04d%02d%02d%s%02d%02d%02d%s%s",YY_N,MO_N,DD_N,SEP,HH_N,MI_N,SEC_N,SEP,"Data.csv");
    if (!file.open(fname,FILE_WRITE))
      {
        return;
      }
    file.close();
    if (sd.exists(fname))
      {
        file.open(fname,FILE_WRITE);   
        file.println("Year; Month; Day; Hour; Minute; Second; Millisecond; Satellites; Latitude; Longitude; Altitude");
        file.close();
      }
  }

void loop()
{
  Serial2.flush();
  if (getGPSdata())
    {
      WriteFile(file);
    }
  else
    {  
      WriteEmpty(file);
    }
}


void WriteFile(SdFile file) {
  
  if (!file.open(fname,  FILE_WRITE  ))
    {
    }
    file.print(gps.date.year());
    file.print("; ");
    file.print(gps.date.month());
    file.print("; ");
    file.print(gps.date.day());
    file.print("; ");
    file.print(gps.time.hour());
    file.print("; ");
    file.print(gps.time.minute());
    file.print("; ");
    file.print(gps.time.second()); 
    file.print("; ");
    file.print(millis());
    file.print("; ");
    file.print(gps.satellites.value());
    file.print("; ");
    Serial.println(gps.location.lat(), 6);
    file.print((float)gps.location.lat());
    file.print("; ");
    Serial.println(gps.location.lng(), 6);
    file.print((float)gps.location.lng());
    file.print("; ");
    file.println((float)gps.altitude.meters());
    file.close();
}

void WriteEmpty(SdFile file) {
  
  if (!file.open(fname,  FILE_WRITE  ))
    {
      digitalWrite(51,0);
      return;
    }
  else
    {
      digitalWrite(51,1);
    }
    digitalWrite(39,0);
    file.print(gps.date.year());
    file.print("; ");
    file.print(gps.date.month());
    file.print("; ");
    file.print(gps.date.day());
    file.print("; ");
    file.print(gps.time.hour());
    file.print("; ");
    file.print(gps.time.minute());
    file.print("; ");
    file.print(gps.time.second()); 
    file.print("; ");  
    file.print(millis());
    file.print("; NaN ; NaN ; NaN ; NaN ;");
    file.close();
}

static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (Serial2.available())
      gps.encode(Serial2.read());
  } while (millis() - start < ms);
}

@J-M-L: adding this thing in the file.print line puts "." at the wriong location in the value.

Ref: Arduino - FilePrint

file .print(data, BASE)

data: the data to print (char, byte, int, long, or string) (Maybe use float?) I dont´t know.

BASE (optional): the base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).

with 6 digit precision
here is the cscreenshot when I tried with ,6 in the line file.print

This tricks is working perfeclty for the Serial.print (checked with serial monitor).

Still stuck ofr a proper writing in the SD card ...

KR

yeah, source code is the ultimate documentation :wink:

the size_t print(double, int = 2); is the one being used with a float (promoted to double) and you see that if you don't pass a second parameter, the default is 2 decimal digits

pass your file as reference to your functions,

what's going on with those empty statements?

  if (!sd.begin(4, SPI_HALF_SPEED))
  {
  }

  if (!file.open(fname,  FILE_WRITE  ))
  {
  }

Hi,

where should I put the size_t print line. In the setup void ?

I emptied the statement to increase the readability of the post !
The orgianl code is much longer ...

Kind regards

ah OK ! the print should be in an else {} clause (unless you have a return in the code you removed)

change the functions to be (note the &)

void WriteFile(SdFile & file) {...
void WriteEmpty(SdFile & file) {...

or just remove the argument since you are using the global variable anyway

size_t not working
with the size_t line in the setup, I got this ,,,,

So I guess there is something I did not understood on where to put the line size_t.

Coudl someone help me with that ?

not sure what you mean. what line?

Hi,

I add the line like this

/* Chargement des bibliothèques*/
#include <TinyGPS++.h>
#include "RTClib.h"
#define TCAADDR 0x70
#include <Wire.h>
#include <SdFat.h>
#include <sdios.h>
#include <SPI.h>

/*GPS*/
TinyGPSPlus gps;
int i;
int32_t starttime;
double longitude;
double latitude;

/*RTC*/
RTC_DS3231 rtc;

/* Noms des fichiers*/
char fname[24] = "00000000_000000_Data.csv";
const char* SEP = "_";

/*Carte SD*/
SdFat sd;
SdFile file;

bool getGPSdata()
{
  bool gotFix = false;
  while (Serial2.available()) {
    if ((gotFix = gps.encode(Serial2.read()))) break;
  }
  return gotFix;
}

void setup()
  {  
    
    while (!Serial);
    delay(1000);
    Wire.begin();
    Serial.begin(115200);
    Serial2.begin(9600);
    smartDelay(1000);

    if(rtc.begin())
    {
    }
    while (gps.satellites.value() == 0)
      {
        smartDelay(1000);
      }
    rtc.adjust(DateTime(gps.date.year(),gps.date.month(),gps.date.day(),gps.time.hour(),gps.time.minute(),gps.time.second()));
    delay(1000);
    starttime = millis();
    
    DateTime now = rtc.now();
    int YY_N = now.year();
    int MO_N = now.month();
    int DD_N = now.day();
    int HH_N = now.hour();
    int MI_N = now.minute();
    int SEC_N = now.second();
    
    if (!sd.begin(4, SPI_HALF_SPEED))
      {
      }
    size_t print(double, int = 6);  
    sprintf(fname,"%04d%02d%02d%s%02d%02d%02d%s%s",YY_N,MO_N,DD_N,SEP,HH_N,MI_N,SEC_N,SEP,"Data.csv");
    if (!file.open(fname,FILE_WRITE))
      {
        return;
      }
    file.close();
    if (sd.exists(fname))
      {
        file.open(fname,FILE_WRITE);   
        file.println("Year; Month; Day; Hour; Minute; Second; Millisecond; Satellites; Latitude; Longitude; Altitude");
        file.close();
      }
  }

void loop()
{
  Serial2.flush();
  if (getGPSdata())
    {
      WriteFile(file);
    }
  else
    {  
      WriteEmpty(file);
    }
}


void WriteFile(SdFile & file) {
  
  if (!file.open(fname,  FILE_WRITE  ))
    {
    }
    file.print(gps.date.year());
    file.print("; ");
    file.print(gps.date.month());
    file.print("; ");
    file.print(gps.date.day());
    file.print("; ");
    file.print(gps.time.hour());
    file.print("; ");
    file.print(gps.time.minute());
    file.print("; ");
    file.print(gps.time.second()); 
    file.print("; ");
    file.print(millis());
    file.print("; ");
    file.print(gps.satellites.value());
    file.print("; ");
    latitude = gps.location.lat();
    Serial.println(gps.location.lat());
    file.print(latitude,6);
    file.print("; ");
    longitude = gps.location.lng();
    Serial.println(gps.location.lng());
    file.print(longitude,6);
    file.print("; ");
    file.println((float)gps.altitude.meters());
    file.close();
}

void WriteEmpty(SdFile & file) {
  
  if (!file.open(fname,  FILE_WRITE  ))
    {
      digitalWrite(51,0);
      return;
    }
  else
    {
      digitalWrite(51,1);
    }
    digitalWrite(39,0);
    file.print(gps.date.year());
    file.print("; ");
    file.print(gps.date.month());
    file.print("; ");
    file.print(gps.date.day());
    file.print("; ");
    file.print(gps.time.hour());
    file.print("; ");
    file.print(gps.time.minute());
    file.print("; ");
    file.print(gps.time.second()); 
    file.print("; ");  
    file.print(millis());
    file.println("; NaN ; NaN ; NaN ; NaN ;");
    file.close();
}

static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (Serial2.available())
      gps.encode(Serial2.read());
  } while (millis() - start < ms);
}

But I still only two digit or more with some random points... ".".

So even when ready the documentation, I cannot upgrade my codsde to get the expected accuracy.

Should I add the line starting with "size_t" somewhere like I did or should I do something else?

KR

which line ?? if you are referring to size_t print(double, int = 6);, I don't know why you have that in the code... get rid of it.

But I still only two digit or more with some random points

can you share the exact file content?

Hi J-M-L,

You can dowload one recorded files:

  • here with only two digits,
  • here when I add ",6" in the line code.
    I tried as well witht the SD library instead of the SdFat library, same issue.

I will get a rid of the size_t line, but I'm still looking for the way to specify properly the number of digit.

Kind regards

I don't see the problem

A
1 Year; Month; Day; Hour; Minute; Second; Millisecond; Satellites; Latitude; Longitude; Altitude
2 2021; 7; 23; 14; 10; 7; 3223; 5; 45.743049; 4.723697; 294.20
3 2021; 7; 23; 14; 10; 7; 3277; 5; 45.743049; 4.723697; 294.20
4 2021; 7; 23; 14; 10; 7; 3332; 5; 45.743049; 4.723697; 294.20
5 2021; 7; 23; 14; 10; 8; 3386; 5; 45.743072; 4.723700; 294.20
6 2021; 7; 23; 14; 10; 8; 3439; 5; 45.743072; 4.723700; 294.20
7 2021; 7; 23; 14; 10; 8; 3493; NaN ; NaN ; NaN ; NaN ;
8 2021; 7; 23; 14; 10; 8; 3544; NaN ; NaN ; NaN ; NaN ;
9 2021; 7; 23; 14; 10; 8; 3604; NaN ; NaN ; NaN ; NaN ;
10 2021; 7; 23; 14; 10; 8; 3654; NaN ; NaN ; NaN ; NaN ;
11 2021; 7; 23; 14; 10; 8; 3706; NaN ; NaN ; NaN ; NaN ;
12 2021; 7; 23; 14; 10; 9; 3757; 5; 45.743068; 4.723710; 294.20

seems you have your 6 digits as expected ?

Hi,

While opening with excel, there is only two digitsor some points inside like XXX.XXX.XXX

I do not know why ...

Now you tell us more...

so it's an excel issue... I see you have some French in the code comments, your excel version is probably in french and expecting commas instead of dots for the decimal point...

➜ open the file in a text editor, substitute all dots with a comma, save the file, then import in excel.

Sorry, I din't thought the issue was coming from Excel ...

a last issue: The GPS coordinates are with , digit seprator while the other data use a ".".
Any idea how I can, in arduino, change the "," into a ".": I guess ht GPs sends string and not number...

KR