Reading CSV file from SD card_Edited

Hi Arduino community,

I have to repost this after I realized my previous post was not following the ‘standard’ here. My apologies.

At the current stage of my project, I’m trying to read the CSV file from the SD card. I know this topic has been posted many times, and there are examples I can find online, or even here. Believe me, I have gone through those tutorials/examples, and tried to use those programs. Apparently, I have managed to get the data printed on the serial monitor, but the readings are somehow inaccurate (some corrects, some are not). The CSV file contains a series of Longitude and Latitude data of a route. Here is the example of the data:

Column 1, Column 2
(Longitude, Latitude)
4530.3979, 909.8869
4530.3981, 909.8866
4530.3982, 909.8866
4530.3982, 909.8868

So this is the complete code that I’m using.

#include <SPI.h>
#include <SD.h>

File myFile;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // re-open the file for reading:
  myFile = SD.open("datalog3.csv");
  if (myFile) {
    Serial.println("test.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      String a="";
       
       float Wval;
      for(int i=0;i<99;++i)
      {
     
       char temp=myFile.read();
       // Serial.println(temp);
       // Serial.print("ciclo  ");
       // Serial.println(i);
        if(temp!=','&&temp!='\n')
      { //a=temp;
        a+=temp;}
      else if(temp==','||temp=='\n'){
         Serial.println(a);
        char buf[a.length()];
        a.toCharArray(buf,a.length());
         Wval=atof(buf);
 
      Serial.println(Wval,4);
     
      break;}
     
        }
     
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop()
{
  // nothing happens after setup
}

And these are the readings I got;

4530.3979
4530.3969
909.8869
909.8869
4530.3981
4530.3979
909.8866
909.8866
4530.3982
4530.3979
909.8866
909.8866
4530.3982
4530.3979
909.8868
909.8868

I’m not sure why it gives different reading from the file. I just need for the program to read the data correctly from the columns and following the sequence, so that I can proceed with the next stage. Really appreciate if somebody can help me out with this. Thank you.

You know the maximum length of a record. Ditch the stupid String class. Use a char array to hold the data.

I do not understand why you are puzzled by the differences. Go read the documentation on float for the Arduino. What you see is perfectly reasonable.

I do not understand why you are puzzled by the differences. Go read the documentation on float for the Arduino. What you see is perfectly reasonable.

or you could ask Krupski very nicely to show you how to fix that problem. He solved the float problem on post 15.

PaulS:
You know the maximum length of a record. Ditch the stupid String class. Use a char array to hold the data.

I do not understand why you are puzzled by the differences. Go read the documentation on float for the Arduino. What you see is perfectly reasonable.

The reading needs to be very accurate, bcos it will determine the success of my project in general and to allow me to proceed to the next stage. But thank you for your advice.

Thomas499:
or you could ask Krupski very nicely to show you how to fix that problem. He solved the float problem on post 15.

Thank you, I will have a look his posts.

The reading needs to be very accurate, bcos it will determine the success of my project in general

Then your project is doomed to failure. A float is good for 6 or 7 digits of precision. That would be 4530.39 or maybe 4530.397. Printing a float that is in the thousands to 4 decimal places is just wishful thinking.

Simple demonstration code

const char* tVal[10] = { "0.12345", "0.123456", "0.1234567", "0.12345678", "0.123456789", "0.1234567890", "0.12345678901", "0.123456789012", "0.1234567890123", "0.12345678901234" };
const float fVal[10] = { 0.12345, 0.123456, 0.1234567, 0.12345678, 0.123456789, 0.1234567890, 0.12345678901, 0.123456789012, 0.1234567890123, 0.12345678901234 };
void setup() {
  Serial.begin(115200);
  char *end;
  for (byte idx = 9; idx > 0; idx--) {
    float val = strtod(tVal[idx], &end);
    Serial.print("this string    '");
    Serial.print(tVal[idx]);
    Serial.println("'");
    Serial.print("converted float ");
    Serial.println(val, 5 + idx);
    Serial.print("float constant  ");
    Serial.println(fVal[idx], 5 + idx);
    Serial.println();
  }
}
void loop() {}
this string    '0.12345678901234'
converted float 0.12345678806304
float constant  0.12345678806304

this string    '0.1234567890123'
converted float 0.1234567880630
float constant  0.1234567880630

this string    '0.123456789012'
converted float 0.123456788063
float constant  0.123456788063

this string    '0.12345678901'
converted float 0.12345678806
float constant  0.12345678806

this string    '0.1234567890'
converted float 0.1234567880
float constant  0.1234567880

this string    '0.123456789'
converted float 0.123456788
float constant  0.123456788

this string    '0.12345678'
converted float 0.12345678
float constant  0.12345678

this string    '0.1234567'
converted float 0.1234567
float constant  0.1234567

this string    '0.123456'
converted float 0.123456
float constant  0.123456

You know, you could think outside of the box and write a protocol that automatically multiplies those numbers by 10^(whatever you feel comfortable with) then when you receive the numbers, have the second protocol automatically divide by the same number… of course i’m actually kind of fond of the float solution that i mentioned Kruspi implemented straight into the IDE.

Thomas499:
You know, you could think outside of the box and write a protocol that automatically multiplies those numbers by 10^(whatever you feel comfortable with) then when you receive the numbers, have the second protocol automatically divide by the same number.... of course i'm actually kind of fond of the float solution that i mentioned Kruspi implemented straight into the IDE.

I have tried to convert the string into the int., unfortunately I have the same problem of conversion. I tried:

….

Serial.println(a);
int b=atoi(a.c_str());
Serial.println(b);

And the print was:
84481211
121341

I have also tried:
int b= a.toInt();

But it still gave the same output. I'm sorry, but I’m not familiar with the concept of conversion in Arduino.

But it still gave the same output. I'm sorry, but I'm not familiar with the concept of conversion in Arduino.

Nor with the concept of posting all of your code.
Nor with the concept of limits on the size of the value that can be stored in a given type. And, that is so easy to check. Go look at the reference page NOW!