SDfat and rfid

Hi there guys, so I'm having a little bit of a problem with using an rfid scanner and sd module together. I'm using the SDfat library by William Greiman (which has been fantastic) and the rfid library by Miguel Balboa. So I have both rfid and sd modules connected to one Arduino via SPI with the rfid SS pin on D10 and SD SS pin on D4. I can use each library separately (such as the examples) and they work fine with scanning cards, reading and writing to an sd card etc... However when it comes to using both combined I can't open a file to read it.

FYI, I have not placed any pull up resistors on the SS lines, opting to bring the pins HIGH with software in setup. I have also not put a diode on the second SPI device MISO line either which I have seen in some multi SPI device connections.

My code I have whipped up is here:

#include <SPI.h>
#include <MFRC522.h>
#include "SdFat.h"

SdFat sd;
SdFile cardsFile;
SdFile regFile;

#define RST_PIN   9    // Configurable pin, see default layout
#define SS_PIN    10   // Configurable pin, see default layout

#define chipSelect 4  //select SPI line for SD Card

String strUID = "";
char UID[30];

char line[100];
int stringIndex = 0;
char readIn;
int i = 0;
int j;
int cardPresent;
int check =0;

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

MFRC522::MIFARE_Key key;  // Set key



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);  // Initialise serial communication with PC
  SPI.begin();         // Init SPI bus
  mfrc522.PCD_Init();  // Init MFRC522 hardware

  //Initialise pinModes for SPI select lines
  pinMode(SS_PIN, OUTPUT);
  pinMode(chipSelect, OUTPUT);

  digitalWrite(SS_PIN, HIGH);

  digitalWrite(chipSelect, HIGH);


  // Prepare key - all keys are set to FFFFFFFFFFFF at chip delivery from the factory
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  
  Serial.println("Initialising SD Card");
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
    sd.initErrorHalt();
  }
  Serial.println("SD Card initialised");

  //digitalWrite(chipSelect, LOW);

}

void loop() {  

  check = 0;

  //Activate rfid communication
  digitalWrite(SS_PIN, LOW);

  // Check for present card and select if present
  if (! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial() ) {
    delay(50);
    return;
  } else {

    //Deactivate rfid communication, Activate SD communiction
    digitalWrite(SS_PIN, HIGH);
    digitalWrite(chipSelect, LOW);

    Serial.println("card detected");

    //get card id
    for (byte i = 0; i < mfrc522.uid.size; i++) {
      strUID += (mfrc522.uid.uidByte[i] < 0x10 ? "0" : "") + String(mfrc522.uid.uidByte[i], HEX);
    }

    strUID.toUpperCase();  // Ensure upper case HEX
    strUID.toCharArray(UID, 30);  //Convert to array ready for sending
    Serial.print("card ID is ");
    Serial.println(strUID);
    

    //Open cardsList.txt file for reading
    if (!cardsFile.open("test.txt", O_READ)) {
      sd.errorHalt("opening test.txt for read failed");
    }

////////////////////////////////////////Doesn't get past this point.////////////////////////////////////
    Serial.println("cards file opened");
    
    //Read through file to check for card in cardsList.txt
    while (cardsFile.available()) {
      
      readIn = cardsFile.read();  

      if (readIn != '\n') {
        line[stringIndex] = readIn;
        stringIndex++;
      } else {
        line[stringIndex] = '\0';
        Serial.print("debug: ");
        Serial.print(i++);
        Serial.print("  ");
        Serial.println(line);
        if (strcmp(UID, line) == 0) {
          Serial.println("found equal");
          cardPresent = 0;
          break;
        } else {
          Serial.println("did not find equal");
          cardPresent = 1;
        }
        stringIndex = 0;
      }
    }
    
    //Close and flush file
    cardsFile.close();

    digitalWrite(chipSelect, HIGH);

    

  }

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();

}

I'm sorry I know it's quite a bit of code, but I want to make sure you get the full picture.

What it essentially does is wait for a rfid card to be scanned formats the UID into string and then array ready for various future use. It then opens and reads a file with a list of cards and will check line by line to check if the card is registered in the txt file.

