6

I am trying to read a text file "Print1.txt", line by line, from an SD card attached to my Arduino MEGA. So far I have the following code:

#include <SD.h>
#include <SPI.h>
int linenumber = 0;
const int buffer_size = 54;
int bufferposition;
File printFile;
char character;
char Buffer[buffer_size];
boolean SDfound;


void setup()
{
  Serial.begin(9600);
  bufferposition = 0;
}

void loop() 
{
  if (SDfound == 0)
  {
    if (!SD.begin(53)) 
    {
      Serial.print("The SD card cannot be found");
      while(1);
    }
  }
  SDfound = 1;
  printFile = SD.open("Part1.txt");


  if (!printFile)
  {
    Serial.print("The text file cannot be opened");
    while(1);
  }

  while (printFile.available() > 0)
  {
    character = printFile.read();
    if (bufferposition < buffer_size - 1)
    {
      Buffer[bufferposition++] = character;
      if ((character == '\n'))
      {
        //new line function recognises a new line and moves on 
        Buffer[bufferposition] = 0;
        //do some action here
        bufferposition = 0;
      }
    }

  }
  Serial.println(Buffer);
  delay(1000);
}

The function returns only the first line of the text file repeatedly.

My Question

How do I change the function to read a line of text, (with the hope to perform an action on such line, shown by "//do some action") and then move onto the next line in the subsequent loop, repeating this until the end of file has been reached?

Hopefully this makes sense.

Julian Das
  • 1,351
  • 3
  • 11
  • 9
  • Why don't you just perform the action using the content of `Buffer` before this line `Buffer[bufferposition] = 0`? – Arton Dorneles Feb 18 '16 at 21:31
  • 1
    @ArtonDorneles What do you think are good points of this change? I don't think do some actions to the `Buffer` before terminating the string is a good idea. – MikeCAT Feb 19 '16 at 13:58
  • I don't think opening a file and not closing it is good. – MikeCAT Feb 19 '16 at 14:03
  • Sorry, I wanted to say **after** `Buffer[bufferposition] = 0`. At this point you have a valid string in your buffer that you can use to trigger any action. However, note that you is including a `\n` character as last character. This can be an issue when processing the line. In order to remove it, just replace `Buffer[bufferposition] = 0;` by `Buffer[bufferposition-1] = 0;`. There is nothing wrong in keeping the file open while processing the commands. You can close it after reading the whole data. – Arton Dorneles Feb 19 '16 at 14:16
  • @ArtonDorneles Thank you for your help regarding the '\n' character. However my issue is not carrying out the action on the line, it is the method to read the next line of the text file for further action. So for example: line 1: G1 X19.500 Y9.000 line 2: G1 X-19.500 Y-9.000 line 3: etc.... how to read the next line and then successive lines till the EOF. Any ideas? thank you in advance. – Julian Das Feb 19 '16 at 15:15
  • So, do want to read all the lines before carrying out some action? – Arton Dorneles Feb 19 '16 at 16:59
  • @ArtonDorneles Well each line is data for motors to use so I want to read a line from the SD, then carry out the action (move motors etc) and then read the next line etc. Hope that makes sense – Julian Das Feb 19 '16 at 21:04
  • The code I presented in my answer does exactly this. You just need to replace insert the code to move the motors below the line indicated by `//do some action here`. The while loop will read one line each time and the content of the line will be stored in the variable `buffer`. – Arton Dorneles Feb 19 '16 at 21:20
  • Thank you so much for your help! Think it's working now – Julian Das Feb 19 '16 at 21:44

1 Answers1

14

Actually, your code returns only the last line of the text file because it is printing the buffer only after reading the whole data. The code is printing repeatedly because the file is being opened inside the loop function. Usually, reading a file should be done in the setup function that is executed only one time.

Instead of reading the data char by char into the buffer, you could read until find the delimiter and assign that to a String buffer. This approach keep your code simple. My suggestion to fix your code is right below:

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

File printFile;
String buffer;
boolean SDfound;


void setup() {
  Serial.begin(9600);

  if (SDfound == 0) {
    if (!SD.begin(53)) {
      Serial.print("The SD card cannot be found");
      while(1);
    }
  }
  SDfound = 1;
  printFile = SD.open("Part1.txt");

  if (!printFile) {
    Serial.print("The text file cannot be opened");
    while(1);
  }

  while (printFile.available()) {
    buffer = printFile.readStringUntil('\n');
    Serial.println(buffer); //Printing for debugging purpose         
    //do some action here
  }

  printFile.close();
}

void loop() {
   //empty
}
Arton Dorneles
  • 1,629
  • 14
  • 18