ESP8266 - SD CARD and RFID not working together / spi conflict

Hi I'm new with Arduino and I have been working on Node MCU ESP8266MOD with RC522 and MicroSD Card Adapter.. my code works but when I tried connecting MicroSD Card the RC522 RF Tag Reader will not work.. need your help on any suggestion that could fix this problem. TIA

Here's my code for your reference

#include <ESP8266WiFi.h>
#include <ESP8266Ping.h>
#include <SPI.h>
#include <MFRC522.h>
#include <SD.h> // Required for SD card logging

// WiFi Credentials
const char* ssid = "Wifi Name";
const char* password = "wifi password";

// RC522 Pins
#define SS_PIN D4 // SDA (CS)
#define RST_PIN D3 // RST

// SD Card Pin
#define SD_CS_PIN D8

// LED Pins
const int ledWiFiConnected = D1;
const int ledWiFiDisconnected = D2;

MFRC522 rfid(SS_PIN, RST_PIN);

// Timing
unsigned long lastWiFiCheck = 0;
unsigned long lastInternetCheck = 0;
const unsigned long wifiCheckInterval = 5000;
const unsigned long internetCheckInterval = 10000;

// Status Flags
bool isWiFiConnected = false;
bool isInternetConnected = false;

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

pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH);
pinMode(SD_CS_PIN, OUTPUT);
digitalWrite(SD_CS_PIN, HIGH);

rfid.PCD_Init();
delay(100);

byte version = rfid.PCD_ReadRegister(MFRC522::VersionReg);
if (version == 0x00 || version == 0xFF) {
Serial.println("ERROR: RC522 not found. Check wiring and power.");
} else {
Serial.print("RC522 Firmware Version: 0x");
Serial.println(version, HEX);
}

pinMode(ledWiFiConnected, OUTPUT);
pinMode(ledWiFiDisconnected, OUTPUT);
digitalWrite(ledWiFiConnected, LOW);
digitalWrite(ledWiFiDisconnected, HIGH);

WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi...");
}

void loop() {
scanRFID();
checkWiFiStatus();
if (WiFi.status() == WL_CONNECTED) {
checkInternetStatus();
}
}

void scanRFID() {
activateRC522(true);

if (!rfid.PICC_IsNewCardPresent()) {
activateRC522(false);
return;
}

if (!rfid.PICC_ReadCardSerial()) {
Serial.println("Card detected but failed to read.");
activateRC522(false);
return;
}

String uidString = "";
for (byte i = 0; i < rfid.uid.size; i++) {
uidString += (rfid.uid.uidByte[i] < 0x10 ? "0" : "");
uidString += String(rfid.uid.uidByte[i], HEX);
}
uidString.toUpperCase();

Serial.print("RFID Tag UID: ");
Serial.println(uidString);

// Deactivate RFID before logging to SD
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
activateRC522(false);

// Log to SD
activateSDCard(true);
if (SD.begin(SD_CS_PIN)) {
File logFile = SD.open("/rfid_log.txt", FILE_WRITE);
if (logFile) {
logFile.print("UID: ");
logFile.print(uidString);
logFile.print(" | Time: ");
logFile.println(millis());
logFile.close();
Serial.println("Logged to SD card.");
} else {
Serial.println("Failed to open log file.");
}
} else {
Serial.println("SD Card not available.");
}
activateSDCard(false);
}

void checkInternetStatus() {
unsigned long currentMillis = millis();
if (currentMillis - lastInternetCheck >= internetCheckInterval) {
lastInternetCheck = currentMillis;

IPAddress targetIP;
WiFi.hostByName("www.google.com", targetIP);
bool pingResult = Ping.ping(targetIP, 1);

if (pingResult && !isInternetConnected) {
  Serial.println("Internet access confirmed!");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  isInternetConnected = true;
  digitalWrite(ledWiFiConnected, HIGH);
  digitalWrite(ledWiFiDisconnected, LOW);
} else if (!pingResult && isInternetConnected) {
  Serial.println("Lost Internet access.");
  isInternetConnected = false;
  digitalWrite(ledWiFiConnected, LOW);
  digitalWrite(ledWiFiDisconnected, HIGH);
}

}
}

