Loading data from SD card

Hi. I have a file “CONFIG.TXT” saved on my SD card, the contents are as follow:

CONFIG.TXT

1,2,3,4,5,6,7,8,9,10

And I am trying to read the data and strong them into an array of integer.

#include <SD.h>

int CS_pin=4, SS_pin=10;
int config[10];

void setup(){
  Serial.begin(9600);
  pinMode(CS_pin, OUTPUT);
  pinMode(SS_pin, OUTPUT);
  SD.begin(CS_pin);
  readConfig;
  printConfig;
}

void loop(){
}

void readConfig(){
  File configFile = SD.open("CONFIG.TXT");
  if(configFile){
    for(int i=0;i<10;i++) //EDIT: TYPO FIXED
      config[i]=configFile.parseInt();
  }
  configFile.close();
  return;
}

void printConfig(){
for(int i=0; i<10; i++)
  Serial.println(config[i]);
}

The Arduino freezes and nothing happen. I think it has to do with the inappropriate use of parseInt(). Can anyone let me know how am I suppose to fix the issue? Thanks in advance!

    for(int i;i<10;i++)

Local variables, like i, are not initialized. They hold whatever garbage was left in that memory location. It amazes me that anyone would NOT set an initial value in a situation like this.

Thanks for your response, but that is not the problem as I still get no response from the Arduino. I believe there is something wrong with these couple of lines:

if(configFile){
  for(int i=0;i<10;i++)
    config[i]=configFile.parseInt();
}

If you fail to open the config file, you close it anyway. That would be dereferencing a null pointer, which is never good. I suggest you put the ‘close’ logic inside the ‘if file opened successfully’ code.

Also, if you aren’t sure where it has got to then add print statements to see how far it is getting.

but that is not the problem

It most certainly is. What if i has an initial value, because you couldn't be bothered assigning it one of -12743? Is that in the range of your array? What if the initial value is 17832? Is that in the range of your array?

What do you think happens when you stomp all over memory you don't own?

I am sorry. I do recognized not initializing i is a problem, but that was a typo when I type the code on the forum. What I meant is that even with i initialized to 0, the Arduino still won't response. I apologize for the confusion I caused.

The Arduino freezes and nothing happen. I think it has to do with the inappropriate use of parseInt(). Can anyone let me know how am I suppose to fix the issue? Thanks in advance!

See what this tells you. It should cut out a good bit of guesswork:

#include <SD.h>

int CS_pin=4, SS_pin=10;
int config[10];

void setup()
{
  Serial.begin(9600);
  pinMode(CS_pin, OUTPUT);
  pinMode(SS_pin, OUTPUT);
  SD.begin(CS_pin);
  readConfig;
  printConfig;
}

void loop()
{
}

void readConfig()
{

    Serial.print( "\n reading\n " );

  File configFile = SD.open("CONFIG.TXT");
  if(configFile)
  {
    for(int i=0;i<10;i++) //EDIT: TYPO FIXED

    Serial.print( i );

      config[i]=configFile.parseInt();

    Serial.println( config[ i ] );

  }

  Serial.print( "\n done reading \n" );

  configFile.close();

  Serial.print( "\n file closed\n" );

  return;
}

/* and here you have a real problem, this is your code
void printConfig(){ // have you ever noticed how easy it is to look at (){ and only see ()?
for(int i=0; i<10; i++) 
  Serial.println(config[i]);
}
*/

// fixed 
void printConfig()
{
  for(int i=0; i<10; i++) 
  {
    Serial.println(config[i]);
  }
}

Thanks for all the help. I figured out why it didn't work. Instead of

  readConfig();
  printConfig();

I wrote

  readConfig;
  printConfig;

Unbelievable :sweat_smile:

That too.

Okay… a new issue shows up and I am having some problem resolving it.

I has confirmed that this code works.

#include <SD.h>

int CS_pin=4, SS_pin=10;
int config[10];

void setup(){
  Serial.begin(9600);
  pinMode(CS_pin, OUTPUT);
  pinMode(SS_pin, OUTPUT);
  SD.begin(CS_pin);
  readConfig();
  printConfig();
}

void loop(){
}

void readConfig(){
  File configFile = SD.open("CONFIG.TXT");
  if(configFile){
    for(int i=0;i<10;i++)
      config[i]=configFile.parseInt();
    configFile.close();
  }
}

void printConfig(){
  for(int i=0; i<10; i++){
    Serial.println(config[i]);
  }
}

with CONFIG.TXT

0,1,2,3,4,5,6,7,8,9

and serial monitor prints

0
1
2
3
4
5
6
7
8
9

Now I would like to have a I2C master to request those values from the slave with the SD card. On the slave side, I declared the array as…

int config[10]={100,101,102,103,104,105,106,107,108,109};

for testing purposes. And I still have the CONFIG.TXT with

0,1,2,3,4,5,6,7,8,9

Here is the requestEvent() function on the slave:

void requestEvent(){
  Serial.print("HAHA");
  File configFile = SD.open("CONFIG.TXT");
  if(configFile){
    for(int i=0;i<10;i++)
      config[i]=configFile.parseInt();
    configFile.close();
  }
  union{
    int configs [10];
    byte buf [2];
  }
  configUnion;
  for(int i=0;i<10;i++)
    configUnion.configs [i] = config[i];
  Wire.write((byte *) &configUnion, sizeof configUnion);
}

If I comment the following:

/*File configFile = SD.open("CONFIG.TXT");
  if(configFile){
    for(int i=0;i<10;i++)
      config[i]=configFile.parseInt();
    configFile.close();
  }*/

it works perfectly. The slave prints “HAHA” and the master is able to obtain 100,101,102,103,104,105,106,107,108,109. But as soon as I de-comment those lines, I get nothing from both the slave and master, not even the “HAHA”. I don’t think it has to do with coding. Maybe insufficient memory?

requestEvent is a form of ISR (interrupt service routine). They are supposed to be fast.

http://www.gammon.com.au/interrupts


  Serial.print("HAHA");

Do not do serial prints inside an ISR.


  File configFile = SD.open("CONFIG.TXT");

Do not open files inside an ISR. Opening files is not only slow but probably relies on interrupts, which are turned off at this point.

  union{
    int configs [10];
    byte buf [2];
  }

The size of each entry in the union MUST be the same size. Your first entry is 20 bytes. Your second entry is 2 bytes.

union{
  int configs [10];
  byte buf [2];
}

I don't quite get how the 1st entry is 20 bytes and the 2nd entry is 2 bytes. I thought I made it such that there are 10 integers and each integer is 2 bytes. Can you please explain it a little bit more? Thanks.

The first entry is:

int configs [10];

That is 20 bytes.

The second entry is:

byte buf [2];

That is two bytes.

2 is not equal to 20.