Community project

Smart RFID Parking Barrier

ESP32
Photo of Smart RFID Parking Barrier
Generated with AI

izzak

Published October 24, 2026

This smart parking barrier combines RFID card authentication with ultrasonic vehicle detection to automate gate control. When a vehicle approaches, the HC-SR04 sensor detects it and prompts for an RFID card scan. Once a valid card is presented to the MFRC522 reader, the SG90 servo rotates to lift the barrier, allowing the vehicle to pass before automatically closing after a set time.

This guide provides a complete wiring diagram showing how to connect the RFID module, ultrasonic sensor, and servo to the ESP32, along with a parts list, the Arduino firmware for gate sequencing logic, and step-by-step assembly instructions. The resistor voltage divider protects the ESP32's input pin from the ultrasonic sensor's 5 V echo signal.

Wiring diagram

Wiring diagram for Smart RFID Parking Barrier

Gather all the parts

QtyComponent
1

MFRC522 RFID Module

13.56 MHz RFID reader/writer module based on the NXP MFRC522 IC. Communicates over SPI and is commonly sold as an RC522 breakout with an onboard antenna.

1

HC-SR04

HC-SR04 ultrasonic distance sensor module with separate 40 kHz transmitter and receiver transducers, measuring 2 to 400 cm. A 10 us pulse on TRIG starts a measurement and ECHO stays high for the echo's round-trip time. This HC-SR04+ board runs from 3.3 V or 5 V.

1

SG90 Servo

Micro servo motor (SG90)

1

Regulated 5 V DC Power Supply, 2 A minimum

A regulated 5 volt supply that provides the short high-current bursts needed by the servo motor.

1

1 kΩ resistor

1 kΩ

A resistor forming the upper half of the divider that lowers the ultrasonic sensor Echo signal.

1

2 kΩ resistor

2 kΩ

A resistor forming the lower half of the divider that lowers the ultrasonic sensor Echo signal safely to 3.3 volts.

Assemble it in 6 steps

1. Keep the two power sources separate

Leave the ESP32-S3 unplugged at first. Use its USB socket only for the board. Set the separate regulated supply to 5.0 V before connecting it; its positive output will power only the servo and ultrasonic sensor.

  • A 5 V supply rated for at least 2 A gives the servo room for its short starting surge.
  • Do not connect the separate supply's 5 V positive wire to the ESP32-S3 3V3 pin — that can damage the board.

2. Connect the RFID reader

With power still off, connect the RC522 VCC pin to ESP32-S3 3V3 and GND to GND. Connect RC522 SDA to GPIO10, SCK to GPIO12, MOSI to GPIO11, MISO to GPIO13, and RST to GPIO14.

  • On this reader, the pin printed SDA is the chip-select wire, not an I²C SDA wire.
  • Make sure RC522 VCC goes to 3V3, not 5 V — most RC522 modules can be damaged or unreliable at 5 V.

3. Build the Echo protection divider

Connect HC-SR04 Echo to one end of the 1 kΩ resistor. Join the other end of that 1 kΩ resistor, one end of the 2 kΩ resistor, and ESP32-S3 GPIO4 in the same breadboard row. Connect the free end of the 2 kΩ resistor to ESP32-S3 GND.

  • The shared middle row is the safe, reduced-voltage Echo signal for GPIO4.
  • Do not connect the HC-SR04 Echo pin directly to GPIO4 — a classic HC-SR04 produces a 5 V Echo pulse that can damage a 3.3 V ESP32-S3 input.

4. Connect the ultrasonic sensor

Connect HC-SR04 TRIG to GPIO2. Connect its VCC to the external supply +5 V and its GND to the external supply GND. Connect that same external supply GND to an ESP32-S3 GND pin.

  • The shared ground is what lets the ESP32-S3 read the sensor signal correctly.
  • Do not swap VCC and GND on the sensor — swapped power can damage the sensor.

5. Connect the barrier servo

Connect the SG90 brown or black wire to the external supply GND, the red wire to external +5 V, and the orange, yellow, or white signal wire to GPIO21. Keep the external supply GND connected to ESP32-S3 GND.

  • Fit the servo horn loosely for the first test, so it can move without forcing the barrier mechanism.
  • Do not power the red servo wire from ESP32-S3 3V3 or a small USB breadboard rail — the servo can reset the board or damage its regulator.

6. Power and test the gate sequence

Plug the ESP32-S3 into USB, then turn on the external 5 V supply. After deploying the firmware, open the Serial Monitor at 115200 baud. Hold an object within 20 cm of the ultrasonic sensor, then place a 13.56 MHz RFID card close to the RC522 antenna; the printed UID is the card identifier used by this test.

  • The servo opens for five seconds and then returns closed. Keep hands clear of the horn while testing.
  • If the servo twitches or the board restarts, turn power off and recheck the shared ground and the dedicated 5 V servo supply.

Review all connections

1. Connections between "rc522_1" and "ESP32"

Functionrc522_1ESP32
powerVCC → 3.3 V power only3V3
groundGND → Common groundGND
spiSCK → SPI clockGPIO 12
spiMOSI → SPI controller-to-reader dataGPIO 11
spiMISO → SPI reader-to-controller dataGPIO 13
spiSDA → SPI chip select; this RC522 pin is labelled SDAGPIO 10
digitalRST → RFID reset controlGPIO 14

2. Connections between "ultrasonic_1" and "ESP32"

Functionultrasonic_1ESP32
groundGND → Common groundGND
digitalTRIG → 3.3 V trigger outputGPIO 2
digitalECHO → 1 kΩ resistor AEXT
powerVCC → Regulated 5 V DC Power Supply, 2 A minimum +5VEXT

3. Connections between "echo_resistor_top_1" and "ESP32"

Functionecho_resistor_top_1ESP32
digitalB → Divider midpoint to 3.3 V-safe Echo inputGPIO 4

4. Connections between "echo_resistor_bottom_1" and "ESP32"

Functionecho_resistor_bottom_1ESP32
groundB → Divider ground referenceGND
digitalA → 1 kΩ resistor BEXT

5. Connections between "servo_supply_1" and "ESP32"

Functionservo_supply_1ESP32
power+5V → SG90 Servo VCCEXT
groundGND → Supply ground shared with ESP32-S3GND

6. Connections between "barrier_servo_1" and "ESP32"

Functionbarrier_servo_1ESP32
groundGND → Servo ground shared with ESP32-S3GND
pwmSIGNAL → Barrier position PWM signalGPIO 21

Deploy the firmware

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

// These GPIO assignments match the assembled gate module wiring.
constexpr uint8_t RC522_SS_PIN = 10;
constexpr uint8_t RC522_RST_PIN = 14;
constexpr uint8_t ULTRASONIC_TRIG_PIN = 2;
constexpr uint8_t ULTRASONIC_ECHO_PIN = 4;
constexpr uint8_t SERVO_PIN = 21;

constexpr int VEHICLE_DISTANCE_CM = 20;
constexpr int BARRIER_CLOSED_ANGLE = 10;
constexpr int BARRIER_OPEN_ANGLE = 90;
constexpr unsigned long SENSOR_INTERVAL_MS = 100;
constexpr unsigned long BARRIER_OPEN_TIME_MS = 5000;

MFRC522 rfid(RC522_SS_PIN, RC522_RST_PIN);
Servo barrierServo;

enum GateState { WAIT_FOR_VEHICLE, WAIT_FOR_CARD, BARRIER_OPEN };
GateState gateState = WAIT_FOR_VEHICLE;
unsigned long lastSensorTime = 0;
unsigned long barrierOpenedAt = 0;

int readDistanceCm() {
  digitalWrite(ULTRASONIC_TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(ULTRASONIC_TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(ULTRASONIC_TRIG_PIN, LOW);

  unsigned long echoUs = pulseIn(ULTRASONIC_ECHO_PIN, HIGH, 25000);
  if (echoUs == 0) return -1;
  return echoUs / 58;
}

void printCardUid() {
  Serial.print("RFID card UID: ");
  for (byte i = 0; i < rfid.uid.size; i++) {
    if (rfid.uid.uidByte[i] < 0x10) Serial.print('0');
    Serial.print(rfid.uid.uidByte[i], HEX);
    if (i + 1 < rfid.uid.size) Serial.print(':');
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);
  pinMode(ULTRASONIC_TRIG_PIN, OUTPUT);
  pinMode(ULTRASONIC_ECHO_PIN, INPUT);

  barrierServo.setPeriodHertz(50);
  barrierServo.attach(SERVO_PIN, 500, 2400);
  barrierServo.write(BARRIER_CLOSED_ANGLE);

  SPI.begin(12, 13, 11, RC522_SS_PIN);
  rfid.PCD_Init();

  Serial.println("Smart Parking gate test ready.");
  Serial.println("Barrier closed. Bring a vehicle within 20 cm, then scan an RFID card.");
}

void loop() {
  unsigned long now = millis();

  if (gateState == WAIT_FOR_VEHICLE && now - lastSensorTime >= SENSOR_INTERVAL_MS) {
    lastSensorTime = now;
    int distanceCm = readDistanceCm();
    if (distanceCm > 0 && distanceCm <= VEHICLE_DISTANCE_CM) {
      Serial.print("Vehicle detected at ");
      Serial.print(distanceCm);
      Serial.println(" cm. Scan an RFID card.");
      gateState = WAIT_FOR_CARD;
    }
  }

  if (gateState == WAIT_FOR_CARD && rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
    printCardUid();
    Serial.println("RFID card accepted for this demonstration. Opening barrier.");
    barrierServo.write(BARRIER_OPEN_ANGLE);
    barrierOpenedAt = now;
    gateState = BARRIER_OPEN;
    rfid.PICC_HaltA();
    rfid.PCD_StopCrypto1();
  }

  if (gateState == BARRIER_OPEN && now - barrierOpenedAt >= BARRIER_OPEN_TIME_MS) {
    barrierServo.write(BARRIER_CLOSED_ANGLE);
    Serial.println("Barrier closed. Waiting for the next vehicle.");
    gateState = WAIT_FOR_VEHICLE;
  }

  delay(1);
}

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik