RFID Smart Parking System
A reader does not report one tap — it reports a burst of reads, and only the database's own toggle can say what actually happened.
- Arduino
- RFID
- MySQL
About this project
An Arduino at the gate reads an RFID tag with an MFRC522 module, opens a barrier LED, and prints every single read over serial as CSV. bridge.py reads that stream — live, or from a bundled sample log if you have no hardware at all — and turns it into correct ENTER/EXIT records and a live occupancy count in MySQL.
An RFID reader does not report "a card was presented once." It reports "a card is in range," over and over, for as long as a human hand holds it near the antenna — one tap is a burst of reads, not one event. A naive handler that treats every read as one event can flip a car's own status back and forth mid-swipe. This project fixes it two ways: a debounce keyed per UID, so a chattering burst collapses to exactly one event without also swallowing a different car that arrives a millisecond later, and a toggle driven by what the database currently believes rather than what the Arduino's own un-debounced local guess says. Occupancy itself is a COUNT() of live rows, and the README proves — with a real run, not a claim — exactly how a running counter kept alongside it quietly drifts the first time anyone corrects a row by hand.
What you will learn
- Debounce a stream of sensor reads keyed per entity, not with one blanket ignore window
- Drive a status toggle from durable database state instead of trusting a device's local guess
- Compute a live count with COUNT() and prove, by actually running it, why a running counter drifts
- Parse a real serial CSV stream and handle a torn or malformed line without crashing
- Read an SPI protocol from a datasheet and reason through timing with no toolchain to compile against
Before you start
- Comfortable with Python and basic SQL
- MySQL installed and reachable — any recent version
- Optional hardware: an Arduino UNO and an MFRC522 RFID module
New to Arduino? The free Arduino course covers everything this project assumes.
Academic integrity notice
These projects are provided for learning, experimentation and reference. Understand the code, modify it for your own requirements, and acknowledge external work according to your institution’s academic policies. Priodemy does not supply work to be submitted as your own.
Features
- Per-UID debounce window that survives a chattering multi-read burst, keyed correctly
- Status toggle driven by the database's own record, never by the reader's local guess
- Occupancy computed live with COUNT(), demonstrated — by actually running it — to never drift
- REJECTED_FULL and IGNORED_DEBOUNCE logged, not silently dropped, so nothing is unexplained
- Runs completely with no hardware — a bundled sample serial log replays real Arduino output
- Graceful handling of a malformed or empty-UID row instead of crashing the bridge
Technology stack
Track: IoT & Hardware · Level: Major project
What is included
- parking_gate.ino, bridge.py, schema.sql, and a bundled sample_serial_log.csv, all commented throughout
- A README with the real, reproduced transcript of a full run against MySQL — not a mocked-up example
- Wiring diagram, parts list, and five suggested extensions
Delivered as a 23 KB ZIP. SHA-256 published under Changelog so you can verify it.
System requirements
- Operating system
- Any OS for bridge.py and MySQL; Windows for the Priodemy Labs simulator
- Runtime
- Python 3.8+, MySQL 8.x or compatible, Arduino IDE 2.x for the sketch itself
- Database
- MySQL
- Hardware
- Optional — Arduino UNO, MFRC522 RFID module, 2 or more RFID cards or fobs
Licence
Learn from it, change it, and use it in your own coursework and personal projects. Do not resell it or pass it off as your own original work.
- Personal and educational use
- Modifying the code however you like
- Using it as the basis of your own coursework, with honest acknowledgement
- Putting your modified version in a portfolio or on your own GitHub
- Reselling or redistributing the project, modified or not
- Presenting it as your own original work
- Commercial deployment — see the Commercial licence
Support window: 6 months from download.
Frequently asked
Do I need an Arduino to try this?
No. bridge.py replays a bundled sample serial log end to end against MySQL, with zero hardware — the exact commands and their real output are in the README. Point it at a serial port instead once you do have the hardware, and nothing else changes.
Why not just trust the Arduino's own ENTER/EXIT guess?
Because the reader reports a burst of reads for one tap, not a single event, and the Arduino has no idea whether the lot is full or what any other gate has seen. The sample run's own "raw" column shows its local guess getting both of those wrong, side by side with bridge.py's correct decision.
Why COUNT() instead of a counter column?
Because a counter only changes when code remembers to change it, and a real single-gate lot eventually needs a manual fix that bypasses that code — a guard waving a car through by hand. The README's drift demo does exactly that and shows COUNT() staying correct while the counter silently goes stale.
Changelog
- First release
SHA-256a849d0a9f8d4cf29c23811756cdc770e1e6964265d243ab67ef40af439eb99ac