Go Down

Topic: Reading integers from SD card (Read 2496 times) previous topic - next topic

Crebsyn

Hi working on a program that needs to pull data from an SD card. The file is a .csv and i have 2 columns and multiple rows(about 400). The data is 4 or 5 digit numders eg 2568, 45876.
I have a counter in my program and want to pull the first row at say count 5, then at count 10 pull the second row and so on. Any tips on how to do this, I have seen examples of 1 column and 1 row but not multiple. I could separate the columns into 2 files if that makes it easier.

Thanks for your help

holmes4

The arduino does not under stand file types, at all, or at least in any thing like the way a PC does. Windows associates a file type with a program and then calls then calls that program to deal with the file. I can't think what application a .cvs file is for.

But I would try this,

Export the file from the application (and I mean export not save) as a text file. You can the see the format of data in the file with notepad.

After that its not to hard ( :smiley-roll:) to read the data from the file.

Mark

Arrch

You're going to need a state machine and basic string reading techniques to read in the values. Posting what code you have so far is going to make it a lot easier to help.

PeterH

Your sketch will read the file as a sequence of characters and it will need to step through it looking for line separators until it gets to the line of interest, then step through the line looking for column separators (i.e. commas) until it gets to the field of interest, and then extract the characters containing the decimal digits and parse them to get the corresponding number.

If you can separate the columns into separate files (one column per file) that reduces the amount of work needed to parse the file contents.

Do you have any performance constraints for this - do you care how long it takes to read the values?
I only provide help via the forum - please do not contact me for private consultancy.

Crebsyn

I am going to simplify the code and post it. As for speed it will need to be read in under  .1 second.

Thanks for the replies

senopati

Maybe this article will give you good clue to do that :

Read Config File from an SD Card

PaulS

Quote
I can't think what application a .cvs file is for.

It's csv, not cvs. The csv extension stands for comma-separated values, and is often used when the data is to be parsed by applications that don't need all the overhead of something like Excel, and don't need the data in binary format.

csv files ARE text files.

Quote
If you can separate the columns into separate files (one column per file) that reduces the amount of work needed to parse the file contents.

But, since parsing is trivial, why bother?



PeterH


But, since parsing is trivial, why bother?


Once you know how to do it, sure. But getting it working the first time is not trivial.

If the need can be avoided, why suffer the extra complexity?
I only provide help via the forum - please do not contact me for private consultancy.

Crebsyn

Yes I am a total noob, so parsing is not trivial to me. I had another idea but can't get it to work. If I could write one number in many files, I could open each file one at a time when needed. See this code - I can't index the file name, is this even possible?
Code: [Select]
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <SD.h>

#define SD_CS 5
#define LCD_RESET A4

Adafruit_TFTLCD tft;
int8_t saved_spimode;

void disableSPI(void) {
  saved_spimode = SPCR;
  SPCR = 0;
}

void enableSPI(void) {
  SPCR = saved_spimode;
}

const int buttonPin = 2;
int cycles = 0;
unsigned long serialTimer;
int cyclecount = 0;
int B = 0;


void setup()
{
  Serial.begin (9600);
  pinMode (buttonPin, INPUT);
  tft.reset();
  uint16_t identifier = tft.readID();
  tft.begin(identifier);
  Serial.print("Initializing SD card...");
  if (!SD.begin(SD_CS)) {
  Serial.println("initialization failed!");
  return;
  }
  Serial.println("initialization done.");
  disableSPI();
  serialTimer =millis();
}

void loop ()
{
 
  cycles++;
  while (digitalRead(buttonPin) == HIGH);
  while (digitalRead(buttonPin) == LOW);
  delay (50);
  Serial.println(cycles);
   for (B=0; B<2000; B+=5){
   if (cycles == B)
   test ();
  }
}


void test ()
{
enableSPI();
   char D = (B);
   File myFile2;
   myFile2 = SD.open("(D).txt", FILE_WRITE);
   if (myFile2) {
   Serial.print("Writing to test.txt...");
   myFile2.println(B);
   myFile2.close();
   Serial.println("done.");
  } else {
    Serial.println("error opening test.txt");
  }
  disableSPI(); 
}


PeterH


See this code - I can't index the file name, is this even possible?


I'm not sure what you mean by 'index the file name', or in what respect the sketch fails to do it.
I only provide help via the forum - please do not contact me for private consultancy.

Crebsyn

File2 = SD.open("(D).txt", FILE_WRITE);

I want "D" to index.

PeterH


I want "D" to index.


And still I don't know what that means. Please try to describe what you're trying to do, without using the word "index".
I only provide help via the forum - please do not contact me for private consultancy.

GoForSmoke

Unless SD.open() has special powers to read "(D).txt" and replace D with a value, you need to build a file name before the call to open.

sprintf() is the easy way to format text into a char or byte array.
I think you don't even need to include stdlib to use sprintf().
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

As a beginner you would do well to look it up on a C++ website and screw around with it for a while, sprintf() can turn none to many numeric variables into tightly formatted text.

The strtok() command is good for parsing buffered text. It will take a little longer to learn if you choose to use it. The reality is that strtok is both clean and simple in action.
IIRC you need to include string.h to get strtok.
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Crebsyn

#13
Nov 15, 2012, 04:13 pm Last Edit: Nov 15, 2012, 04:20 pm by Crebsyn Reason: 1
Ok I know this code is a mess. But can someone shown me how it should look. Not sure how to arrange sprintf.
Code: [Select]
void test ()
{
enableSPI();
  char D = (B); //B is a counter
  File newfile;
  File myFile2;
  myFile2 = SD.open((sprintf (newfile, "sensor%d.txt", (D) )) , FILE_WRITE); //know idea of how to arrange this, do I use D or B?
  if (myFile2) {
  Serial.print("Writing to test.txt...");
  myFile2.println(B);
  myFile2.close();
  Serial.println("done.");
 } else {
   Serial.println("error opening test.txt");
 }
 disableSPI();  
}

danb35

Try this instead:
Code: [Select]
int D = 1; // obviously you can set D however you want, but it should be an int
char fileName[13];
sprintf(fileName, "sensor%d.txt", D);
myFile2 = SD.open(fileName, FILE_WRITE);

Go Up