2

Ok, I'm fairly new to Arduino and I'm trying to read bytes from a file in an SD card and convert to integer values (0-255).

I have a file, with 1 byte on it (128 int value, created in Python, can provide the code if necessary) and the hex dump (binary mode) is:

xxd -b single_byte.dat
00000000: 10000000

So far so good, right? So I was expecting to read this byte from the file (SD card) and then convert back to 128 value. This is my Arduino code:

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

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  delay(100);
  Serial.print("\nInitializing SD card...");

  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    while (1);
  }

  File file;
  byte one_byte;
  int dec_value;

  file = SD.open("single_byte.dat", FILE_READ);
  one_byte = file.read();
  file.close();
  
  dec_value = int(one_byte);

  Serial.println(dec_value, DEC);
  
}

void loop(void) {
}

I was expecting the output to be 128.

However I get:

Actual output

What am I missing? (yes, I tried generating the .dat file with big-endian encoding, same result)

9
  • Which version of Python are you using? "Note: Since Python 3.6, all files are read and written by Python using utf-8 by default, even on Windows." Maybe you are writing UTF16 and do not realize it. What happens if you try to read the next byte, and the next?
    – st2000
    Commented Jul 9, 2023 at 23:06
  • I'm using Python 3.9 (on Debian 11)... I haven't tried reading more bytes but, the hex dump displays a single byte on the file so, I think file is ok?
    – melev
    Commented Jul 9, 2023 at 23:10
  • 1
    Oh, I think I see what you did. Try adding SD.begin.
    – st2000
    Commented Jul 9, 2023 at 23:36
  • I just tried adding the SD.begin(4) code, no luck, same result as before: message "initialization done" is displayed, but the output on my variable is the same. What else can I try? Maybe the int(one_byte) is not the way to go and something else (bit manipulation?) must be done?
    – melev
    Commented Jul 10, 2023 at 2:18
  • 1
    @Fahad I got it working, it was the freaking filename that was the problem, check my answer. Thanks!
    – melev
    Commented Jul 10, 2023 at 4:55

2 Answers 2

5

Ok, I got it working now, here's what was happening:

Turns out the file wasn't being opened. Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:

root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE)

And sure enough my file was not detected as single_byte.dat but it was something like: single_~.dat so I renamed the file to test.dat and tada! code now works like a charm.

I guess I overlooked this restriction on the documentation, so keep this in mind when you use an SD card.

Also, make sure to check if you are really opening your file because no exception will be thrown if you reference an uninitialized file pointer I guess.

Just make sure to have:

file = SD.open(filename, FILE_READ);
if(file){
    // Do things here.
}
else{
    Serial.println("You're out of luck: Can't open file");
}

Ok, there goes my Sunday. Thanks all for reading!!!

2
  • 1
    The root of this restriction is partly Microsoft and partly the library. On one hand Microsoft stuffed long file names on their old FAT filesystems trying to be backwards compatible. Each files has a 8+3 short name and following some directory entries for the long name. On the other hand the library apparently saves on size and left out the code to work with long names. -- However, the main lesson you learned is: Always check return values! Commented Jul 10, 2023 at 6:03
  • 1
    Ah, good catch! So you asked: "Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:" The "Why" is because the FAT file system format dates back from when Bill Gates grabbed something called DOS from some computer club. That fixed all file names to 8.3 or an eight-characters-decimal-point-three-character format. That still exists. Some clever workarounds are used to hide it. But it still exists. So the actual file name gets "mangled" when you try to go beyond the 8.3 format. I think the clever trick is that they all get "mangled" uniquely.
    – st2000
    Commented Jul 10, 2023 at 12:43
1

Consider adding a call to SD.begin() as is done in the example found on this arduino.cc web page.

Here's the section of the example code where SD.begin() is used:

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

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.