Reading data from SD card, receive floats?

Hello,

I'm trying to read data from a file on a micro sd card. To store this data, I used the following code:

myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println(temperature());
    // close the file:
    myFile.close();
    Serial.println("done.");
  } 
  else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

Where temperature returns a float....

When I read my file later in my program and display it on the serial monitor trough my computer with this code, it's working, returning my floats number on the screen:

File dataFile = SD.open("test.txt");

  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {
 
    Serial.write(dataFile.read());

    }
    Serial.println("");
 
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening test.txt");
  }

But if want to use these datas, I change the Serial.write(dataFile.read()); as following:

File dataFile = SD.open("test.txt");
String tempweb;
  // if the file is available, write to it:
  if (dataFile) {
    while (dataFile.available()) {

      tempweb=String(dataFile.read());
      Serial.println(tempweb);
    //  Serial.write(dataFile.read());

    }
    Serial.println("");
 
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening test.txt");
  }

It's not returning me my floats, only strange numbers... =( I guess it's a problem in variable type, I read in the documentation that datas were written as *char. I cannot check this, I've no micro sd reader...
So how can I succeed in reading my datas as float to re-use them later?
Any help would be very appreciated , I'm trying to finish my own temperature datalogger server with a graphing display webpage (via google api chart) on a client ask.

Sorry for bad english, french arduino user, by the way if there is a big grammatical mistake, do not hesitate to tell me! :wink:

Best regards

WalterW

The read function does not know what to expect for data , it will probably only read a byte.

Simples way is to define a function that is called readFloat() that read four bytes into an union that holds a float and an array of 4 bytes. A union uses the same memory for both, so this memory can be accessed as a byte array or as a float. See snippet

union 
{
  float f;
  byte ar[4];
} z;

float readFloat()
{
  for (int i=0; i< 4; i++) z.ar[i] = file.read();
  return z.f;
}
1 Like

The data on the SD card is character data, not 4 bytes representing a float. That's why

    while (dataFile.available()) 
   {
      Serial.write(dataFile.read());
   }

is able to print the characters, one at a time, so that they look correct.

This code:

      tempweb=String(dataFile.read());

is creating a new String object for each character. That does not seem like what you want to do.

Make tempweb a char array, not a String. Add an index, and increment that after storing each character in the array. Print the array.

char fileContents[128}; // Probably can be smaller
byte index = 0;
while (dataFile.available()) 
   {
      fileContents[index++] = dataFile.read();
      fileContents[index] = '\0'; // NULL terminate the array
   }
Serial.print("fileContents: [");
Serial.print(fileContents);
Serial.println("]");

Does that look better?

Thanks for the answers,

Yes the last solution with a char array works to disp values on the serial monitor....

fileContents: [19.66
19.66
19.66
19.66
19.76
19.76
19.66
]

but I really don't know how to grab these temperature for use them :frowning: . I would like to be able to store one of this temperature value (for exemple 19.66) in a float type variable.....

The output you posted show that the individual values are separated by carriage return/line feeds.

   char fileContents[128}; // Probably can be smaller
   byte index = 0;
   while (dataFile.available()) 
   {
      char aChar = dataFile.read();
      if(aChar != '\n' && aChar != '\r')
      {
         fileContents[index++] = aChar;
         fileContents[index] = '\0'; // NULL terminate the array
      }
      else // the character is CR or LF
      {
         Serial.print("fileContents: [");
         Serial.print(fileContents);
         Serial.println("]");
         if(strlen(fileContents) > 0)
         {
            float aVal = atof(fileContents);
            // Do something with aVal
         }

         fileContents[0] = '\0';
         index = 0;
      }
   }

Thanks a lot PaulS, I've now an acess to my data! 8)
I didn't know the atof function!

Thanks again on spending time on this! Arduino rocks!!! :slight_smile:

i try this code but i cant read data aVal

/*
  SD card read/write

 This example shows how to read and write data to and from an SD card file
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe

 This example code is in the public domain.

 */

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

File myFile;
float n = 1.2;

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(12)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  SD.remove("test.txt");  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.print(n);
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");
    // read from the file until there's nothing else in it:
    char fileContents[128]; // Probably can be smaller
    byte index = 0;
   while (myFile.available()) 
   {
      char aChar = myFile.read();
      if(aChar != '\n' && aChar != '\r')
      {
         fileContents[index++] = aChar;
         fileContents[index] = '\0'; // NULL terminate the array
      }
      else // the character is CR or LF
      {
         Serial.print("fileContents: [");
         Serial.print(fileContents);
         Serial.println("]");
         if(strlen(fileContents) > 0)
         {
            float aVal = atof(fileContents);
            Serial.print(aVal);
            // Do something with aVal
         }
         fileContents[0] = '\0';
         index = 0;
      }
   }
    // 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
}

The code you posted does something. We can't help you if all you says is "this doesn't work".