SD.begin causing code to freeze? - Arduino Uno

Hi,
I am trying to make a code where i scan a barcode with a usb barcode scanner (connected to a usb host shield), which will then check a text file for that string and print the value on the same line in two other text-files. All on a microSD-card in a reader connected with pins to the Arduino Uno like so:

Pin 1 (~CS) to pin 4 on the Arduino
Pin 2 (MOSI) to pin 11 (MOSI) on the Arduino
Pin 3 (MISO) to pin 12 (MISO) on the Arduino
Pin 4 (SCK) to pin 13 (SCK) on the Arduino
Pin 5 (GND) to GND on the Arduino
Pin 6 (VCC) to 3.3V on the Arduino

The different MyParser functions does not seem to be called. When i try deleting the SD.begin from setup, the code runs as expected (without the SD functionality of course).

Here is the code:

#include <usbhid.h>
#include <usbhub.h>
#include <hiduniversal.h>
#include <hidboot.h>
#include <SPI.h>

#include <SD.h>

File liste1;
File liste2;
File liste3;

String searchString;

class MyParser : public HIDReportParser {
  public:
    MyParser();
    void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
  protected:
    uint8_t KeyToAscii(bool upper, uint8_t mod, uint8_t key);
    virtual void OnKeyScanned(bool upper, uint8_t mod, uint8_t key);
    virtual void OnScanFinished();
};

MyParser::MyParser() {}

void MyParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
  if (buf[2] == 1 || buf[2] == 0) return;

  for (uint8_t i = 7; i >= 2; i--) {
    if (buf[i] == 0) continue;

    if (buf[i] == UHS_HID_BOOT_KEY_ENTER) {
      OnScanFinished();
    }

    else {
      OnKeyScanned(i > 2, buf, buf[i]);
    }
    return;
  }
}

String barcodeString="";

uint8_t MyParser::KeyToAscii(bool upper, uint8_t mod, uint8_t key) {
  // Numbers
  if (VALUE_WITHIN(key, 0x1e, 0x27)) {
    return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
  }

  return 0;
}

void MyParser::OnKeyScanned(bool upper, uint8_t mod, uint8_t key) {
  uint8_t ascii = KeyToAscii(upper, mod, key);
  Serial.print((char)ascii);
  barcodeString += (char)ascii; 
}

void MyParser::OnScanFinished() {
  Serial.println("scanfinsiu start");
  String searchString = barcodeString;
  int startLine = 0, endLine = 0, currentLine = 0;

  liste1.seek(0);
  currentLine = 1;
  while (liste1.available()) {
    String line = liste1.readStringUntil('\n');
    if (line.indexOf(searchString) >= 0) {
      Serial.print("Found at line ");
      Serial.println(currentLine);
      Serial.print("String in liste1.txt: ");
      Serial.println(line);

      int liste2Line = currentLine - 1;
      liste2.seek(0);
      for (int i = 0; i < liste2Line; i++) {
        liste2.readStringUntil('\n');
      }
      String line2 = liste2.readStringUntil('\n');
      Serial.print("String in liste2.txt: ");
      Serial.println(line2);

      int liste3Line = currentLine - 1;
      liste3.seek(0);
      for (int i = 0; i < liste3Line; i++) {
        liste3.readStringUntil('\n');
      }
      String line3 = liste3.readStringUntil('\n');
      Serial.print("String in liste3.txt: ");
      Serial.println(line3);
      break;
    }
    currentLine++;
  }
  liste1.close();
  liste2.close();
  liste3.close();
  Serial.println("Search complete.");
  barcodeString = "";
}


USB          Usb;
USBHub       Hub(&Usb);
HIDUniversal Hid(&Usb);
MyParser     Parser;

bool isSDCardInitialized = false;

void setup() {
  Serial.begin( 115200 );
  if (Usb.Init() == -1) {
    Serial.println("OSC did not start.");
  }
  delay( 200 ); // Wait for USB initialization to complete
  Hid.SetReportParser(0, &Parser);


  while (!Serial) {
    ;
  }
  isSDCardInitialized = SD.begin(4);
  if (isSDCardInitialized) {
    Serial.println("SD card initialized.");
      liste1 = SD.open("liste1.txt");
      Serial.println(liste1);
      liste2 = SD.open("liste2.txt");
      Serial.println(liste2);
      liste3 = SD.open("liste3.txt");
      Serial.println(liste3);
      if (!liste1 || !liste2 || !liste3) {
        Serial.println("error opening files");
      }
  }
    else {
      Serial.println("SD card initialization failed!");
    }
  }
void loop(){
  Usb.Task();
}

Any help would be greatly appriciated!

Hi! Welcome to the Forum!

Thanks for posting your code in code tags.

Here goes my guesses:

  1. The CS pin must be set as an OUTPUT in order to avoid the UNO entering in slave mode. Keep in mind that the UNO standard pin for CS is pin 10.

  2. Double check if your SD card (module I presume) works at 3.3V.

Which Arduino and SD card module do you have? Post links.

If the Arduino is 5V, then you MUST use logic level shifters with a 3.3V SD card module. Some SD modules have those built in.

Also, the SD module requires 512 bytes of RAM, so it is possible that you are running out of memory.

