Pages: [1]   Go Down
Author Topic: Totally puzzled by infinite loop  (Read 873 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Alright, so I am having some trouble parsing data on an SD card (shocker). So the idea is that you access the a config file on an SD card and assign a few values, then add items in the body of the file to a 2D array. I can handle the 2D array and assigning values (at least I think), but I am having trouble getting past the first field in my config file. By the way, the 2D array is composed of buffers of 12 elements (ie byte example[20][12]). I know using 12 is a pain, but I have to for the given application. The buffers are shifted out to an external IC for translation. So here is my code:

Code:
#include <SD.h>
int chipSelect = 10;
int counter = 0; // Used for count the number of iterations
int currPosition = 0; // Used for keeping track of the current position (the 0 value wont be used)
boolean ignoreFlag = true; // true if you are supposed to ignore

void setup()
{
  Serial.begin(9600);
 
  pinMode(10, OUTPUT);
  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.print("failed!"); // If there is an issue, tell us and quit 
    return;
  }
  Serial.print("card initialized"); // You will only be here on success
  Serial.println();
 
  // Dump the file
  File comboFile = SD.open("egFile.txt"); // Open the combo file
  if (comboFile) { // If the file is availble
    while (comboFile.available()) {
      if (comboFile.peek() == ':') {  // If entering a zone
        ignoreFlag = !ignoreFlag;
        if (ignoreFlag) currPosition++; // When it switches to high
        comboFile.read();
      }
      // If not in an ignore zone write the stuff
      else if (!ignoreFlag)  Serial.write(comboFile.read();
    }
  comboFile.close(); // Close the file
  }
 
  // If the file isnt open produce an error
  else Serial.println("There was an error openeing the file");
}

void loop()
{
}

And here is the file it will be reading:

Code:
:field1: // This is a comment you can throw in
:field2:
// So is this

:field3:
:meter:
:101010101010,
101010101010,
101010101010,
101010101010,
101010101010
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,
101010101010,:

So ideally, the output would be

Code:
Initializing bla bla bla
field1
field2

and so on

Instead I get:
Code:
Initializing bla bla bla
field1

And thats it. So to investigate, I added a counter to the while (comboFile.available()) loop. To my surprise, this actually seems to be an infinite loop. I don't know if this is entirely unrelated, but I figured I would give you a heads up on what I have tried.

Thanks for your time, even if it is just to laugh at some egregious error =)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

All that you are doing with the data read from the SD card is printing it, one character at a time, to the serial port. If that data is interesting, you need to save it in a NULL terminated array of chars. Then, when you read the end of a packet (probably denoted by a carriage return or line feed (or both)), you need to parse the data and reset the array.

Your toggling of ignoreFlag when you see a colon is suspect. Some character to indicate comments and another to indicate data would be more logical.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, I forgot to mention that this is an excerpt to test the issue. But yep, I am pretty sure thats where it is.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 114
Posts: 4242
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The code that you posted won't compile because of a missing right parenthesis.

What is currPosition used for ?  It is initialised and incremented but never used.
How does comboFile.peek() know where to look in the file ?
Does it read the next byte and then update its own pointer to the next byte ?
Same questions for comboFile.read()
What is the difference between the two ?
How do you know that you have reached the end of the input file ?
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1726
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
while (comboFile.available()) {
      if (comboFile.peek() == ':') {  // If entering a zone
        ignoreFlag = !ignoreFlag;
        if (ignoreFlag) currPosition++; // When it switches to high
        comboFile.read();
      }
      // If not in an ignore zone write the stuff
      else if (!ignoreFlag)  Serial.write(comboFile.read());
    }

Where in that bit of code does ignoreFlag get cleared? When it comes across a ':', ok, but you missed something important.

What happens if you have this:

:Hi: :Low:

It will first detect the ':' and read it to move on to the next character. 'ignoreFlag' will be clear so it will read and print 'Hi'. Then it sees a ':' and 'ignoreFlag' becomes set. Now what? It will sit there constantly peeking at the ' ' between the colons, but it will never move on. There is nothing to increment the index in the file.

Code:
    while (comboFile.available()) {
      if (comboFile.peek() == ':') {  // If entering a zone
        ignoreFlag = !ignoreFlag;
        if (ignoreFlag) {
          currPosition++; // When it switches to high
        }
        comboFile.read();
      } else if (!ignoreFlag)  {
        Serial.write(comboFile.read()); // If not in an ignore zone write the stuff
      } else {
        comboFile.read(); //work through all characters that are in the ignore region by reading them.
      }
    }

An simpler alternative would be this:
Code:
    while (comboFile.available()) {
      char in = comboFile.read(); //read in the character
      if (in == ':') {  // If entering a zone
        ignoreFlag = !ignoreFlag;
        if (ignoreFlag) {
          currPosition++; // When it switches to high
        }
      } else if (!ignoreFlag)  {
        Serial.write(in); // If not in an ignore zone write the stuff
      }
    }



One last thing. I know it is a valid syntax, but it is best to not do things like:
Code:
if() code;

and stick to the more readable
Code:
if() {
  code
}
It makes it much clearer as to what is going on.
« Last Edit: January 04, 2013, 07:12:33 am by Tom Carpenter » Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sweet, this works perfectly. Cant believe I forgot about the dual colons. Quick question, when analyzing the body section (the 12 bit buffers), how do I take the result of myFile.peek() and add it to my array as a byte equal to its meaning as a string (ie "1000000000" translates to byte myArray[1][12]= {1,0,0,0,0,0,0,0,0,0,0,0})?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
how do I take the result of myFile.peek() and add it to my array as a byte equal to its meaning as a string (ie "1000000000" translates to byte myArray[1][12]= {1,0,0,0,0,0,0,0,0,0,0,0})?
First, don't. Use the result of myFile.read(), instead.

Second, you are not reading a string. You are reading a bunch of characters. So, 1 = '1' - '0'.

If you read a character and subtract '0' from it, you get its value as a number, if the character is in the range '0' to '9'.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Whoa! Sweet, thanks a million!
Logged

Pages: [1]   Go Up
Jump to: