Smart Toll Gate
Automation System
RFID-based automatic toll collection using Arduino UNO with servo motor barrier, ultrasonic vehicle detection, GSM SMS notifications, and I2C LCD display — a complete smart city traffic solution.
📖 Read the complete project guide with simulation on MakeMindz
🔗 View Full Project on MakeMindzProject Overview
An intelligent toll booth that replaces manual collection with automated RFID authentication and servo gate control
The Smart Toll Gate Automation System uses an RFID RC522 module to identify vehicles equipped with prepaid RFID tags. When a vehicle approaches, the HC-SR04 ultrasonic sensor detects its presence and prompts the driver to scan their card. The RFID UID is matched against a stored database — if the card is valid and the balance is sufficient, the driver confirms payment via a push button, and the servo motor barrier opens automatically.
After deducting the toll fee, the GSM module sends an instant SMS to the vehicle owner confirming the transaction. An IR sensor detects when the vehicle has fully passed, then closes the gate. The I2C 16×2 LCD displays real-time system status throughout the process.
A second Arduino can be connected via SoftwareSerial for dual-controller architecture — receiving payment status updates for logging or display purposes.
RFID Authentication
MFRC522 scans vehicle RFID tags via SPI — verifies UID against stored card database
Servo Barrier
Servo rotates 0°→90° to open, waits for IR clear signal, then returns to 0° to close
Ultrasonic Detection
HC-SR04 measures vehicle distance — triggers RFID scan only when car is within 50cm
GSM SMS Alert
SIM800L sends SMS to owner confirming toll amount and remaining prepaid balance
LCD Status Display
I2C 16×2 LCD shows live status: scanning, processing, granted, insufficient, denied
10-Second Timer
Payment confirmation window — button must be pressed within 10 seconds or timeout occurs
Prepaid Balance System
Card balances stored in Arduino memory — deducted on each successful toll payment
Dual Arduino Serial
SoftwareSerial sends payment status to a second Arduino for logging or remote display
LCD Status Messages
Real-time messages shown on the 16×2 LCD throughout the toll process
0x27 (common for PCF8574 backpack). If your LCD doesn't display anything, try 0x3F. Use an I2C scanner sketch to find the correct address for your module.
Components Required
All hardware needed to build the smart toll gate system
Arduino UNO
Main controller — manages RFID reading, LCD display, servo control, ultrasonic sensing, and GSM communication
RFID RC522 Module + RFID Cards/Tags
Reads vehicle RFID tags via SPI protocol. Provides unique UID per card matched against the registered vehicle database
Servo Motor (SG90 or MG90S)
Controls the physical barrier arm — rotates 90° to open, 0° to close. Connected to PWM pin 5.
HC-SR04 Ultrasonic Sensor
Detects vehicle presence at the toll booth — triggers the RFID scan workflow only when a vehicle is within 50cm
GSM Module (SIM800L / SIM900)
Sends SMS payment confirmation to the registered vehicle owner. Communicates via SoftwareSerial UART.
I2C 16×2 LCD Display
Shows real-time system status messages. Uses I2C protocol (only 2 wires: SDA + SCL) — address 0x27
IR Sensor Module
Detects when the vehicle has fully passed through the gate — triggers the gate to close automatically
Push Button
Payment confirmation button — driver presses within 10 seconds to confirm toll deduction and open gate
Jumper Wires + Breadboard
For connections and prototyping — male-to-male and male-to-female wires for all module interconnections
Pin Configuration & Wiring
Complete pin mapping for all modules connected to Arduino UNO
| Module / Pin | Arduino Pin | Notes |
|---|---|---|
| RFID RC522 (SPI) | ||
| RFID SS (SDA) | Pin 10 | SS_PIN — chip select |
| RFID RST | Pin 9 | RST_PIN — reset |
| RFID MOSI | Pin 11 | SPI MOSI |
| RFID MISO | Pin 12 | SPI MISO |
| RFID SCK | Pin 13 | SPI Clock |
| RFID VCC | 3.3V | ⚠️ 3.3V only — not 5V! |
| Ultrasonic (HC-SR04) | ||
| TRIG | Pin 6 | Trigger pulse output |
| ECHO | Pin 7 | Echo pulse input |
| Servo Motor + IR + Button | ||
| Servo Signal | Pin 5 | PWM — gate barrier |
| IR Sensor OUT | Pin 4 | IR_PIN — vehicle clear detect |
| Push Button | Pin 2 | INPUT_PULLUP — payment confirm |
| GSM Module (SoftwareSerial) | ||
| GSM TX | Pin 3 | GSM_TX — to GSM RX |
| GSM RX | Pin 8 | GSM_RX — to GSM TX (reassigned) |
| I2C LCD 16×2 | ||
| LCD SDA | A4 | I2C Data |
| LCD SCL | A5 | I2C Clock |
Arduino Code
Full sketch — includes RFID, servo gate, ultrasonic detection, LCD, and GSM SMS
① Libraries, Pins & Data Structures
#include <SPI.h> #include <MFRC522.h> #include <Servo.h> #include <LiquidCrystal_I2C.h> #include <SoftwareSerial.h> #define RST_PIN 9 #define SS_PIN 10 #define TRIG_PIN 6 #define ECHO_PIN 7 #define IR_PIN 4 #define SERVO_PIN 5 #define BUTTON_PIN 2 #define GSM_TX 3 #define GSM_RX 8 // Reassigned to avoid pin 2 conflict MFRC522 mfrc522(SS_PIN, RST_PIN); Servo gateServo; LiquidCrystal_I2C lcd(0x27, 16, 2); SoftwareSerial gsm(GSM_RX, GSM_TX); SoftwareSerial serialComm(3, 4); // Registered RFID cards with prepaid balances struct RFIDCard { String uid; int balance; }; RFIDCard rfidCards[] = { {"F3E45216", 200}, {"A1B2C3D4", 100} }; const int tollFee = 50;
② Setup & Main Detection Loop
void setup() { Serial.begin(9600); SPI.begin(); mfrc522.PCD_Init(); lcd.init(); lcd.backlight(); lcd.print("Toll Booth Ready"); pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); pinMode(IR_PIN, INPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); gateServo.attach(SERVO_PIN); gateServo.write(0); // Barrier closed at startup gsm.begin(9600); serialComm.begin(9600); } void loop() { if (detectVehicle()) { lcd.setCursor(0, 0); lcd.print("Vehicle Detected"); delay(500); lcd.clear(); if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { String cardID = getCardID(); int balanceIdx = getBalanceIndex(cardID); lcd.setCursor(0, 0); if (balanceIdx != -1) { if (rfidCards[balanceIdx].balance >= tollFee) { lcd.print("Pay 50 Taka?"); bool paid = false; unsigned long t = millis(); while (millis() - t < 10000) { // 10s window if (digitalRead(BUTTON_PIN) == LOW) { paid = true; break; } } if (paid) { rfidCards[balanceIdx].balance -= tollFee; lcd.setCursor(0, 1); lcd.print("Payment Success "); serialComm.println("Payment Successful"); String msg = "Toll: 50 deducted. Balance: " + String(rfidCards[balanceIdx].balance); sendSMS("+8801743648510", msg); openGate(); } else { lcd.setCursor(0, 1); lcd.print("Payment Timeout"); serialComm.println("Payment Timeout"); } } else { lcd.print("Insufficient Bal"); serialComm.println("Insufficient Balance"); delay(2000); } } else { lcd.print("Card Not Found"); serialComm.println("Card Not Recognized"); delay(2000); } mfrc522.PICC_HaltA(); lcd.clear(); } } else { lcd.setCursor(0, 0); lcd.print("Waiting for Car "); delay(500); lcd.clear(); } }
③ Helper Functions
// Ultrasonic distance — returns true if vehicle within 50cm bool detectVehicle() { digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); long dur = pulseIn(ECHO_PIN, HIGH); int dist = dur * 0.034 / 2; return (dist < 50); } // Read RFID UID as uppercase hex string String getCardID() { String id = ""; for (byte i = 0; i < mfrc522.uid.size; i++) { if (mfrc522.uid.uidByte[i] < 0x10) id += "0"; id += String(mfrc522.uid.uidByte[i], HEX); } id.toUpperCase(); return id; } // Find card index by UID, returns -1 if not found int getBalanceIndex(String uid) { for (int i = 0; i < (int)(sizeof(rfidCards)/sizeof(rfidCards[0])); i++) if (rfidCards[i].uid == uid) return i; return -1; } // Servo: open gate, wait for vehicle to pass, then close void openGate() { lcd.setCursor(0, 0); lcd.print("Opening Gate..."); gateServo.write(90); delay(5000); while (digitalRead(IR_PIN) == LOW); // Wait for vehicle to pass lcd.setCursor(0, 0); lcd.print("Closing Gate..."); gateServo.write(0); delay(1500); lcd.clear(); } // GSM AT commands — send SMS via SIM800L void sendSMS(String phone, String msg) { gsm.print("AT+CMGF=1\r"); delay(100); gsm.print("AT+CMGS=\"" + phone + "\"\r"); delay(100); gsm.print(msg); delay(100); gsm.write(26); // Ctrl+Z to send delay(5000); Serial.println("SMS sent to " + phone); }
How It Works
Step-by-step operation of the automatic toll gate system
Vehicle Approaches — Ultrasonic Detects
The HC-SR04 sends a 10μs TRIG pulse and measures the ECHO return time. If distance is under 50cm, a vehicle is confirmed at the booth — LCD shows "Vehicle Detected" and the RFID scan is activated.
Driver Scans RFID Card
The MFRC522 reads the card's UID via SPI. The UID is converted to an uppercase hex string and searched against the rfidCards[] array. If found, the balance check begins; if not, "Card Not Found" displays.
Balance Check & Payment Prompt
If the card balance ≥ tollFee (50), the LCD shows "Pay 50 Taka?" and a 10-second countdown begins. The driver presses the green button to confirm. If no press within 10 seconds, "Payment Timeout" displays.
Payment Confirmed — Deduct & Notify
On button press, the toll fee is deducted from the card's balance in memory. A status update is sent to the second Arduino via SoftwareSerial. The GSM module sends an SMS to the registered phone number with the remaining balance.
Gate Opens — Vehicle Passes
gateServo.write(90) lifts the barrier. The system waits 5 seconds minimum, then polls the IR sensor. When the IR sensor clears (vehicle fully through), the gate closes with gateServo.write(0).
System Resets to Standby
LCD clears, the system returns to "Waiting for Car" state, and the ultrasonic sensor resumes polling for the next vehicle. The process repeats for every vehicle.
Key Concepts Explained
Protocols and techniques used in this advanced Arduino project
Serial Peripheral Interface Protocol
The MFRC522 communicates via SPI using 4 lines: MOSI (master out), MISO (master in), SCK (clock), and SS (chip select). The Arduino acts as SPI master. When mfrc522.PICC_IsNewCardPresent() returns true, the reader has detected a card in its field, and PICC_ReadCardSerial() retrieves the full UID.
AT Commands via SoftwareSerial
The SIM800L uses Hayes AT command set over UART. AT+CMGF=1 sets text mode, AT+CMGS="number" specifies the recipient, the message text is sent next, and write(26) (Ctrl+Z, ASCII 26) tells the modem to dispatch the SMS. SoftwareSerial emulates UART on non-hardware pins.
Inter-Integrated Circuit 2-Wire Bus
The I2C LCD uses only two wires (SDA + SCL) compared to the 6–8 wires of parallel LCD wiring. A PCF8574 I/O expander chip on the LCD backpack converts I2C signals to the parallel interface the LCD controller needs. The LiquidCrystal_I2C library handles all addressing and data framing.
Pulse Width Modulation Positioning
A servo motor position is set by the width of a PWM pulse: ~1ms = 0°, ~1.5ms = 90°, ~2ms = 180°. gateServo.write(0) closes the barrier and gateServo.write(90) opens it. The Servo library handles PWM generation on pin 5 automatically — no manual timing needed.
Sound Echo Time-of-Flight
The HC-SR04 emits a 40kHz ultrasonic burst (TRIG HIGH for 10μs), then measures how long the echo takes to return. Distance = (echo duration × speed of sound) ÷ 2. At 20°C, speed of sound ≈ 343 m/s, so the formula becomes distance = duration × 0.034 / 2 in centimetres.
Real-World Applications
Where this smart toll gate system can be deployed
Highway Toll Booths
Automate toll collection on expressways — reduce queues and eliminate manual cash handling
Smart City Traffic
Integrate with city-wide traffic management systems for congestion pricing and zone access
Parking Lot Control
Automatic entry and exit barrier for prepaid parking passes — logs timestamps per vehicle
Factory Vehicle Entry
Authenticate registered delivery vehicles — log all entries and deny unauthorized access
Transport Monitoring
RFID-based bus or truck fleet tracking at checkpoints with timestamp logging
Campus Gate Control
University or school vehicle access control — only registered staff/student vehicles enter
Future Enhancements
Ways to extend and upgrade this project
Comments
Post a Comment