Read SD card file and put values into variables

Hello, I am absolutely new to Arduino programming and need some help;
normally I will do a lot of researches to avoid to disturb and learn something new but, for this simple task, a lot of paths leaded me in the nowhere land!!
So, my problem, I want to read my SD card where I have stored 13 parameters, line by line, separated by /n, after I read the line, hopefully removing unwanted characters like ‘=’, I want to put the value in the corresponding variable, the txt file looks like:

IPADDRESS = 192.168.1.1
SSID = WIFI1
PW = PASS1
NAME = MYNAME

So I need the value after the ‘=’ to be inserted into its proper variable vith a name similar to PARAMETER1, PARAMETER2 etc., these variables are then used after to connect to an AP, I don’t want these parameters fixed into the code.

I will attach my current sketch, it reads the file and prints all the 13 values correctly, I tried several solutions like concat variables or add the index value at the end of the name but doesn’t work.
Thanks a lot for your patience and help
Alessandro

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

const int chipSelect = 8;
String DataTemp;
String Parametro;
short i;

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


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

  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on Arduino Uno boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(SS, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File myFile = SD.open("param.sav");

  // if the file is available, write to it:
  if (myFile) {
    while (myFile.available()) {
      char c = myFile.read(); // Get the next character
      if (isPrintable(c)) { // 
         DataTemp.concat(c); 
        
    } else if (c == '\n') { // End of line
        
        Parametro = DataTemp;  // 
        DataTemp = "";  // Reset to null ready to read the next line
        Serial.print(F("The parameter is: "));
        Serial.println(Parametro); // Show us the value
        //Here we have to put values in 13 variables, like parameter1, parameter2 and so on.......
    }
}
      
    }
    myFile.close();
  }
   
void loop() {
}

If you know the number of values to be read or the file has an end marker of some kind, then I suggest the first thing to do would be to read each line and put it into an array to be parsed. Get that working first

UKHeliBob:
If you know the number of values to be read or the file has an end marker of some kind, then I suggest the first thing to do would be to read each line and put it into an array to be parsed. Get that working first

Hello, thanks for the reply, so I have to define an array like char ARRAY1[14]; and put the values inside separated by commas or blanks? Note the number 14 that is 13+1 for the NULL termination of the string
Regards

alex998r:
Hello, thanks for the reply, so I have to define an array like char ARRAY1[14]; and put the values inside separated by commas or blanks? Note the number 14 that is 13+1 for the NULL termination of the string
Regards

What I wrote is wrong, I made a string with only 14 characters, I think I need an array of strings

Personally I would use an array of C style string pointers (lowercase s) and use the strtok() function to parse the values from the array once the lines had been read from the SD card.

Hello, thanks again, I am not so skilled, please, may you give an example?
Arrays are still an obscure object for me
Many thanks

An example of saving to an array based on your program

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

const byte chipSelect = 10;
String parameter;
byte line;
String theArray[10];

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Initializing SD card...");
  if (!SD.begin(chipSelect))
  {
    Serial.println("Card failed, or not present");
    while (true);
  }
  Serial.println("card initialized.");
  File myFile = SD.open("params.txt");
  if (myFile)
  {
    while (myFile.available())
    {
      char c = myFile.read();
      if (isPrintable(c))
      {
        parameter.concat(c);
      }
      else if (c == '\n')
      {
        //        Serial.println(parameter);
        theArray[line] = parameter;
        parameter = "";
        line++;
      }
    }
  }
  myFile.close();
  printArray();
}

void loop()
{
}

void printArray()
{
  Serial.println("\nThe array contains :\n");
  for (int line = 0; line < 4; line++)
  {
    Serial.println(theArray[line]);
  }
}

Note that because this is based on your code it uses Strings rather than strings but should show you the principle. Note too that it does not parse the data, it merely stores it in an array ready to be parsed

1 Like

A second example. This time not using Strings

#include <SPI.h>
#include <SD.h>
char recordArray[4][30];
char aRecord[30];
byte recordNum;
byte charNum;

File myFile;

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }
  Serial.print("Initializing SD card...");
  if (!SD.begin(10))
  {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  myFile = SD.open("params.txt");
  if (myFile)
  {
    Serial.println("params.txt:");
    while (myFile.available())
    {
      char inChar = myFile.read();
      if (inChar == '\n')
      {
        strcpy(recordArray[recordNum], aRecord);
        recordNum++;
        charNum = 0;
      }
      else
      {
        aRecord[charNum++] = inChar;
        aRecord[charNum] = '\0';
      }
    }
    myFile.close();
  }
  else
  {
    Serial.println("error opening params.txt");
  }
  printArray();
}

void loop()
{
}

void printArray()
{
  Serial.println("from the array :");
  for (int index = 0; index < 4; index++)
  {
    Serial.println(recordArray[index]);
  }
}

An expanded version that parses the data stored in the record array and puts the values in a second array

#include <SPI.h>
#include <SD.h>
const byte NUMBER_OF_RECORDS = 4;
char recordArray[NUMBER_OF_RECORDS][40];
char * parameterArray[NUMBER_OF_RECORDS];
char aRecord[30];
byte recordNum;
byte charNum;

