RFID - RC522, ST7735S TFT and ESP32

Hi,

I was having a play with the RFID RC522 and I'm quite impressed with the amount of data a single card can actually store. I tried to find a sample sketch that I could use to decode and print ALL the block address but I couldn't find one. So I butchered the Random Nerds version created my own and it's below:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-mfrc522-rfid-reader-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.  
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

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

// Learn more about using SPI/I2C or check the pin assigment for your board: https://github.com/OSSLibraries/Arduino_MFRC522v2#pin-layout
MFRC522DriverPinSimple ss_pin(5);

MFRC522DriverSPI driver{ss_pin}; // Create SPI driver
//MFRC522DriverI2C driver{};     // Create I2C driver
MFRC522 mfrc522{driver};         // Create MFRC522 instance

MFRC522::MIFARE_Key key;

const byte BLOCKS [] = {0,1,2,4,5,6,8,9,10,12,13,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,56,57,58,60,61,62};

//byte blockAddress = 2;
byte bufferblocksize = 18;
byte blockDataRead[18];

int IndLED = 33;

void setup() {
  pinMode(IndLED, OUTPUT);
  digitalWrite(IndLED, HIGH);
  Serial.begin(115200);  // Initialize serial communication
  while (!Serial);       // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4).
  
  mfrc522.PCD_Init();    // Init MFRC522 board.
  Serial.println(F("Warning: this example overwrites a block in your card, use with care!"));
 
  // 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;
  }
}

void loop() {
  // Check if a new card is present
  if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) {
    delay(500);
    return;
  }
  Serial.print("----------------\nCard UID: ");
  MFRC522Debug::PrintUID(Serial, (mfrc522.uid));
  Serial.println();

  //Card is present so loop through all blocks
  for (byte BLOCKADD : BLOCKS) { // for each block address in the blocks
    ReadBlocks(BLOCKADD);
  }

  // Halt communication with the card
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
  digitalWrite(IndLED, LOW);
  delay(2000);  // Delay for readability
  digitalWrite(IndLED, HIGH);
  delay(2000);  // Delay for readability
}

void ReadBlocks(byte BLOCKADD){

  // Authenticate the specified block using KEY_A = 0x60
  if (mfrc522.PCD_Authenticate(0x60, BLOCKADD, &key, &(mfrc522.uid)) != 0) {
    Serial.println("Authentication failed.");
    return;
  }

  // Read data from the specified block
  if (mfrc522.MIFARE_Read(BLOCKADD, blockDataRead, &bufferblocksize) != 0) {
    Serial.println("Read failed.");
  } else {
    Serial.print("Data in block ");
    Serial.print(BLOCKADD);
    Serial.print(": ");
    for (byte i = 0; i < 16; i++) {
      Serial.print((char)blockDataRead[i]);  // Print as character
    }
    Serial.println();
  }
  
  }

Now that I have the basics I'm going to create an iPhone app that sends data either using Bluetooth or WiFi to program various blocks with the data I want on the card. I'll send a command to initialise the Write process, using an LED as an indication its ready to write data to the relevant data block then give a 10 second window to place the card on the RC522. If the card isn't placed on the RC522 then it will revert back to the Read Mode.

I'm thinking of using a ST7735S TFT but I've heard that there will be a conflict using the RFID and TFT on the same ESP32. Has anyone done this? If so, could you please share?

How about using a nextion display which has a serial interface.
Much easier to use than a TFT with SPI interface.

My recommendation is to NOT use the Nextion library. Very cryptic with using function-pointers for everything.

Communicating with the Nextion-display without the nextion-library is easier to adapt.

As you are programming an iPhone-App why don't you do all communication with this app?

Another approach would be to use the ESPUI-library to create a webinterface by purely C-coding for all

Thanks for the reply. I only dabble in the ESP32 products and peripherals.... although I have created an entire home system using the ESP32 CYD and ESP32-D microcontrollers. It works extremely well.
I've been looking at the Nextion displays and I don't think I would pay that sort of money for a project that I only wanted to create to see if I can. I'm off work now for 2 days so I'll look at attaching the TFT and iron out any conflicts. If I do get it going I'll add the complete sketch and wiring on here for other people to replicate.

Thanks again for the reply.

you could attach the TFT to VSPI and the MFRC522 RFID read to HSPI - see esp32-pinout-reference-gpios

testing a 1.8" SPI TFT LCD Module Display Shield ST7735S

for example TFT.ino using TFT_eSPI library

// ESP32 TFT_eSPI library  example TFT_Print_Test

#include <SPI.h>

#include <TFT_eSPI.h> // Hardware-specific library

TFT_eSPI tft = TFT_eSPI();       // Invoke custom library

#define TFT_GREY 0x5AEB // New colour


void setup(void) {
  //uint16_t ID = tft.readID();
  Serial.begin(115200);
  delay(2000);
  Serial.println("\n\nESP32 TFT_eSPI TFT_Print_Test"
     "\n  ST7735_TFT on VSPI  MFRC522 RFID reader on HSPI");
  //Serial.println(ID);
  tft.init();
  tft.setRotation(2);
  setupRFID();
}