void checkWiFiStatus() {
unsigned long currentMillis = millis();
if (currentMillis - lastWiFiCheck >= wifiCheckInterval) {
lastWiFiCheck = currentMillis;

if (WiFi.status() != WL_CONNECTED) {
  Serial.println("WiFi Disconnected. Reconnecting...");
  WiFi.begin(ssid, password);
  digitalWrite(ledWiFiConnected, LOW);
  digitalWrite(ledWiFiDisconnected, HIGH);
  isWiFiConnected = false;
  isInternetConnected = false;
} else if (!isWiFiConnected) {
  Serial.println("WiFi Connected.");
  digitalWrite(ledWiFiConnected, HIGH);
  digitalWrite(ledWiFiDisconnected, LOW);
  isWiFiConnected = true;
}

}
}

void activateRC522(bool active) {
digitalWrite(SS_PIN, active ? LOW : HIGH);
}

void activateSDCard(bool active) {
digitalWrite(SD_CS_PIN, active ? LOW : HIGH);
}

Thanks @MaximoEsfuerzo for your reply and base on their topic on that thread it seems be that the are using Arduino UNO. However, I'm using ESP8266. I have checked ESP8266 operates at 3.3V while Arduino Uno uses 5V..

Addition to it, I suspected that it is not only SPI conflict but the power is not enough to supply both RC522 and MicroSD Card Adapter as I have tried to disconnect the 3.3v jumper of MicroSD Adapter from the board and the RC522 works but when I connect it back again both are not working(Correct me if I'm wrong with this) TIA

The problem with the SPI bus is caused by the microSD module regardless of the board to which it is connected.

If you are using a generic uSD adapter board such as this:

there are two problems. First, they are meant for 5V boards like an Uno, not a 3.3V board like an ESP8266. Second, due to a mistake in the PCB, they don't release the MISO line when not selected, so they can't be used with anything else (like your RFID board) on the SPI bus.

With a 3.3V board like an ESP8266, what you want is a simple uSD breakout board with no level shifters, no buffers, nothing. Something like this:

1 Like

can you give a link to the SD card reader your are using?

if the SD card is sharing a SPI bus with other devices there can be problems - see Sharing the SPI bus among SD card and other SPI devices

with the ESP32 I tend to use the HSPI interface for the SD card and VSPI for other SPI devices

the ESP8266 has two SPI interfaces so you try the same approach

Thank you, yes I'm using the generic one

I might buy a new this kind of MicroSD Adapter instead as suggested to my problem I will update you all as soon as I got MicroSD Adapter with lower voltage

Thanks @MaxomoEsfuerzo, I'll consider this as well

Hi @horace

I'm using this MicroSD card

thinking again I have shared a SD card reader and an MFRC522 RFID reader on the ESP32 VSPI bus

the SD card reader is a Micro SD TF Card Reader Slot Module with SPI Interface for ESP32 Arduino Pi ESP
which does not have the level shifter etc shown on the SD reader in post 9 which may be a problem when sharing the SPI bus by not tri-stating the MISO line correctly

I have Arduino UNO.. I'm thinking that maybe I can try to put the VCC of the MicroSD Card Adaptor to the 5v of Aruino Uno while the other modules/slaves are connected to the 3v of ESP8266? or it will fry my ESP8266?

cannot see how that would help
if you need 5V use the VIN pin of the ESP8266

is it is safe to use the VIN as I'm just being careful not to fry the ESP8266 as I only have limited time and resource as of the moment.. could you confirm?

not recommended
I assume if powered from VIN (5V) the level converter converts to 3.3V logic level of the SD card to 5V on the IO pins which could damage the ESP8266

the SD card reader in post10 is labeled explicitly 3.3V power suitable for ESP32, ESP8266, etc

The level shifter on the SD module is only one-way. It converts the three SPI outputs from the Arduino to 3.3V for the SD card, but it only converts the MISO line from the SD card to 3.3V, and in the process fails to release that line.

However, there is a fix for the module he has that should work as long as he can power the SD module with 5V. It consists of cutting one trace and soldering in one wire. Basically, it just lets the SD card drive the MISO line directly, bypassing the level shifter. The card itself knows to tri-state the line when it should.

2 Likes

I should add that I think you can even power the SD module with 3.3V if you short the 3.3V voltage regulator's input to its output. That bypasses the regulator and supplies 3.3V to the SD card and to the level shifter.

I think the regulator is just the typical AMS1117 type pinout. In the picture above, the pin on the right is the input, and the middle pin is the output, which is also on the tab.

ported the ESP32 test program which shared a SD card reader and an MFRC522 RFID reader on the VSPI bus to a ESP8266
simply changed Tolls>Board from "ESP32 Dev Module" to "Generic ESP8266 Modules" - compiles and loads OK (used same CS GPIO pins on ESP32 and ESP8266 and same SD and MFRC522 modules)

test code main.ino file


// ESP32 MFRC522 RFID reader and SD card reader on VSPI - works OK

// ESP8266 version DOES NOT WORK!!!
// RFID initialises OK but does not read tags
// SD reader displays directory OK
// comment out SDsetup() RFID reader works OK 

#include <MFRC522v2.h>
#include <MFRC522DriverSPI.h>
#include <MFRC522DriverPinSimple.h>
#include <MFRC522Debug.h>

MFRC522DriverPinSimple ss_1_pin(15);  // Configurable, take an unused pin, only HIGH/LOW required, must be different to SS 2.
MFRC522DriverSPI driver{ ss_1_pin };
MFRC522 reader{ driver };

void SDsetup();  // SD card prototypes
void SDloop();

void setup() {
  Serial.begin(115200);  // Initialize serial communications with the PC for debugging.
  while (!Serial)
    ;  // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4).
  delay(2000);
  Serial.println("\n\nESP32 MFRC522 RFID reader and SD card reader on VSPI");
  // ESP8266 comment out SDsetup() RFID reader works OK 
  SDsetup();  // ESP8266 SD card initialse - works heere and at end of setup()
  Serial.println("\n\nESP32 MFRC522 RFID reader and SD card reader on VSPI");
  reader.PCD_Init();  // Init MFRC522 card.
  Serial.print(F("Reader "));
  static uint8_t i = 0;
  i++;
  Serial.print(i);
  Serial.print(F(": "));
  MFRC522Debug::PCD_DumpVersionToSerial(reader, Serial);
  // SDsetup();  // SD card initialse
}

void loop() {
  delay(2000);
  // if keyboard hit read SD card
  if (Serial.available()) {
    while (Serial.available()) Serial.read();
    SDloop();  // check SD card
  }
  Serial.println("reading RFID");
  // Look for new RFID cards.
  if (reader.PICC_IsNewCardPresent() && reader.PICC_ReadCardSerial()) {
    Serial.print(F("Reader "));
    static uint8_t i = 0;
    i++;
    Serial.print(i);
    // Show some details of the PICC (that is: the tag/card).
    Serial.print(F(": Card UID:"));
    MFRC522Debug::PrintUID(Serial, reader.uid);
    Serial.println();
    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = reader.PICC_GetType(reader.uid.sak);
    Serial.println(MFRC522Debug::PICC_GetTypeName(piccType));
  }
  // MFRC522 Halt PICC. (othersie SD card does not work)
  reader.PICC_HaltA();
  // Stop encryption on PCD.
  reader.PCD_StopCrypto1();
}

listfiles.cpp (place in same directory as above main.ino file)

// ESP8266 SD card listfile

/*
  Listfiles

  This example shows how print out the files in a
  directory on a SD card

  The circuit:
   SD card attached to SPI bus as follows:
 ** MOSI - pin 13
 ** MISO - pin 12
 ** CLK - pin 14
 ** CS - pin 5

  created   Nov 2010
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe
  modified 2 Feb 2014
  by Scott Fitzgerald

  This example code is in the public domain.

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

File root;

void printDirectory(const char * dirname);

void SDsetup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);

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

  if (!SD.begin(5)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  printDirectory("/");
  Serial.println("done!");
}

void SDloop() {
  printDirectory("/");
  Serial.println("done!");
  // nothing happens after setup finishes.
}

void printDirectory(const char * dirname) {
   File root = SD.open(dirname);
  if(!root){
    Serial.println("Failed to open directory");
    return;
  }
  if(!root.isDirectory()){
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while(file){
    if(file.isDirectory()){
      Serial.print("  DIR : ");
      Serial.println(file.name());
      //if(levels){
      //  listDir(fs, file.name(), levels -1);
      //}
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }}

both SD reader and MFRC522 RFID reader work OK in separate programs

using the above code

  1. RFID initializes OK but does not read tags - SD reader displays directory OK
  2. comment out call to SDsetup() RFID reader works OK

work separately but cannot get both to work together!!
guess there is some difference between the ESP32 and ESP8266 - either a hardware problem or different libraries

photo

serial output of above program (SD card reads OK MFRC522 initializes but does not read tags)

ESP32 MFRC522 RFID reader and SD card reader on VSPI
Reader 1: Firmware Version: 0x92 = v2.0
  DIR : System Volume Information
  FILE: TestNumber.txt  SIZE: 2
  FILE: test1.dat  SIZE: 14145
  FILE: test2.dat  SIZE: 260
  FILE: test3.dat  SIZE: 170
  FILE: test4.dat  SIZE: 1350
  FILE: test5.dat  SIZE: 15
  FILE: test6.dat  SIZE: 2250
  FILE: test7.dat  SIZE: 45
  FILE: test8.dat  SIZE: 2575
  FILE: test9.dat  SIZE: 4500
  FILE: test10.dat  SIZE: 1920
  FILE: test11.dat  SIZE: 5
  FILE: test12.dat  SIZE: 9715
  FILE: test13.dat  SIZE: 19115
  FILE: test14.dat  SIZE: 49715
  FILE: test15.dat  SIZE: 3020
  FILE: test16.dat  SIZE: 5
  FILE: test.txt  SIZE: 1048576
  FILE: foo.txt  SIZE: 13
  FILE: test17.dat  SIZE: 80
  FILE: test18.dat  SIZE: 7
  FILE: test19.dat  SIZE: 7
  FILE: test20.dat  SIZE: 7
done!
reading RFID
reading RFID
reading RFID
reading RFID
reading RFID
reading RFID

serial output of program with call to SDsetup() commented out (MFRC522 reads RFID tags OK)


08:23:30.896 -> ESP32 MFRC522 RFID reader and SD card reader on VSPI
08:23:30.961 -> Reader 1: Firmware Version: 0x92 = v2.0
08:23:32.941 -> reading RFID
08:23:35.017 -> reading RFID
08:23:37.062 -> reading RFID
08:23:39.106 -> reading RFID
08:23:41.149 -> reading RFID
08:23:41.149 -> Reader 1: Card UID: BF EC 0C 04
08:23:41.149 -> PICC type: MIFARE 1KB
08:23:43.188 -> reading RFID
08:23:45.233 -> reading RFID
08:23:45.233 -> Reader 2: Card UID: 4E 06 0C 04
08:23:45.233 -> PICC type: MIFARE 1KB
08:23:47.276 -> reading RFID

I was able to find the solution and make them work by adding a 220 resistor in the MISO of MicroSD Card Adapter

I remember and used this diagram and was able to have them work together

Yes, the resistor lets the misbehaving MISO line act like a pullup or pulldown resistor on the other device, which is still able to work. But I suspect a good bit higher resistance value would also work, which would lessen the wasted current in this setup.

tested by setup (code and photo in post 17) with 220K and 1Mohm resistors in SD card MISO line

  1. MFRC522 RFID reader initializes but does not read RFID tags
  2. SD card fails to initialize