SD Card Usage - not reading entire file

I have written some code that reads data.txt from an SD card. To test it I have written a script that displays the chord data. However, for some reason its not reading the entire array, but only 7 of the 8 string fields (the last chord C# add4 doesn't seem to be in the array). Wracking my brain here. These array's must be read or the script that uses the SD read/write peace won't work properly. Any help is appreciated!

Here's the code followed by the data.txt file:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); 

const int SD_CS_PIN = 10;            // Chip select pin for SD card module
const char filename[] = "data.txt";  // File name for storing and reading the matrix
int button_assignments[8][4];        // number array that will be loaded from SD card
const char* chord_names[8];          // string array that will be loaded from SD card                                                          
void setup() {
//
// Initialize the display
// Clear the display
// Turn on the backlight
//
    lcd.init();
    lcd.backlight();
    lcd.clear();
//    
// Initialize the SD card
//
  if (!SD.begin(SD_CS_PIN)) {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("SD card");
    lcd.setCursor (0,1);
    lcd.print("Initialization failed!");
    while (1);
  }
    //
    // Read the matrix from the SD card function
    //
    readMatrix();
    //
    //
    // 
}
void loop() 
{
  for (int i = 0; i<8; i++) {
   lcd.setCursor(0,0);
   lcd.print(String(chord_names[i])); // print chord names from the array
   delay(2000);
   lcd.clear();
}
}  
///////////////////////////////////////////////
///////     Clear memory before reading   /////
//////////////////////////////////////////////
void freeChordNamesMemory() {
  for (int i = 0; i < 8; i++) {
    if (chord_names[i] != NULL) {
      delete[] chord_names[i];  // Free the memory
      chord_names[i] = NULL;    // Set the pointer to NULL
    }
  }
}
///////////////////////////////////////////////
///////     Read Matrix From SD Card     /////
//////////////////////////////////////////////
void readMatrix() {
  File file = SD.open("data.txt", FILE_READ);
  if (file) {
    // Read button_assignments array
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 4; j++) {
        button_assignments[i][j] = file.parseInt();
      }
    }
    //
    // Read chord_names array
    //
    for (int i = 0; i < 8; i++) {
      String chordStr = file.readStringUntil('\n');      // Allocate memory and copy the string from chordStr to chord_names[i]
      chord_names[i] = new char[chordStr.length() + 1];  // Allocate memory
      strcpy(chord_names[i], chordStr.c_str());          // Copy the string
    }
    file.close();
  } else {
    lcd.clear();
    lcd.print("Error opening data.txt");
  }
}

data.txt file contents:
60 64 67 72
65 69 72 76
70 74 77 81
75 79 82 86
80 84 87 91
85 89 92 96
90 94 97 101
95 99 102 106
C Maj
D Min
E 7th
F maj7th
G min7th
A sus4
B sus2
C# add4



A "string" is terminated by a null character, x'00. Are sure the eighth string has a null at the end? Did you print the file,in hex, on you pc?

Off the top of my head, I'll guess that the last line in the file doesn't have a cr/lf at the end. Dump the file in hex to check. Or just open it up in a text editor, go to the end and hit the enter key a time or two.

I tried entering a blank line after the last string. I'll try adding more blank lines.

OK. Converted to hex.

characters are 0d0a0d0a

So there's a cr/lf at the end of the file.

Be mindful of the dynamic allocation. These Arduino micros don't have a garbage collector like your PC does, and they have very limited amounts of memory. If you fragment the heap too much then your program will crash.

But there is no null there, so it is NOT a string. Your code told us you are reading strings.

Got it working. I modified the line to read and discard the remainder of the line (including the newline character) after the midi chord numbers array is read (the first half of the file), before starting to read the chord_names` . That ensures that the reading starts at the beginning of the chord names.

Appreciate the help!

I have a sub routine to dump the memory and reload when updates are made to the data.txt file are made (not reflected in this script). The file won't be any larger than what I provided. Haven't seen any problems yet, but thanks for the watch out!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.