Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

ESP32-Based Smart Parking System with IR Sensors and LCD Display

View and Edit Project In Cirkit DesignerImage of ESP32-Based Smart Parking System with IR Sensors and LCD Display

Circuit Documentation

Summary

This circuit is designed to manage a parking system using an ESP32 microcontroller. It includes two IR sensors to detect vehicle entry and exit, two servos to control entry and exit gates, and a 16x2 I2C LCD to display the parking status. The system counts the number of vehicles in the parking lot and updates the display accordingly. When the parking lot is full, it prevents additional vehicles from entering.

Component List

  1. ESP32 Devkit V1

    • Description: Microcontroller used to control the entire system.
    • Pins: 3V3, GND, D15, D2, D4, RX2, TX2, D5, D18, D19, D21, RX0, TX0, D22, D23, EN, VP, VN, D34, D35, D32, D33, D25, D26, D27, D14, D12, D13, VIN
  2. 16x2 I2C LCD

    • Description: Display module used to show the parking status.
    • Pins: GND, VCC, SDA, SCL
  3. IR Sensor (Entry)

    • Description: Infrared sensor used to detect vehicle entry.
    • Pins: out, gnd, vcc
  4. IR Sensor (Exit)

    • Description: Infrared sensor used to detect vehicle exit.
    • Pins: out, gnd, vcc
  5. Servo (Entry Gate)

    • Description: Servo motor used to control the entry gate.
    • Pins: gnd, vcc, pulse
  6. Servo (Exit Gate)

    • Description: Servo motor used to control the exit gate.
    • Pins: gnd, vcc, pulse

Wiring Details

ESP32 Devkit V1

16x2 I2C LCD

IR Sensor (Entry)

IR Sensor (Exit)

Servo (Entry Gate)

Servo (Exit Gate)

Documented Code

#include <Arduino.h>
#include <ESP32Servo.h> // Pastikan Anda telah menginstal library ESP32Servo
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// --- Konfigurasi Pin ---
const int sensorMasukPin = 34;    // GPIO 34 untuk sensor masuk
const int sensorKeluarPin = 35;   // GPIO 35 untuk sensor keluar
const int servoMasukPin = 14;     // GPIO 14 untuk servo masuk
const int servoKeluarPin = 27;    // GPIO 27 untuk servo keluar

// --- Variabel Global ---
volatile int countKendaraan = 0;
volatile bool sensorMasukState = false;
volatile bool sensorKeluarState = false;

// --- Status Sensor ---
bool prevSensorMasuk = false;  // Status sebelumnya dari sensor masuk
bool prevSensorKeluar = false; // Status sebelumnya dari sensor keluar

// --- Objek Servo ---
Servo servoMasuk;
Servo servoKeluar;

// --- Objek LCD ---
LiquidCrystal_I2C lcd(0x27, 16, 2); // Pastikan alamat I2C sesuai dengan modul Anda

// --- Timing Servo ---
unsigned long servoMasukTimer = 0;
unsigned long servoKeluarTimer = 0;

const unsigned long servoOpenTime = 1000; // Waktu servo terbuka dalam ms

// --- State Machine untuk Servo ---
enum ServoState { IDLE, OPENING, OPEN, CLOSING };

ServoState servoMasukStateMachine = IDLE;
ServoState servoKeluarStateMachine = IDLE;

// --- Indikator LED (Opsional) ---
const int ledMasukPin = 12;  // GPIO 12 untuk LED masuk
const int ledKeluarPin = 13; // GPIO 13 untuk LED keluar

// --- Batas Maksimal Parkir ---
const int batasParkir = 10;

void IRAM_ATTR sensorMasukISR() {
  sensorMasukState = true;
}

void IRAM_ATTR sensorKeluarISR() {
  sensorKeluarState = true;
}

void setup() {
  // Inisialisasi Serial Monitor
  Serial.begin(115200);

  // Inisialisasi pin sensor
  pinMode(sensorMasukPin, INPUT_PULLUP);
  pinMode(sensorKeluarPin, INPUT_PULLUP);

  // Inisialisasi pin LED
  pinMode(ledMasukPin, OUTPUT);
  pinMode(ledKeluarPin, OUTPUT);
  digitalWrite(ledMasukPin, LOW);
  digitalWrite(ledKeluarPin, LOW);

  // Pasang ISR
  attachInterrupt(digitalPinToInterrupt(sensorMasukPin), sensorMasukISR, FALLING);
  attachInterrupt(digitalPinToInterrupt(sensorKeluarPin), sensorKeluarISR, FALLING);

  // Inisialisasi servo
  servoMasuk.attach(servoMasukPin);
  servoKeluar.attach(servoKeluarPin);

  // Inisialisasi LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Parkir: ");
  lcd.setCursor(0, 1);
  lcd.print("Status: ");

  // Inisialisasi posisi servo
  servoMasuk.write(0);  // Posisi awal servo masuk
  servoKeluar.write(0); // Posisi awal servo keluar
}

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

  // --- Penanganan Sensor Masuk ---
  if (sensorMasukState) {
    sensorMasukState = false; // Reset flag

    // Membaca status sensor masuk
    bool currentSensorMasuk = (digitalRead(sensorMasukPin) == LOW);

    // Deteksi transisi dari HIGH ke LOW
    if (currentSensorMasuk && !prevSensorMasuk) {
      if (countKendaraan < batasParkir) { // Cek apakah parkir belum penuh
        countKendaraan++;
        Serial.print("Kendaraan masuk. Total: ");
        Serial.println(countKendaraan);

        // Update tampilan LCD
        lcd.setCursor(7, 0);
        lcd.print("       "); // Clear sebelumnya
        lcd.setCursor(7, 0);
        lcd.print(countKendaraan);

        // Update Status Parkir
        updateStatusParkir();

        // Mulai state machine servo masuk
        servoMasukStateMachine = OPENING;
        servoMasukTimer = currentMillis;

        // Nyalakan LED indikator masuk
        digitalWrite(ledMasukPin, HIGH);
      } else {
        // Parkir penuh, tampilkan pesan
        Serial.println("Parkir penuh! Tidak bisa menambah kendaraan.");
        lcd.setCursor(0, 1);
        lcd.print("Penuh!            ");
      }
    }

    prevSensorMasuk = currentSensorMasuk;
  }

  // --- Penanganan Sensor Keluar ---
  if (sensorKeluarState) {
    sensorKeluarState = false; // Reset flag

    // Membaca status sensor keluar
    bool currentSensorKeluar = (digitalRead(sensorKeluarPin) == LOW);

    // Deteksi transisi dari HIGH ke LOW
    if (currentSensorKeluar && !prevSensorKeluar) {
      if (countKendaraan > 0) {
        countKendaraan--;
        Serial.print("Kendaraan keluar. Total: ");
        Serial.println(countKendaraan);

        // Update tampilan LCD
        lcd.setCursor(7, 0);
        lcd.print("       "); // Clear sebelumnya
        lcd.setCursor