Group assignment

Here is a link to the group assignment page.

Individual Assignments:

final project sketch

This week’s focus is on input devices, and as part of our individual assignment, we were tasked with integrating a sensor into our microcontroller board. The goal was to successfully read data from this sensor. For a part of my final project: I’ll be using an RFID (Radio Frequency Identification) reader to control a servo motor. The concept is to associate specific RFID tags with servo movements. When an authorized RFID tag is detected, the servo will respond accordingly.

With the board I designed, all I have to do is plug the RFID reader directly into the board without any additional wiring. This setup, however, is temporary because the board will be inside the main base of the project, while the RFID reader and servo will be in the cat pods to control the doors.

Programming on Arduino

To start out the programming for the RFID, I used the MFRC522 library, which is a library for interfacing with RFID readers. At first, I just wanted the RFID reader to recognize the tags, so I used the example code that comes with the library and simplified it, and changed the pin numbers to match the ones on my board.


	#include <SPI.h>
	#include <MFRC522.h>
	
	#define SS_PIN 10
	#define RST_PIN 9
	
	MFRC522 rfid(SS_PIN, RST_PIN);
	
	void  setup() {
	  Serial.begin(9600);
	  SPI.begin();
	  rfid.PCD_Init();
	  Serial.println("Tap an RFID/NFC tag to read its UID");
	}
	
	void loop () {
		if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
		Serial.print("UID: ");
		for (byte i = 0; i < rfid.uid.size; i++) {
		  Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
		  Serial.print(rfid.uid.uidByte[i], HEX);
		}
		Serial.print();
		rfid.PICC_HaltA();
		rfid.PCD_StopCrypto1();
	  }
	}
	

this code reads the UID of the RFID tag and prints it to the serial monitor allong with the time it was read. The next step was set one tag as a key and when it read the key tag, it would print "Access Granted" to the serial monitor and when it read any other tag it would print "Access Denied".

    breakdown of the new additions to the code to get to this:

  • byte authorizedUID[4];

    Here I declared an array to store the authorized UID, this array will hold the unique identifier (UID) of the authorized RFID/NFC tag.

  • bool isUIDSet = false;

    This boolean variable will be used to check if the authorized UID has been set.

  • Serial.println("Tap an RFID/NFC tag to set it as the authorized UID");

    A new message will be displayed on the serial monitor

  • in the loop function:

  • for (byte i = 0; i < 4; i++) {
    	authorizedUID[i] = rfid.uid.uidByte[i];
      }

    This is if a new card is present and its serial number is read, and the UID has not yet been set, then the UID is stored in the "authorizedUID" array, and if "isUTDset" flag is set "true", then a message is printed

    Serial.println("Authorized UID set!");
  • Otherwise:

  •     Serial.print("UID:");
    	for (byte i = 0; i < rfid.uid.size; i++) {
    	  Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
    	  Serial.print(rfid.uid.uidByte[i], HEX);
    	}
    	Serial.println();

    If the read UID matches the authorizied UID, it´ll print "Access granted". Otherwise it´ll print “Access denied.”

  • byte authorizedUID[4];

    Lastly, the communication with the RFID reader is stopped and the crypto1 is stopped.

Here is the final code:

    
        #include <SPI.h>
        #include <MFRC522.h>
        
        #define SS_PIN  A4 
        #define RST_PIN D5 
        
        MFRC522 rfid(SS_PIN, RST_PIN);
        byte authorizedUID[4]; 
        bool isUIDSet = false; 
        
        void setup() {
          Serial.begin(9600);
          SPI.begin(); 
          rfid.PCD_Init(); 
          // Set Rx Gain to maximum (0x07 << 4)
          rfid.PCD_WriteRegister(rfid.RFCfgReg, (0x07 << 4));
          Serial.println("Tap an RFID/NFC tag to set it as the authorized UID");
        }
        
        void loop() {
          if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
            if (!isUIDSet) {
              for (byte i = 0; i < 4; i++) {
                authorizedUID[i] = rfid.uid.uidByte[i];
              }
              isUIDSet = true;
              Serial.println("Authorized UID set!");
            } else {
              if (memcmp(rfid.uid.uidByte, authorizedUID, 4) == 0) {
                Serial.println("Access granted.");
              } else {
                Serial.println("Access denied.");
              }
            }
            // Print the UID in the Serial Monitor in hex format
            Serial.print("UID:");
            for (byte i = 0; i < rfid.uid.size; i++) {
              Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
              Serial.print(rfid.uid.uidByte[i], HEX);
            }
            Serial.println();
            rfid.PICC_HaltA(); // halt PICC
            rfid.PCD_StopCrypto1(); // stop encryption on PCD
          }
        }
    

