Go Down

Topic: Read CSV or TXT from SD card into string or array (Read 35178 times) previous topic - next topic

fat16lib

Use a floating type for the variable and use strtod() in place of strtol();

Code: [Select]

  //  int array[ROW_DIM][COL_DIM];

  //  change array type to float or double (both are 32-bit floating point on AVR)
  double array[ROW_DIM][COL_DIM];

  // ...

  //  array[i][j] = strtol(str, &ptr, 10);

  //  convert filed to floating point instead of long.
      array[i][j] = strtod(str, &ptr);


hiramvillarreal

Hi fat16lib, great solution to read a CSV, I need to output almost the same but I need to output a line once and never output it again.

I am using a CSV to load a list of "user" and "password" from a PC, then insert the SD card into the Arduino card reader, after push a bottom it will output on a LCD an unused line, the next time the push bottom it will press, it will give the next line.

I been thinking  to use an extra file to save the last position read it and stop the while loop keeping that X,Y value for the display, after that the "index" file will be saved with an increment of the last position.
Do you have an advice to do so?

Thanks  sorry for my English.

pussimus

Here is a simple sketch that reads a CSV file with two numbers on each line.  It doesn't use the dangerous String class.
Code: [Select]

#include <SD.h>
File file;

bool readLine(File &f, char* line, size_t maxLen) {
  for (size_t n = 0; n < maxLen; n++) {
    int c = f.read();
    if ( c < 0 && n == 0) return false;  // EOF
    if (c < 0 || c == '\n') {
      line[n] = 0;
      return true;
    }
    line[n] = c;
  }
  return false; // line too long
}

bool readVals(long* v1, long* v2) {
  char line[40], *ptr, *str;
  if (!readLine(file, line, sizeof(line))) {
    return false;  // EOF or too long
  }
  *v1 = strtol(line, &ptr, 10);
  if (ptr == line) return false;  // bad number if equal
  while (*ptr) {
    if (*ptr++ == ',') break;
  }
  *v2 = strtol(ptr, &str, 10);
  return str != ptr;  // true if number found
}

void setup(){
  long x, y;
  Serial.begin(9600);
  if (!SD.begin(SS)) {
    Serial.println("begin error");
    return;
  }
  file = SD.open("TEST.CSV", FILE_READ);
  if (!file) {
    Serial.println("open error");
    return;
  }
  while (readVals(&x, &y)) {
    Serial.print("x: ");
    Serial.println(x);
    Serial.print("y: ");
    Serial.println(y);
    Serial.println();
  }
  Serial.println("Done");
}
void loop() {}
 
Is it just me, or doesnt it work anymore ?
I updated Library SD.H (v1.1.1) after that it wont read files from my SD card.

MikeOrlando02

Here is a simple sketch that reads a CSV file with two numbers on each line.  It doesn't use the dangerous String class.
Code: [Select]

#include <SD.h>
File file;

bool readLine(File &f, char* line, size_t maxLen) {
  for (size_t n = 0; n < maxLen; n++) {
    int c = f.read();
    if ( c < 0 && n == 0) return false;  // EOF
    if (c < 0 || c == '\n') {
      line[n] = 0;
      return true;
    }
    line[n] = c;
  }
  return false; // line too long
}

bool readVals(long* v1, long* v2) {
  char line[40], *ptr, *str;
  if (!readLine(file, line, sizeof(line))) {
    return false;  // EOF or too long
  }
  *v1 = strtol(line, &ptr, 10);
  if (ptr == line) return false;  // bad number if equal
  while (*ptr) {
    if (*ptr++ == ',') break;
  }
  *v2 = strtol(ptr, &str, 10);
  return str != ptr;  // true if number found
}

void setup(){
  long x, y;
  Serial.begin(9600);
  if (!SD.begin(SS)) {
    Serial.println("begin error");
    return;
  }
  file = SD.open("TEST.CSV", FILE_READ);
  if (!file) {
    Serial.println("open error");
    return;
  }
  while (readVals(&x, &y)) {
    Serial.print("x: ");
    Serial.println(x);
    Serial.print("y: ");
    Serial.println(y);
    Serial.println();
  }
  Serial.println("Done");
}
void loop() {}
 

Reading this "TEST.CSV" file.
Results in this output
Here is a simple sketch that reads a CSV file with two numbers on each line.  It doesn't use the dangerous String class.
Code: [Select]

#include <SD.h>
File file;

bool readLine(File &f, char* line, size_t maxLen) {
  for (size_t n = 0; n < maxLen; n++) {
    int c = f.read();
    if ( c < 0 && n == 0) return false;  // EOF
    if (c < 0 || c == '\n') {
      line[n] = 0;
      return true;
    }
    line[n] = c;
  }
  return false; // line too long
}

bool readVals(long* v1, long* v2) {
  char line[40], *ptr, *str;
  if (!readLine(file, line, sizeof(line))) {
    return false;  // EOF or too long
  }
  *v1 = strtol(line, &ptr, 10);
  if (ptr == line) return false;  // bad number if equal
  while (*ptr) {
    if (*ptr++ == ',') break;
  }
  *v2 = strtol(ptr, &str, 10);
  return str != ptr;  // true if number found
}

void setup(){
  long x, y;
  Serial.begin(9600);
  if (!SD.begin(SS)) {
    Serial.println("begin error");
    return;
  }
  file = SD.open("TEST.CSV", FILE_READ);
  if (!file) {
    Serial.println("open error");
    return;
  }
  while (readVals(&x, &y)) {
    Serial.print("x: ");
    Serial.println(x);
    Serial.print("y: ");
    Serial.println(y);
    Serial.println();
  }
  Serial.println("Done");
}
void loop() {}
 

Reading this "TEST.CSV" file.
Results in this output
@fat16lib, I am having a little difficulty in following your code; however with some time/google I think I will figure it out.  If you have a minute, could you look at my post and see if this code you posted would be applicable to my situation?  I have an SD card with the fixed-length HEX and then the username, can I use your code for this case?

https://forum.arduino.cc/index.php?topic=622216.0

Code: [Select]

ba322d387d980d74fc5d0d46, John
ba039b572f612e58d05a8c2d, Katie
979aeeb3ee35360a24d6190, Sandra
78cabc678dc0a503647cb05d, Tim




wildbill

To get started just use the readline function to pull each line in turn into a character array. Then print it to the serial port. Once that's working you can figure out how to parse it into two parts for storage.

Go Up