So, pinMode(4, OUTPUT) i presume? If that is the case, it did not work.
I tried using pin 10 before, but i think it clashed with the USB Host Shield and wouldn't work.

Yes the module uses 3,3V and the UNO outputs 3,3V.

Forgot to mention; the sd card thing works on another piece of smaller code, where i just have a static string instead of input from barcode scanner:

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

File liste1;
File liste2;
File liste3;

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

  while (!Serial) {
    ;
  }

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

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

  Serial.println("initialization done.");

  liste1 = SD.open("liste1.txt");
  liste2 = SD.open("liste2.txt");
  liste3 = SD.open("liste3.txt");

  if (!liste1 || !liste2 || !liste3) {
    Serial.println("error opening files");
    while (1);
  }
}

void loop() {
  String searchString = "7044610874906";
  int startLine = 0, endLine = 0, currentLine = 0;

  liste1.seek(0);
  currentLine = 1;
  while (liste1.available()) {
    String line = liste1.readStringUntil('\n');
    if (line.indexOf(searchString) >= 0) {
      Serial.print("Found at line ");
      Serial.println(currentLine);

      int liste2Line = currentLine - 1;
      liste2.seek(0);
      for (int i = 0; i < liste2Line; i++) {
        liste2.readStringUntil('\n');
      }
      String line2 = liste2.readStringUntil('\n');
      Serial.print("String in liste2.txt: ");
      Serial.println(line2);

      int liste3Line = currentLine - 1;
      liste3.seek(0);
      for (int i = 0; i < liste3Line; i++) {
        liste3.readStringUntil('\n');
      }
      String line3 = liste3.readStringUntil('\n');
      Serial.print("String in liste3.txt: ");
      Serial.println(line3);
      break;
    }
    currentLine++;
  }

  liste1.close();
  liste2.close();
  liste3.close();
  Serial.println("Search complete.");
  while(1);
}

So i think it either clashes with the usb somehow or it's out of memory.
However it states in the output that "Global variables use 1539 bytes (75%) of dynamic memory, leaving 509 bytes for local variables. Maximum is 2048 bytes."

So shouldn't it be enough? Or is the "local variables" what is left for the sd card?

I use Arduino Uno and Pmod microSD reader (link: Pmod MicroSD - Digilent Reference)
Judging by it working earlier, I suppose it has logic level shifters built in (although I am no expert).

The Uno digital output pins produce 5V, which is what destroys 3.3V devices, unless you use logic level shifters. The damage has probably already been done, but you could try this logic level shifter board. Or you could have followed the instructions on the SD card product page, which recommended a different logic level shifter.

I suppose it has logic level shifters built in

No, it does not:

Capture

I use the 3,3V dedicated output on the Arduino UNO.
It has 3,3V and 5V and I am using 3,3V.

Either way, that is not the problem.
It works, just not in my code.

You still don't understand the problem. The digital output pins MOSI, SCK, CS, which you connected to the SD module, produce 5V. That destroys 3.3V devices.

Good luck with your Arduino projects, you will need it!

I see your point, however it is not what I need help with. As stated, the reader works, just not in my current code. Even if it might get fried later, it is still working as of now. I appriciate the heads up, but you didn't really answer my question, and rather just pointed out some unrelated mistake, so thanks for that.

I think the problem might be that the USB Host Shield and the SD card module are using the same pins for MOSI, MISO and SCK? I am not that familiar with this, but it does seem plausible.
Is there any way to define new MOSI, MISO and SCK pins for the SD card module, while letting the host shield have its own set?

A few suggestiong:

Only open one file on the SD card at a time, having multiple files open takes more memory.

Use the F() macro when printing text literals.

Do not use String variables, use char arrays instead.

Good tips, will come in handy later.
However, I am not so sure the problem lies within the memory.
It seems like any time i initiate the SD card and the scanner (the usb), it causes problems.
Could of course be wrong, but have tried removing a whole lot of code to where it should have more than enough memory, but still did not work (leaving only the sd and usb intializing).

If your using modules that are getting the wrong logic level signals, its possible the devices are interacting in a way that they would not if they were connected properly.

Do you have a link to the SD card module you are using ?

See post #4

The SD card module has no level shifters, just straight connections to the SD card, so is not suitable for a 5V processor.

A warning to the OP, when shopping for an SD card adapter, there is a design commonly used that does not properly release MISO, you will want to make sure to avoid this type board. See this thread https://forum.arduino.cc/t/microsd-card-hardware-fault-fixed/625442

Probably. And in this case it goes beyond my help capabilities. But there is one thing that called my attention and that I would try if the project was mine:

It comes from the SD card manufacturer site and sounded contraditory:

" The Pmod MicroSD is designed to communicate with the host board primarily through the SPI protocol. By default, the microSD card itself is defined to boot up in SD mode, but will enter into SPI mode when the Chip Select line is pulled low".

So maybe a test would be setting pin 4 as LOW just before SD.begin().

Did not work unfortunately :confused:

Yeah i suppose it could be related to the 5V instead of 3.3V, but then again, weird how it works without the usb device.

It also seems like the code never leaves setup, but that might just be a result of being out of memory or the sd card not initializing properly (while still not giving error in

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

I will try getting logic level shifters and see if it can fix the problem, unless anyone can see an error in the code that could be causing this.

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