void loop() {
  loopRFID();     // attempt to read MFRC522 RFID card

  // ever 10secons run print test
  static unsigned long int timer1=millis();
  if(millis()-timer1 < 10000)return;
  timer1=millis();
  Serial.println("TFT print test");
  // Fill screen with random colour so we can see the effect of printing with and without 
  // a background colour defined
  tft.fillScreen(random(0xFFFF));
  
  // Set "cursor" at top left corner of display (0,0) and select font 2
  // (cursor will move to next line automatically during printing with 'tft.println'
  //  or stay on the line is there is room for the text with tft.print)
  tft.setCursor(0, 0, 2);
  // Set the font colour to be white with a black background, set text size multiplier to 1
  tft.setTextColor(TFT_WHITE,TFT_BLACK);  tft.setTextSize(1);
  // We can now plot text on screen using the "print" class
  tft.println("Hello World!");
  
  // Set the font colour to be yellow with no background, set to font 7
  tft.setTextColor(TFT_YELLOW); tft.setTextFont(7);
  tft.println(1234.56);
  
  // Set the font colour to be red with black background, set to font 4
  tft.setTextColor(TFT_RED,TFT_BLACK);    tft.setTextFont(4);
  tft.println((long)3735928559, HEX); // Should print DEADBEEF

  // Set the font colour to be green with black background, set to font 4
  tft.setTextColor(TFT_GREEN,TFT_BLACK);
  tft.setTextFont(4);
  tft.println("Groop");
  tft.println("I implore thee,");

  // Change to font 2
  tft.setTextFont(2);
  tft.println(F("my foonting turlingdromes.")); // Can store strings in FLASH to save RAM
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  // This next line is deliberately made too long for the display width to test
  // automatic text wrapping onto the next line
  tft.println("Or I will rend thee in the gobberwarts with my blurglecruncheon, see if I don't!");
  
  // Test some print formatting functions
  float fnumber = 123.45;
   // Set the font colour to be blue with no background, set to font 4
  tft.setTextColor(TFT_BLUE);    tft.setTextFont(4);
  tft.print("Float = "); tft.println(fnumber);           // Print floating point number
  tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary
  tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal

}

User_Setup.h file (place in same directory as above TFT.ino file)

// TFT_eSPI setup.h file for  ESP32  1.8 inch_ST7735_TFT

// note: ESP32 core 3.1.1 DOES NOT WORK - GOES INTO A RESET LOOP
// ESP32-C3 works with ESP32 core 2.0.14 fails with ESP32 core 2.0.15

// ESP32-S3-DevKitC-1 with ESP32 core 3.2.0 GOES INTO A RESET LOOP
//   does not work with ESP32 core 2.0.14 blank screen


#define USER_SETUP_INFO "User_Setup"

#define USE_HSPI

#define ST7735_DRIVER      // Full configuration option, define additional parameters below for this display

//#define ST7735_GREENTAB
// For ST7735, ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display
// Try ONE option at a time to find the correct colour order for your display
//  #define TFT_RGB_ORDER TFT_RGB  // Colour order Red-Green-Blue
//  #define TFT_RGB_ORDER TFT_BGR  // Colour order Blue-Green-Red

// For ST7789, ST7735, ILI9163 and GC9A01 ONLY, define the pixel width and height in portrait orientation
#define TFT_WIDTH  128 // ST7789 240 x 240 and 240 x 320
#define TFT_HEIGHT 160 // ST7789 240 x 320

// If colours are inverted (white shows as black) then uncomment one of the next
// 2 lines try both options, one of the options should correct the inversion.

// #define TFT_INVERSION_ON
// #define TFT_INVERSION_OFF

// ESP32-C3 supermini 
#define TFT_CS   5//SS     

#define TFT_MOSI 23//MOSI   
#define TFT_SCLK 18//SCK    
#define TFT_MISO -1      

#define TFT_DC   2
#define TFT_RST  4

#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF

#define SMOOTH_FONT

#define SPI_FREQUENCY   40000000

#define SPI_TOUCH_FREQUENCY  2500000


RFID.ino file (place in same directory as above TFT.ino file)

// ESP32 MFRC522 using HSPI

#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.

void setupRFID() {
  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).
  Serial.println("\n\nESP32 MFRC522 using HSPI");
  hspi->begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, HSPI_CS);
  reader.PCD_Init();  // Init each MFRC522 card.
  Serial.print(F("Reader "));
  static uint8_t i = 0;
  i++;
  Serial.print(i);
  Serial.print(F(": "));
  MFRC522Debug::PCD_DumpVersionToSerial(reader, Serial);
}

/**
 * Main loop.
 */
void loopRFID() {
 // delay(2000);
  //Serial.println("reading RFID");
  // Look for new 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));

    // Halt PICC.
    reader.PICC_HaltA();
    // Stop encryption on PCD.
    reader.PCD_StopCrypto1();
  }
}

when executed the RFID reader read tags OK and the TFT displays the print test every 10 seconds

serial monitor output

ESP32 TFT_eSPI TFT_Print_Test
  ST7735_TFT on VSPI  MFRC522 RFID reader on HSPI


ESP32 MFRC522 using HSPI
Reader 1: Firmware Version: 0x92 = v2.0
TFT print test
Reader 1: Card UID: 83 6E D2 A6
PICC type: MIFARE 1KB
Reader 2: Card UID: 4E 06 0C 04
PICC type: MIFARE 1KB
TFT print test
TFT print test
Reader 3: Card UID: 15 64 FD C2
PICC type: MIFARE 1KB
TFT print test

photo of setup