File myFile;

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }
  Serial.print("Initializing SD card...");
  if (!SD.begin(10))
  {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  myFile = SD.open("params.txt");
  if (myFile)
  {
    Serial.println("params.txt:");
    while (myFile.available())
    {
      char inChar = myFile.read();  //get a character
      if (inChar == '\n') //if it is a newline
      {
        strcpy(recordArray[recordNum], aRecord);  //copy the record to the array
        recordNum++;  //increment the record array index
        if (recordNum > NUMBER_OF_RECORDS)
        {
          Serial.println("record count exceeded");
          while(true);
        }
        charNum = 0;  //start again at the beginning of the array record
      }
      else
      {
        aRecord[charNum] = inChar;  //add character to record
        charNum++;  //increment character index
        aRecord[charNum] = '\0';  //terminate the record
      }
    }
    myFile.close();
  }
  else
  {
    Serial.println("error opening params.txt");
  }
  parseRecordArray();
  printParameterArray();
}

void loop()
{
}

void parseRecordArray() //split the parameters from each record
{
  for (int index = 0; index < NUMBER_OF_RECORDS; index++)
  {
    char * ptr; //pointer to current data
    ptr = strtok(recordArray[index], "=");//find the "="
    ptr = strtok(NULL, ""); //get remainder of text
    parameterArray[index] = ptr + 1;  //remove space and save to array
  }
}

void printParameterArray()
{
  Serial.println("\nparameter values from the array");
  for (int index = 0; index < NUMBER_OF_RECORDS; index++)
  {
    Serial.print("parameterArray[");
    Serial.print(index);
    Serial.print("] = ");
    Serial.println(parameterArray[index]);
  }
}

Note that the values are not in named variables, rather they are in array elements which can be used in the same way. Note too that the record array is not strictly necessary as each record could be parsed on the fly but putting each record in the array allows for easier debugging

Here is version that does not use an intermediate array

#include <SPI.h>
#include <SD.h>
const byte NUMBER_OF_RECORDS = 4;
char parameterArray[NUMBER_OF_RECORDS][30];
char aRecord[30];
byte recordNum;
byte charNum;

File myFile;

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  }
  Serial.print("Initializing SD card...");
  if (!SD.begin(10))
  {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  myFile = SD.open("params.txt");
  if (myFile)
  {
    Serial.println("params.txt:");
    while (myFile.available())
    {
      char inChar = myFile.read();  //get a character
      if (inChar == '\n') //if it is a newline
      {
        parseRecord(recordNum);
        recordNum++;
        charNum = 0;  //start again at the beginning of the array record
      }
      else
      {
        aRecord[charNum] = inChar;  //add character to record
        charNum++;  //increment character index
        aRecord[charNum] = '\0';  //terminate the record
      }
    }
    myFile.close();
  }
  else
  {
    Serial.println("error opening params.txt");
  }
  printParameterArray();
}

void loop()
{
}

void parseRecord(byte index)
{
  char * ptr;
  ptr = strtok(aRecord, " = ");  //find the " = "
  ptr = strtok(NULL, ""); //get remainder of text
  strcpy(parameterArray[index], ptr + 2); //skip 2 characters and copy to array
}

void printParameterArray()
{
  Serial.println("\nparameter values from the array");
  for (int index = 0; index < NUMBER_OF_RECORDS; index++)
  {
    Serial.print("parameterArray[");
    Serial.print(index);
    Serial.print("] = ");
    Serial.println(parameterArray[index]);
  }
}

Hello Bob, you were very helpful, I will check your examples and save them. In the meantime I continued to study by myself, I want to learn something new every day, and further developed my code, in this version it reads all 13 strings, put them into an array and then extracts and prints them, it function ok. Next step will be to populate variables ( example var1, var2, var3 … ) instead of printing the values, here my code, maybe it is not elegant or optimized but I am satisfied :wink:

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

const int chipSelect = 8;
String DataTemp;
String Parametro;
short i;
String AllData[14];
int Pointer = 0;
int count = 0;
#define PRINTLN(count) Serial.print(" "); Serial.print(count); Serial.print(" = ");
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


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

  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on Arduino Uno boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
   pinMode(SS, OUTPUT);
   
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File myFile = SD.open("param.sav");

  // if the file is available, write to it:
  if (myFile) {
    while (myFile.available()) {
      char c = myFile.read(); // Get the next character
      if (isPrintable(c)) { // 
         DataTemp.concat(c); 
        
       } else if (c == '\n') { // End of line
        
      Parametro = DataTemp;  // 
      DataTemp = "";  // Reset to null ready to read the next line
      Serial.print(F("The parameter is: "));
      Serial.println(Parametro); // Show us the valu
      AllData[Pointer] = Parametro;
        Pointer++;

        for (count=0;count<13;count++) {
         Serial.print("Parametro dentro ARRAY numero");
         PRINTLN(count);
         Serial.println(AllData[count]);
         delay(1000);
       } 
        
    }
     }
   
    }
    myFile.close();
}
   
void loop() {

    
}

Next step will be to populate variables ( example var1, var2, var3 ... )

Just put the values in an array as I did and they can be used as normal variables, albeit without names. If you want meaningful variables names then you can't create them on the fly from strings read from the SD card because the names will be unknown to the compiler. What you could do is to declare them as normal then assign the corresponding value in an array to the variable