SD FileLogger - numerica data

Google: searched
Forums: searched

Can someone please give me a simple example of using numeric data (float or int) with FileLogger::append to write data to the SD card? There are plenty of text-data examples around.

I've tried many solutions posted here and haven't gotten anything to work - I'm pulling out my hair here!

The ability to write integer or float data to a file starts with how you open the file. If you open it as a text file, writing binary data to it will not work. If you open it as a binary file, it will.

So, how are you opening the file? As text or as binary?

What have you tried, and what problems have you encountered?

Hi PaulS, thanks for the quick reply.

Here's my test code:

byte data[1];
int temp = 123;
data[0] = temp;
unsigned long length = sizeof(data[1]);
FileLogger::append("data.txt", data, length);

When I look at the SD card (in Notepad say) I get lots of garbage.

I'm really just trying to log some numeric data (float or int) to the SD card. I've tried several examples I found here (including the sprintf ones) and this is the closest I've come to getting anything to work.

unsigned long length = sizeof(data[1]);

data[1] is not a valid value to pass to the sizeof function. data is an array with a length of 1. That means that the maximum index is 0, not 1.

You are telling FileLogger::append some undefined number of bytes to the file.

If you are writing binary data to the file, and trying to read it in a text editor, you will see garbage.

What are you expecting to see in the file, with this code?

One other issue.

byte data[1];
int temp = 123;

data and temp are not the same size. There is potential to lose data doing this.

Thanks a bunch for your help!

The above was just example code. I figured if I could get that working, I could adapt it to any numerical logging I needed done.

The good news is that I finally found something that worked, which I will place here for the benefit of others that may have the same needs.

/*This snippet will allow the logging of integer data using the append function of the FileLogger SD card reader library */

int count = 123;
char minutes[1];
unsigned long lengthminutes = strlen(minutes);
FileLogger::append("data.txt", (byte*)minutes, lengthminutes);

(I'm not sure if this can be easily adapted to float data.)

Now I simply have to go back in time 2 days and send this to myself

I would recommend the SparkFun OpenLog. I bought one and it is very easy to use. It requires 2 pins from the Arduino to talk to it, but it's very simple. Price seems a bit steep at first, but once you've used it, it's worth the price.

This method is, of course, not writing numeric data to a file. It is writing an ascii representation of numeric data to a file. A fine distinction, but real none the less.

Writing float data is a bit more difficult as the %f format is not supported by sprintf on the Arduino.

You could split the float into two parts - the integer part and the fractional part:

float someValue = 14.375;
int intPart = someValue;
int fracPart = (someValue - intPart) * 100; // Use larger value for more decimal places
// fracPart will be 37

Then, use sprintf to generate a string using both parts:

sprintf(buffer, "%i.%i", intPart, fracPart);

sprintf(buffer, "%i.%i", intPart, fracPart);

That works well enough until the number s 14.037 :frowning:

That works well enough until the number s 14.037

It was an example. To make it more robust, and to have the rounding that one would expect, I'd really do something more like this:

float someValue = 14.376;
int intPart = someValue;
int fracPart = (someValue - intPart) * 1000; // fracPart will be 376
fracPart = (fracPart+5)/10; // fracPart will be 381/10 = 38
sprintf(buffer, "%i.%2i", intPart, fracPart);

Specifying the minimum width of the field causes fracPart to be padded with leading 0s if it is less than 2 digits.

Changing 1000 to 10000, 10 to 100, and 2 to 3 would then print 3 decimal places.

Yeah, I just get the sense that people copy code when it's supplied, and I wanted to point out that the first sprintf statement wasn't a robust answer in all cases, so that people wouldn't use it verbatim. Your followup above is better.

[edit]You probably meant to use
sprintf(buffer, "%i.%[glow]0[/glow]2i", intPart, fracPart);[/edit]
People will have to understand how to adjust it to get the number of decimal places they want, and that's not necessarily a bad thing.

You have a good example of a loop in another situation elsewhere on the forum, converting incoming individual bytes via serial to an int. The loop multiplies an intermediate result by 10 and adds the next digit received. An extension of that loop could be devised for converting floats to a string. The loop would also have to be adjusted, depending on the number of decimal places desired, much like the note in your last line above.