Build a Smart Road Safety
Traffic Violation Detector!
Use Arduino, IR sensors, an ultrasonic sensor, and a camera module to catch speeding vehicles and red-light jumpers — just like real traffic cameras! 🚦📷
Overview
What Are We Building? 🚦
Every year in India, millions of road accidents happen because vehicles jump red lights and drive too fast. Real police departments use smart cameras and sensors to catch these violations automatically. In this project, you'll build a miniature version of that system!
Your road safety detector will use two IR sensors to measure vehicle speed, an ultrasonic sensor to detect vehicles crossing the stop line during red light, and an OV7670 camera module connected to an Arduino to capture an image when a violation is detected. An LED + buzzer signals the alert!
Detection Modes
What Violations Does It Catch? 🚔
Our system can detect three types of traffic violations — just like real-world smart surveillance!
| Violation | How It's Detected | Sensor Used | Alert |
|---|---|---|---|
| 🔴 Red Light Jumping | Vehicle crosses stop-line while signal is RED | Ultrasonic (HC-SR04) | Camera + Buzzer |
| 🚀 Overspeeding | Time between IR1 and IR2 beam breaks is too short | 2× IR Sensors | Camera + Buzzer + LED |
| ⚠️ No-Stop Zone Entry | Ultrasonic detects vehicle in restricted zone | Ultrasonic (HC-SR04) | Buzzer Alert |
| ✅ Safe Vehicle | Speed within limit, signal is GREEN | All sensors | Green LED |
Speed = Distance ÷ Time, we calculate the vehicle's speed! If it's above our set limit, we trigger an alert.Shopping List
Components You Need 🛒
All parts are easily available on Amazon India, Robocraze, or your local electronics shop in Chennai!
| # | Component | Qty | Purpose | Price (₹) |
|---|---|---|---|---|
| 1 | Arduino UNO R3 | 1 | Main controller | ₹450 |
| 2 | OV7670 Camera Module | 1 | Captures violation images | ₹350 |
| 3 | HC-SR04 Ultrasonic Sensor | 1 | Detects vehicle at stop line | ₹80 |
| 4 | IR Sensor Module (FC-51) | 2 | Speed trap beams | ₹60 × 2 = ₹120 |
| 5 | 5mm Red LED | 1 | Violation alert indicator | ₹5 |
| 6 | 5mm Green LED | 1 | Safe / all-clear indicator | ₹5 |
| 7 | Active Buzzer (5V) | 1 | Audio violation alarm | ₹30 |
| 8 | Traffic Light LED Module (optional) | 1 | Simulated signal light | ₹80 |
| 9 | 220Ω Resistors | 4 | LED current limiting | ₹10 |
| 10 | Half-size Breadboard | 1 | Prototype wiring | ₹60 |
| 11 | Jumper Wires (M-M, M-F) | 30+ | Connections | ₹80 |
| 12 | 9V Adapter or USB Power Bank | 1 | Power supply | ₹150 |
| 13 | USB-A to USB-B Cable | 1 | Upload code to Arduino | ₹50 |
| 14 | Small Cardboard / Foam Board | – | Build miniature road model | ₹30 |
| 💰 Estimated Total | ₹1,500 – ₹1,800 | |||
System Design
How Does the System Work? 🧠
Here's the complete logic flow from vehicle arrival to violation logging:
Wiring
Circuit Diagram 🔌
Complete wiring for all sensors, LEDs, buzzer, and camera module. Take your time — triple-check each connection before powering on!
╔══════════════════════════════════════════════════════════════════════════════╗ ║ MAKEMINDZ — Road Safety Traffic Violation Detector — CIRCUIT DIAGRAM ║ ╚══════════════════════════════════════════════════════════════════════════════╝ ┌───────────────────────────────────────────────────────┐ │ ARDUINO UNO R3 │ │ │ │ Pin 2 (INT0) ──────────────── IR Sensor 1 (OUT) │ ← Speed beam 1 │ Pin 3 (INT1) ──────────────── IR Sensor 2 (OUT) │ ← Speed beam 2 │ Pin 4 ──────────────── HC-SR04 TRIG │ ← Ultrasonic trigger │ Pin 5 ──────────────── HC-SR04 ECHO │ ← Ultrasonic echo │ Pin 6 ──────────────── Red LED (+) │ ← Violation LED │ Pin 7 ──────────────── Green LED (+) │ ← Safe LED │ Pin 8 ──────────────── Buzzer (+) │ ← Alert buzzer │ Pin 9 ──────────────── Traffic Light RED │ ← Simulated signal │ Pin 10 ──────────────── Traffic Light GREEN │ ← Simulated signal │ (A4/A5 optionally used for I2C LCD display) │ │ │ ── OV7670 CAMERA MODULE ──────────────────────────── │ │ Pin 11 (MOSI) ─────────────── CAM_DATA[7] │ │ Pin 12 (MISO) ─────────────── CAM_XCLK (clock out) │ │ Pin 13 (SCK) ─────────────── CAM_PCLK │ │ A0 ─────────────── CAM_HREF │ │ A1 ─────────────── CAM_VSYNC │ │ 3.3V ─────────────────────── CAM_VCC (⚠ 3.3V ONLY!) │ │ GND ─────────────────────── CAM_GND │ │ │ │ 5V ────────── (+) Power rail (breadboard) │ │ GND ───────── (–) Ground rail (breadboard) │ └───────────────────────────────────────────────────────┘ ───────────────────────────────────────────────────────────────────────────── IR SENSOR MODULE (FC-51) — Wire the SAME way for both IR1 and IR2: ───────────────────────────────────────────────────────────────────────────── [VCC pin] ─────── 5V rail (breadboard) [GND pin] ─────── GND rail (breadboard) [OUT pin] ─────── Arduino Pin 2 (IR Sensor 1) ─────── Arduino Pin 3 (IR Sensor 2) Sensor spacing: exactly 50 cm apart on the road model ───────────────────────────────────────────────────────────────────────────── HC-SR04 ULTRASONIC SENSOR: ───────────────────────────────────────────────────────────────────────────── [VCC pin] ─────── 5V rail [GND pin] ─────── GND rail [TRIG pin] ─────── Arduino Pin 4 [ECHO pin] ─────── Arduino Pin 5 Mount facing the stop line, ~30cm away from road surface ───────────────────────────────────────────────────────────────────────────── LEDs & BUZZER: ───────────────────────────────────────────────────────────────────────────── Red LED: [+] ─── 220Ω resistor ─── Arduino Pin 6 │ [–] ─── GND Green LED: [+] ─── 220Ω resistor ─── Arduino Pin 7 │ [–] ─── GND Buzzer: [+] ─── Arduino Pin 8 │ [–] ─── GND Signal RED: [+] ─── 220Ω resistor ─── Arduino Pin 9 │ [–] ─── GND Signal GRN: [+] ─── 220Ω resistor ─── Arduino Pin 10│ [–] ─── GND ───────────────────────────────────────────────────────────────────────────── PHYSICAL LAYOUT OF ROAD MODEL (top view): ───────────────────────────────────────────────────────────────────────────── [CAMERA] ──── mounted above, pointing down at road │ ══════╪═══════════════════════════════════════ ROAD ═══ [IR1] [IR2] [STOP LINE] [US] ══════════════════════════════════════════════════════ │←────── 50 cm ──────→│ │←─10cm─→│ Speed measurement zone Red light zone ⚠ OV7670 runs at 3.3V — NEVER connect its VCC to Arduino 5V pin! Use Arduino's dedicated 3.3V output pin for the camera only.
| Component | Signal | Arduino Pin | Wire Colour |
|---|---|---|---|
| IR Sensor 1 | OUT (interrupt) | Pin 2 | Blue wire |
| IR Sensor 2 | OUT (interrupt) | Pin 3 | Cyan wire |
| HC-SR04 | TRIG | Pin 4 | Purple wire |
| HC-SR04 | ECHO | Pin 5 | Purple wire |
| Red LED | Anode (+) | Pin 6 | Red wire |
| Green LED | Anode (+) | Pin 7 | Green wire |
| Buzzer | Positive (+) | Pin 8 | Orange wire |
| Signal RED LED | Anode (+) | Pin 9 | Red wire |
| Signal GREEN LED | Anode (+) | Pin 10 | Green wire |
| OV7670 Camera | XCLK / Data bus | Pins 11,12,13,A0,A1 | White wires |
Construction
Step-by-Step Build Guide 🔨
-
Build the Road Model 🛣️ Cut a piece of foam board or thick cardboard (about 60cm × 20cm) to be your "road". Use black tape or paint to create lane markings. Draw a white stop line 50cm from one end. This is where your ultrasonic sensor will sit. Your miniature road is ready!
-
Mount the IR Speed Trap Sensors 📡 Place IR Sensor 1 at one end of the road model, and IR Sensor 2 exactly 50 cm away. Mount them on small stands (lollipop sticks or cardboard L-brackets) so the IR beam crosses the road at a fixed height (~3cm above the surface). Both sensors face across the road — their beams will be broken when a vehicle passes through.
-
Set Up the Ultrasonic Sensor at the Stop Line 📏 Mount the HC-SR04 sensor beside the stop line on a small post, facing horizontally across the road. When a vehicle enters the stop-line zone, the ultrasonic sensor will detect it. Adjust its angle so it detects objects between 5–25 cm (the width of your model lane).
-
Build the Traffic Light Pole 🚦 Stack a red and green LED vertically inside a small black cardboard rectangle. Connect them through 220Ω resistors to Arduino Pins 9 and 10. Your code will alternate between red and green every 5 seconds to simulate a traffic signal cycle.
-
Mount the Camera Module 📷 Position the OV7670 camera above and behind the stop line, angled downward at ~45° to point at the road (like a real CCTV camera). Use a cardboard gantry or clamp stand. Connect all its data pins carefully — the OV7670 has 18 pins, so take your time and follow the circuit diagram.
-
Wire LEDs, Buzzer, and Arduino 🔌 Connect the red and green indicator LEDs (with 220Ω resistors) to Pins 6 and 7. Connect the active buzzer to Pin 8. Wire all component VCC to the 5V rail and GND to the GND rail on your breadboard. Double-check every connection with the circuit diagram.
-
Upload the Code 💻 Connect your Arduino to your PC via USB. Install the Arduino IDE (free at arduino.cc). Open the code below, check your pin numbers match your wiring, then click Upload. Open the Serial Monitor at 9600 baud to watch the system live!
-
Test with a Small Toy Car 🚗 Slowly slide a toy car (or a block of wood) across the IR beams and past the stop line. Push it fast to test overspeed detection. Push it slowly through a RED signal to test red-light violation. Watch the Serial Monitor for logged output. If the buzzer sounds and red LED lights — your system works! 🎉
Programming
The Arduino Code 💻
This is the full Arduino code for all three detection modes — speed trap, red-light violation, and no-stop zone entry. Copy it into the Arduino IDE.
// ================================================================ // MAKEMINDZ — Road Safety Traffic Violation Detector // Detects: Overspeeding + Red-Light Jumping + No-Stop Zone // Components: Arduino UNO, 2x IR Sensor, HC-SR04, OV7670, // Buzzer, Red/Green LEDs, Traffic Signal LEDs // ================================================================ // ── Pin Definitions ───────────────────────────────────────────── const int IR1_PIN = 2; // IR Sensor 1 (speed trap near) const int IR2_PIN = 3; // IR Sensor 2 (speed trap far) const int US_TRIG = 4; // Ultrasonic trigger const int US_ECHO = 5; // Ultrasonic echo const int RED_LED = 6; // Violation indicator LED const int GREEN_LED = 7; // All-clear LED const int BUZZER_PIN = 8; // Alert buzzer const int SIG_RED = 9; // Traffic signal RED LED const int SIG_GREEN = 10; // Traffic signal GREEN LED const int CAM_TRIGGER = 11; // Camera capture trigger pin // ── Configuration ─────────────────────────────────────────────── const float SENSOR_DISTANCE_M = 0.50; // Distance between IR sensors (metres) const float SPEED_LIMIT_MS = 0.50; // Speed limit in m/s (scale model speed) const int STOP_ZONE_CM = 20; // Distance (cm) to flag stop-line crossing const int SIGNAL_CYCLE_MS = 5000; // Traffic light cycle time (ms) // ── State variables ────────────────────────────────────────────── volatile bool ir1Triggered = false; volatile bool ir2Triggered = false; volatile unsigned long ir1Time = 0; volatile unsigned long ir2Time = 0; bool signalIsRed = true; unsigned long lastSignalChange = 0; unsigned long lastReset = 0; bool waitingForIR2 = false; // ================================================================ // INTERRUPT SERVICE ROUTINES (ISR) // These run instantly when an IR beam is broken! // ================================================================ void IRAM_ATTR onIR1Break() { if (!ir1Triggered) { ir1Triggered = true; ir1Time = micros(); // Record time in microseconds waitingForIR2 = true; } } void IRAM_ATTR onIR2Break() { if (waitingForIR2 && ir1Triggered) { ir2Triggered = true; ir2Time = micros(); waitingForIR2 = false; } } // ================================================================ // HELPER FUNCTIONS // ================================================================ // Measure distance from ultrasonic sensor (in cm) float getDistanceCM() { digitalWrite(US_TRIG, LOW); delayMicroseconds(2); digitalWrite(US_TRIG, HIGH); delayMicroseconds(10); digitalWrite(US_TRIG, LOW); long duration = pulseIn(US_ECHO, HIGH, 30000); // 30ms timeout return (duration * 0.034) / 2.0; // Convert to cm } // Trigger camera capture (pulse the trigger pin HIGH) void captureImage() { digitalWrite(CAM_TRIGGER, HIGH); delay(100); // Hold trigger for 100ms digitalWrite(CAM_TRIGGER, LOW); Serial.println("📷 Image captured!"); } // Sound violation alarm — 3 short beeps void soundAlarm() { for (int i = 0; i < 3; i++) { digitalWrite(BUZZER_PIN, HIGH); delay(200); digitalWrite(BUZZER_PIN, LOW); delay(150); } } // Log a violation to Serial Monitor void logViolation(String type, float speed) { Serial.println("════════════════════════════════"); Serial.print ("🚨 VIOLATION: "); Serial.println(type); if (speed > 0) { Serial.print (" Speed: "); Serial.print (speed, 3); Serial.println(" m/s"); } Serial.print (" Time: "); Serial.println(millis()); Serial.println("════════════════════════════════"); } // Handle a confirmed violation void triggerViolationAlert(String type, float speed) { logViolation(type, speed); digitalWrite(RED_LED, HIGH); digitalWrite(GREEN_LED, LOW); captureImage(); soundAlarm(); delay(2000); digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HIGH); } // Update the simulated traffic signal void updateTrafficSignal() { if (millis() - lastSignalChange >= SIGNAL_CYCLE_MS) { signalIsRed = !signalIsRed; lastSignalChange = millis(); digitalWrite(SIG_RED, signalIsRed ? HIGH : LOW); digitalWrite(SIG_GREEN, signalIsRed ? LOW : HIGH); Serial.print("🚦 Signal: "); Serial.println(signalIsRed ? "RED" : "GREEN"); } } // Reset IR state for next vehicle void resetIRState() { ir1Triggered = false; ir2Triggered = false; ir1Time = ir2Time = 0; waitingForIR2 = false; } // ================================================================ // SETUP // ================================================================ void setup() { Serial.begin(9600); // Sensor inputs pinMode(IR1_PIN, INPUT); pinMode(IR2_PIN, INPUT); pinMode(US_TRIG, OUTPUT); pinMode(US_ECHO, INPUT); // Outputs pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); pinMode(SIG_RED, OUTPUT); pinMode(SIG_GREEN, OUTPUT); pinMode(CAM_TRIGGER,OUTPUT); // Attach hardware interrupts for IR sensors (FALLING = beam just broken) attachInterrupt(digitalPinToInterrupt(IR1_PIN), onIR1Break, FALLING); attachInterrupt(digitalPinToInterrupt(IR2_PIN), onIR2Break, FALLING); // Startup sequence digitalWrite(GREEN_LED, HIGH); digitalWrite(SIG_RED, HIGH); // Start on RED lastSignalChange = millis(); Serial.println("🚦 MakeMindz Road Safety Detector READY!"); Serial.println(" Speed limit: 0.50 m/s (scale model)"); Serial.println(" Monitoring for violations..."); } // ================================================================ // MAIN LOOP // ================================================================ void loop() { // 1. Update the traffic signal colour updateTrafficSignal(); // 2. Check for overspeed (both IR beams triggered) if (ir1Triggered && ir2Triggered) { unsigned long elapsedMicros = ir2Time - ir1Time; if (elapsedMicros > 0) { float elapsedSec = elapsedMicros / 1000000.0; float speedMS = SENSOR_DISTANCE_M / elapsedSec; Serial.print("🚗 Vehicle speed: "); Serial.print(speedMS, 3); Serial.println(" m/s"); if (speedMS > SPEED_LIMIT_MS) { triggerViolationAlert("OVERSPEEDING", speedMS); } } delay(500); resetIRState(); } // 3. Check for red-light jumping using ultrasonic float distCM = getDistanceCM(); if (distCM > 2 && distCM < STOP_ZONE_CM) { // Vehicle detected near stop line if (signalIsRed) { triggerViolationAlert("RED LIGHT JUMP", 0); } else { // Green signal — vehicle has right of way Serial.println("✅ Vehicle passing — signal GREEN, speed OK"); digitalWrite(GREEN_LED, HIGH); } delay(1500); // Debounce — wait before next detection } // 4. Safety timeout — reset IR if no vehicle detected in 5s if (ir1Triggered && !ir2Triggered) { if (millis() - ir1Time / 1000 > 5000) { Serial.println("⏱ IR timeout — resetting"); resetIRState(); } } delay(50); // Small loop delay for stability }
SPEED_LIMIT_MS is set to 0.5 m/s for a scale model with a toy car. In a real system, you'd set this to 13.9 m/s (50 km/h). Adjust STOP_ZONE_CM to match how far your ultrasonic sensor is from the stop line on your model.Calibration Sketch (Run This First!) 🔧
// CALIBRATION SKETCH — run this first to check all sensors #include <Arduino.h> const int US_TRIG = 4, US_ECHO = 5; const int IR1 = 2, IR2 = 3; void setup() { Serial.begin(9600); pinMode(US_TRIG, OUTPUT); pinMode(US_ECHO, INPUT); pinMode(IR1, INPUT); pinMode(IR2, INPUT); Serial.println("CALIBRATION MODE — Open Serial Monitor at 9600"); } void loop() { // Ultrasonic distance digitalWrite(US_TRIG, LOW); delayMicroseconds(2); digitalWrite(US_TRIG, HIGH); delayMicroseconds(10); digitalWrite(US_TRIG, LOW); long dur = pulseIn(US_ECHO, HIGH); float cm = (dur * 0.034) / 2.0; // Print all readings Serial.print("US: "); Serial.print(cm); Serial.print(" cm | "); Serial.print("IR1: "); Serial.print(digitalRead(IR1) == LOW ? "BLOCKED" : "CLEAR"); Serial.print(" | IR2: ");Serial.println(digitalRead(IR2) == LOW ? "BLOCKED" : "CLEAR"); delay(500); }
Help & FAQ
Troubleshooting & Questions 🙋
📡 The IR sensor always shows "BLOCKED" even when nothing is in the way! ▶
This usually means the IR sensor sensitivity potentiometer needs adjustment. Use a small screwdriver to turn the blue pot on the FC-51 module until the indicator LED goes OFF when nothing blocks it and ON when you block it with your hand. Bright sunlight can also interfere — try testing in a shaded area!
📏 The ultrasonic sensor gives inconsistent readings! ▶
Check these common causes:
- Is the TRIG pulse exactly 10 microseconds? Make sure you're using
delayMicroseconds(10) - Is the sensor tilted? It should face straight across the road, not at an angle
- Is there a reflective surface nearby confusing the echo?
- Add a
30000microsecond timeout topulseIn()to prevent freezing if no echo returns
📷 How does the OV7670 actually save the image? ▶
The OV7670 outputs raw pixel data frame by frame. In this beginner project, we use a simplified trigger mode — the camera is set to capture mode and we pulse the trigger pin. For a complete implementation that actually stores images, you'd need:
- An SD card module connected to SPI (for storing the image)
- A frame buffer to capture all pixel data
- Or use a Raspberry Pi with
picameralibrary for full image storage — much easier!
For the science fair version, a Raspberry Pi 4 + Pi Camera is the recommended upgrade path!
🚗 Can I make this work with real-sized vehicles? ▶
For a real-world version, you'd need to upgrade the sensors:
- Replace IR sensors with laser + photodiode pairs for longer range (10–30m)
- Use a Raspberry Pi + Pi Camera HQ for proper image capture
- Replace ultrasonic with a radar or inductive loop sensor
- Add a GSM module (SIM800L) to SMS violations to a control centre!
The logic stays exactly the same — only the sensors change. That's the beauty of modular design!
💡 What can I add to make this project more impressive? ▶
- 📺 LCD Display — Show live speed readings and violation count on an I2C LCD screen
- 📊 Violation Counter — Use EEPROM to remember violation count across power cycles
- 📱 Bluetooth App — Send violation alerts to your phone via HC-05 + MIT App Inventor
- 🗂️ SD Card Logging — Save every violation with timestamp to a CSV file
- 🌐 IoT Dashboard — Upgrade to Arduino + ESP8266 and send data to a web server!
Achievement Unlocked!
What You've Mastered 🏆
Completing this project puts you ahead of most hobbyists — you've tackled real engineering challenges:

Comments
Post a Comment