the message displayed in this video is different but, the code it the same as the one above.

Updates and changes

In the new PCB I designed during the electronics design week, I added a few more components to the board, including two LEDs, for the sole purpose of testing and also for programming along with the RFID reader. So in this next code, I added one of the LEDs to the code to light up when the access is granted, and to turn off when the access is denied.

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

        #define SS_PIN  A4 // GPIO pin connected to RC522's SS pin (SPI CS)
        #define RST_PIN D5 // GPIO pin connected to RC522's RST pin
        #define LED_PIN D3 // GPIO pin connected to the LED

        MFRC522 rfid(SS_PIN, RST_PIN);
        byte authorizedUID[4]; // Array to store the authorized UID
        bool isUIDSet = false; // Flag to check if the UID has been set

        void setup() {
          Serial.begin(9600);
          SPI.begin(); // Initialize SPI bus
          rfid.PCD_Init(); // Initialize MFRC522
          pinMode(LED_PIN, OUTPUT); // Set the LED pin as an output
          digitalWrite(LED_PIN, LOW); // Ensure the LED is off
          Serial.println("Tap an RFID/NFC tag to set it as the authorized UID");
        }

        void loop() {
          if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
            if (!isUIDSet) {
              for (byte i = 0; i < 4; i++) {
                authorizedUID[i] = rfid.uid.uidByte[i];
              }
              isUIDSet = true;
              Serial.println("Authorized UID set!");
            } else {
              if (memcmp(rfid.uid.uidByte, authorizedUID, 4) == 0) {
                digitalWrite(LED_PIN, HIGH); // Turn on the LED
                Serial.println("Access granted.");
              } else {
                digitalWrite(LED_PIN, LOW); // Turn off the LED
                Serial.println("Access denied.");
              }
            }

            // Print the UID in the Serial Monitor in hex format
            Serial.print("UID:");
            for (byte i = 0; i < rfid.uid.size; i++) {
              Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
              Serial.print(rfid.uid.uidByte[i], HEX);
            }
            Serial.println();

            rfid.PICC_HaltA(); // Halt PICC (Proximity Integrated Circuit Card)
            rfid.PCD_StopCrypto1(); // Stop encryption on PCD (Proximity Coupling Device)
          }
        }
    

Controlling the servo

In the first part of this week I was having problems with the servo, no matter what code I used, the code would not even compile and this is the part of the message that told me the problem was with the servo library "Multiple libraries were found for "Servo.h"".

final project sketch

To further test this, I compiled the same code using a different microcontroller. I used the first PCB I made, which has a Seeeduino Xiao SMD as the controller, and an Arduino Uno. Surprisingly, the code compiled and worked flawlessly. This observation suggests that the issue might indeed be a compatibility problem between the Arduino Nano ESP32 and the servo library.

After a quick Google search, I found that others went through similar issues with this combination, and the solution was to use a different servo library. So, I used the "ServoESP32" library, and the code compiled and worked perfectly. Here is a link to the forum where people discussed this issue and then the solution. Additionally, you can download a version of the ESP servo library compatible with your Arduino IDE software version here.

The next step was to control the servo with the RFID reader. This part (the cat door) of my final project is based on Pamela Martello's final project which uses an RFID activated door lock system. so for this I followed her documentation, and then used her code as a base and adapted it to my project.