The rfid initializes fine and the sd initializes fine(I was having issues with that before which I resolved with bring SS pins HIGH in setup and also using a different SD card), I can scan a card however, when it gets to opening the test file to read, it outputs an error. (Code below the attempt to read the file may have errors, I have not managed to test that yet as I'm at a roadblock with opening and reading, so no need to worry about that)

This is my output (error is last 2 lines) I am unsure as to what these error codes mean? I could not find an error code list anywhere. Also I know that the test.txt file can be opened as I did it with the SDFat readWrite example which I adjusted to just read (that code did not include any rfid related code)

Initialising SD Card
SD Card initialised
card detected
card ID is C399E6D9
error: opening test.txt for read failed
SD errorCode: 0X4,0XFF

I am absolutely baffled as of yet and been headbanging real hard> I may try adding the diode and pull up resistors but I have a feeling I may be doing something wrong in my code.

I will probably follow this diagram example when adding the resistors and diode, except with 2 devices

Thanks guys, I appreciate any help! :slight_smile:

    //Deactivate rfid communication, Activate SD communiction
    digitalWrite(SS_PIN, HIGH);
    digitalWrite(chipSelect, LOW);

I've got to ask. Wouldn't rfidSelect and cardSelect make more sense? Then, it would be easy to tell which device was being activated.

Don't the SD library and the RFID library already manage the slave select pins?

That's not a diode.

Yes, not a diode, that's like 1 gate of a 74HC125.

To see if it is a MISO problem...

...Just put a voltage divider on MISO using 10k or larger resistors, one to gnd and one to Vcc. Do SD and RFID operations and then measure the voltage on MISO. If both devices have properly released it (tri-stated their pins), it should be Vcc/2.

Idea from SD Card - MISO doesn't release [Bad MISO, Bad MISO!!] - Storage - Arduino Forum post 28

PS: if you have a spare analog pin, you could monitor MISO voltage via software and print it to the serial monitor.

Alexisa:
Hi there guys, so I'm having a little bit of a problem with using an rfid scanner and sd module together. I'm using the SDfat library by William Greiman (which has been fantastic) and the rfid library by Miguel Balboa. So I have both rfid and sd modules connected to one Arduino via SPI with the rfid SS pin on D10 and SD SS pin on D4. I can use each library separately (such as the examples) and they work fine with scanning cards, reading and writing to an sd card etc... However when it comes to using both combined I can't open a file to read it.

FYI, I have not placed any pull up resistors on the SS lines, opting to bring the pins HIGH with software in setup. I have also not put a diode on the second SPI device MISO line either which I have seen in some multi SPI device connections.

My code I have whipped up is here:

Thanks guys, I appreciate any help! :slight_smile:

I agree with @PaulS, you do not need the:

void loop(){
digitalWrite(cs,LOW);
digitalWrite(cs,HIGH);
}

The SdFat.h and the RFid libraries handle the SPI chip select internally. I think your digitalWrite()'s are confusing the hardware. The SdFat.h uses SPI.beginTransaction() which can change the SCK idle level. If the CS pin is already low, the hardware can interpret this initialization as incoming data.

I would comment out those lines and recompile it.

Chuck.

Hmm ok thanks guys I see what your saying. I'll give your advice a go and post my results. Looks like my misunderstanding of the libraries might be the problem.
I'll also check on the MISO lines as DaveEvans recommended.

Thanks everyone

Ok so I removed all the digitalWrites for the SS pins of the SPI devices from the code and it I still get the same error, it scans the card, gets the uid and then when it comes to opening that test file, it still can't open it and outputs the error codes "SD errorCode: 0X4,0XFF"

I'm still yet to check the miso lines and possibly add pullup resistors for the SS lines

Also I moved the "file opening" code too and when I moved it outside the if-else statement which checks if a card is read or not the file can be opened. It appears to be able to be opened anywhere BEFORE that if statement checking to see if there are any rfid cards detected. Anywhere after that, I cannot open the file! Which is weird because I did a test and brought the "file opening" code to before the if statement and it opened an closed the file over and over (since it's in the loop) fine, but then I put it after the if statement and it just won't open the file at all.

Thanks everyone

Just a stab in the dark, but what happens if you put

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();

immediately before

//Open cardsList.txt file for reading
    if (!cardsFile.open("test.txt", O_READ)) {
      sd.errorHalt("opening test.txt for read failed");
    }

Yea I tried doing that thinking it might not be "releasing" the SS line, but it didn't work :frowning:

Alexisa:
Yea I tried doing that thinking it might not be "releasing" the SS line, but it didn't work :frowning:

before the sdFile.open() try just sending a bare SPI.transfer(0xff); without doing any digitalWrite(ss,LOW); Some SPI devices need additional clocks to complete an operation. Hopefully the RFid() object is correctly controlling it's CS pin. Without any of your SPI devices CS pins low, all of them should ignore the bus. If the RFid() device doesn't correctly release MISO I have heard this extra clocking sometimes solves the problem.

It cannot hurt. Try it?

One other question:
Does your SDcard have signal level converters?

Maybe when you have both devices on the SPI bus, if your SDcard is only outputting 3.3v there might be enough drain on MISO from the RFid such that the Arduino does not receive valid 5v signal levels?

Chuck.