Firebeetle 2 ESP32-E, RFID, MicroSD, RTC - RFID scans once

ESP32 example with SD card using VSPI MFRC522 RFID reader using HSPI

// ESP32 - SD card using VSPI MFRC522 RFID reader using HSPI

// see https://forum.arduino.cc/t/esp32-initialize-hspi-as-default-spi/1155093/12

/* original SD code from
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-microsd-card-arduino/
*/

#include "FS.h"
#include "SD.h"
#include "SPI.h"

// MFRC522 RFID reader
#include <MFRC522v2.h>
#include <MFRC522DriverSPI.h>
#include <MFRC522DriverPinSimple.h>
#include <MFRC522Debug.h>

// default HSPI pins used by MFRC522 RFID reader
#define HSPI_SCK 14
#define HSPI_MISO 12
#define HSPI_MOSI 13
#define HSPI_CS 15

SPIClass *hspi = new SPIClass(HSPI);      // HSPI object used by MFRC522
MFRC522DriverPinSimple ss_1_pin(HSPI_CS);   // Configurable, take an unused pin, only HIGH/LOW required, must be different to SS 2.
MFRC522DriverSPI driver_1{ ss_1_pin, *hspi };
MFRC522 reader = driver_1;                // Create MFRC522 instance.

// ESP32 RTC
#include <ESP32Time.h>
ESP32Time rtc(3600);  // offset in seconds GMT+1

void setup() {
  Serial.begin(115200);
  delay(2000);
  Serial.println("Read MRFC522 RFID card save time and data to SD card");
  rtc.setTime(1609459200);  // initialise RTC 1st Jan 2021 00:00:00
  // setup SD card reader using VSPI
  if (!SD.begin()) {                       // mount card
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }
  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);
  listDir(SD, "/", 0);
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));

  // setup MRFC522 RFID reader using HSPI
  Serial.print("open MRFC522 RFID reader");
  reader.PCD_Init();  // Init MFRC522 card.
  MFRC522Debug::PCD_DumpVersionToSerial(reader, Serial);
}

void loop() {
  // check Serial input read or delete data file
  if (Serial.available()) {
    char ch = Serial.read();
    if (ch == 'p')
      readFile(SD, "/data.txt");
    if (ch == 'd')
      deleteFile(SD, "/data.txt");
  }
  // check MFRC522 RFID reader
  if (reader.PICC_IsNewCardPresent() && reader.PICC_ReadCardSerial()) {
    Serial.print("\n");
    Serial.println(rtc.getTime("%A, %B %d %Y %H:%M:%S"));  // (String) returns time with specified format
    // Show some details of the PICC (that is: the tag/card).
    Serial.print(F(" Card UID:"));
    MFRC522Debug::PrintUID(Serial, reader.uid);
    Serial.print("  PICC type: ");
    MFRC522::PICC_Type piccType = reader.PICC_GetType(reader.uid.sak);
    Serial.println(MFRC522Debug::PICC_GetTypeName(piccType));
    // save card details to SD
    String s = rtc.getTime("%A, %d/%m/%Y %H:%M:%S") + " Card UID:";
    for (byte i = 0; i < reader.uid.size; i++) {
      char text[10] = { 0 };
      snprintf(text, 100, " 0x%2X", reader.uid.uidByte[i]);
      s += String(text);
    }
    s += "  PICC type: " + String((const char *)MFRC522Debug::PICC_GetTypeName(piccType)) + "\n";
    appendFile(SD, "/data.txt", s.c_str());
    // Halt PICC.
    reader.PICC_HaltA();
    // Stop encryption on PCD.
    reader.PCD_StopCrypto1();
    delay(1000);
  }
}
// ************** SD functions **************************

void listDir(fs::FS &fs, const char *dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.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();
  }
}

void createDir(fs::FS &fs, const char *path) {
  Serial.printf("Creating Dir: %s\n", path);
  if (fs.mkdir(path)) {
    Serial.println("Dir created");
  } else {
    Serial.println("mkdir failed");
  }
}

void removeDir(fs::FS &fs, const char *path) {
  Serial.printf("Removing Dir: %s\n", path);
  if (fs.rmdir(path)) {
    Serial.println("Dir removed");
  } else {
    Serial.println("rmdir failed");
  }
}

void readFile(fs::FS &fs, const char *path) {
  Serial.printf("\nReading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  //Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

void writeFile(fs::FS &fs, const char *path, const char *message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void appendFile(fs::FS &fs, const char *path, const char *message) {
  //Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    //Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(fs::FS &fs, const char *path1, const char *path2) {
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(fs::FS &fs, const char *path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void testFileIO(fs::FS &fs, const char *path) {
  File file = fs.open(path);
  static uint8_t buf[512];
  size_t len = 0;
  uint32_t start = millis();
  uint32_t end = start;
  if (file) {
    len = file.size();
    size_t flen = len;
    start = millis();
    while (len) {
      size_t toRead = len;
      if (toRead > 512) {
        toRead = 512;
      }
      file.read(buf, toRead);
      len -= toRead;
    }
    end = millis() - start;
    Serial.printf("%u bytes read for %u ms\n", flen, end);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }


  file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }

  size_t i;
  start = millis();
  for (i = 0; i < 2048; i++) {
    file.write(buf, 512);
  }
  end = millis() - start;
  Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
  file.close();
}

test run results

ESP32 SD card test - note VCC to 5V

Read MRFC522 RFID card save time and data to SD card
SD Card Type: SDHC
SD Card Size: 14992MB
Listing directory: /
  DIR : System Volume Information
  FILE: test.txt  SIZE: 1048576
  FILE: data.txt  SIZE: 891
Total space: 14984MB
Used space: 2MB
open MRFC522 RFID readerFirmware Version: 0x92 = v2.0
dDeleting file: /data.txt
File deleted

Friday, January 01 2021 01:00:14
 Card UID: ZZ XX FD C2  PICC type: MIFARE 1KB

Friday, January 01 2021 01:00:18
 Card UID: Z0 XF 62 1A  PICC type: MIFARE 1KB

Friday, January 01 2021 01:00:19
 Card UID: Z0 XF 62 1A  PICC type: MIFARE 1KB

Friday, January 01 2021 01:00:22
 Card UID: ZZ XX FD C2  PICC type: MIFARE 1KB

Friday, January 01 2021 01:00:23
 Card UID: ZZ XX FD C2  PICC type: MIFARE 1KB

Friday, January 01 2021 01:02:30
 Card UID: Z0 XF 62 1A  PICC type: MIFARE 1KB
p
Reading file: /data.txt
Friday, 01/01/2021 01:00:14 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:18 Card UID: 0xZ0 0xXF 0x62 0x1A  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:19 Card UID: 0xZ0 0xXF 0x62 0x1A  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:22 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:23 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:02:30 Card UID: 0xZ0 0xXF 0x62 0x1A  PICC type: MIFARE 1KB

Friday, January 01 2021 01:03:28
 Card UID: ZZ XX FD C2  PICC type: MIFARE 1KB
p
Reading file: /data.txt
Friday, 01/01/2021 01:00:14 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:18 Card UID: 0xZ0 0xXF 0x62 0x1A  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:19 Card UID: 0xZ0 0xXF 0x62 0x1A  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:22 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:00:23 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:02:30 Card UID: 0xZ0 0xXF 0x62 0x1A  PICC type: MIFARE 1KB
Friday, 01/01/2021 01:03:28 Card UID: 0xZZ 0xXX 0xFD 0xC2  PICC type: MIFARE 1KB

photo