Pamela´s code:

    
        *
        Servo moves when RFID reads recognized tag
        Version1_works fine

        //inspired on: Viral Science tutorials
        //---RFID + SERVO MOTOR = MIRRU IN MIRRU OUT CODE---
        //adapted and modified by Pamela Martello
        //04 June 2019
        Pamela Martello
        */

        #include SPI.h> //peripheral communication
        #include MFRC522.h> ///RFID library
        #include Servo.h> // Servo library
        #define SS_PIN 10 // RFID PINS
        #define RST_PIN 9 //RFID PINS
        #define ACCESS_DELAY 10000 //delay open the lock 10,000millis=10secs
        #define DENIED_DELAY 1000
        MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

        Servo myservo; // create servo object to control a servo

        //int pos = 0; // variable to store the servo position (not needed)

        void setup() {
        Serial.begin(9600); // Initiate a serial communication
        SPI.begin(); // Initiate SPI bus
        mfrc522.PCD_Init(); // Initiate MFRC522
        Serial.println("Put your card to the reader...");
        Serial.println();
        myservo.attach(3); // attaches the servo on pin 3 to the servo object
        myservo.write(100);
        mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max); //If you set Antenna Gain to Max it will
        //increase reading distance it increases about 1-2cm
        }

        void loop() {
        // Look for new cards
        if ( ! mfrc522.PICC_IsNewCardPresent())
        {
        return;
        }
        // Select one of the cards
        if ( ! mfrc522.PICC_ReadCardSerial())
        {
        return;
        }
        //Show UID on serial monitor
        Serial.print("UID tag :");
        String content= "";
        byte letter;
        for (byte i = 0; i < mfrc522.uid.size; i++) { Serial.print(mfrc522.uid.uidByte[i] < 0x10
        ? " 0" : " " ); Serial.print(mfrc522.uid.uidByte[i], HEX);
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " " ));
        content.concat(String(mfrc522.uid.uidByte[i], HEX)); } Serial.println();
        Serial.print("Message : ");
        content.toUpperCase();
        if (content.substring(1) == " 09 5E BB 59") //change here the UID of the card/cards that you want
        //to give access (to know the code use examples inside MFRC522>DumpInfo)
        {
        Serial.println("Authorize mirru access");
        Serial.println();
        delay(200);
        myservo.write(0);// lock position
        delay(ACCESS_DELAY); //delay to keep the lock open and let the cat go in
        myservo.write(90); // unlock position
        }
        else {
        Serial.println(" CATccess denied");

        delay(DENIED_DELAY);

        }
    

    Most of the changes I made included:

  • Adjusting the pins to match those on my board.
  • Adding the ESP servo library.
  • Modifying the UID tag to match the one I set on the RFID reader.
  • Updating the sentences displayed on the serial monitor.
  • Implementing LED behavior based on access granted or denied.
  • I also removed some parts, that didnt work with my set up, namely a line that was supposed to make the RFID´s range bigger, however this did not work with the RFID I have :(
    
        *
        //inspired on: Viral Science tutorials
        //---RFID + SERVO MOTOR = MIRRU IN MIRRU OUT CODE---
        //adapted and modified by Pamela Martello
        //04 June 2019
        //adapted and modified by Bianca Guimarães 
        //04 april 2024
        *

        #include <SPI.h>
        #include <MFRC522.h>
        #include <ESP32Servo.h>

        #define SS_PIN A4
        #define RST_PIN D5
        #define ACCESS_DELAY 10000 // 10 seconds
        #define DENIED_DELAY 1000
        #define LED_PIN D3 // Pin for the LED

        MFRC522 mfrc522(SS_PIN, RST_PIN);
        Servo myservo;

        void setup() {
          Serial.begin(9600);
          SPI.begin();
          mfrc522.PCD_Init();
          Serial.println("Put your card to the reader...");
          Serial.println();
          myservo.attach(2);
          myservo.write(100);
          pinMode(LED_PIN, OUTPUT); // Set LED pin as output
        }

        void loop() {
          if (!mfrc522.PICC_IsNewCardPresent()) {
            return;
          }
          if (!mfrc522.PICC_ReadCardSerial()) {
            return;
          }

          Serial.print("UID tag: ");
          String content = "";
          for (byte i = 0; i < mfrc522.uid.size; i++) {
            Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
            Serial.print(mfrc522.uid.uidByte[i], HEX);
            content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
            content.concat(String(mfrc522.uid.uidByte[i], HEX));
          }
          Serial.println();

          content.toUpperCase();
          if (content.substring(1) == "29 62 73 5B") { // Authorized tag UID
            Serial.println("The cat may enter and feast");
            Serial.println("20 seconds until the servo moves back");
            Serial.println();
            digitalWrite(LED_PIN, HIGH); // Turn on the LED
            delay(200);
            myservo.write(0); // Lock position
            delay(ACCESS_DELAY); // Keep the lock open and let the cat go in
            myservo.write(100); // Unlock position
            digitalWrite(LED_PIN, LOW); // Turn off the LED
          } else {
            Serial.println("You shall not pass! Stinky cat");
            for (int i = 0; i < 4; i++) {
              digitalWrite(LED_PIN, HIGH); // Blink the LED
              delay(200);
              digitalWrite(LED_PIN, LOW);
              delay(200);
            }
            delay(DENIED_DELAY);
          }
        }