#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ===== LCD I2C =====
LiquidCrystal_I2C lcd(0x27, 20, 4);
// ===== Pin Setup =====
#define TRIG_FRONT 13
#define ECHO_FRONT 12
#define TRIG_BACK 14
#define ECHO_BACK 27
#define BUZZER 19
#define BTN_ENGINE 18
#define BTN_SENSOR 5
#define LED_ENGINE 2
#define LED_LOCK 4
#define RELAY_BRAKE 15
#define LED_BRAKE 16
#define HEADLIGHT 17
#define LDR_PIN 34
#define LDR_THRESHOLD 1000 // ปรับตามความสว่าง
// ===== Auto-lock settings =====
const unsigned long AUTO_LOCK_DELAY_MS = 5000UL; // 5 วินาที หลังสตาร์ทรถ
const unsigned long AUTO_LOCK_AFTER_OFF_MS = 15000UL; // 15 วินาที หลังดับรถ
// ===== State Variables =====
bool engineOn = false;
bool sensorOn = false;
// button prev state for edge detect
int prevBtnEngine = HIGH;
int prevBtnSensor = HIGH;
// auto-lock timer
bool autoLockPending = false;
unsigned long autoLockStartMillis = 0;
unsigned long autoLockDelayMS = 0;
// ===== Function วัดระยะ Ultrasonic =====
long readDistanceCM(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH, 30000); // timeout 30ms
long distance = duration * 0.034 / 2;
return distance;
}
// ===== Lock Door =====
void lockDoorNow() {
digitalWrite(LED_LOCK, HIGH); // lock
lcd.setCursor(0,2);
lcd.print("Door: Locked ");
autoLockPending = false;
Serial.println("Door auto-locked.");
}
void cancelAutoLock() {
if (autoLockPending) {
autoLockPending = false;
Serial.println("Auto-lock canceled.");
}
}
void setup() {
Serial.begin(115200);
lcd.init();
lcd.backlight();
// Pin modes
pinMode(TRIG_FRONT, OUTPUT);
pinMode(ECHO_FRONT, INPUT);
pinMode(TRIG_BACK, OUTPUT);
pinMode(ECHO_BACK, INPUT);
pinMode(BUZZER, OUTPUT);
pinMode(LED_ENGINE, OUTPUT);
pinMode(LED_LOCK, OUTPUT);
pinMode(BTN_ENGINE, INPUT_PULLUP);
pinMode(BTN_SENSOR, INPUT_PULLUP);
pinMode(RELAY_BRAKE, OUTPUT);
pinMode(LED_BRAKE, OUTPUT);
pinMode(HEADLIGHT, OUTPUT);
// Initial Display
lcd.setCursor(0,0); lcd.print(" Smart Parking Sys ");
lcd.setCursor(0,1); lcd.print("Engine: OFF ");
lcd.setCursor(0,2); lcd.print("Door: Locked ");
lcd.setCursor(0,3); lcd.print("Sensor: OFF ");
digitalWrite(LED_LOCK, HIGH); // Locked by default
digitalWrite(LED_ENGINE, LOW);
digitalWrite(RELAY_BRAKE, LOW);
digitalWrite(LED_BRAKE, LOW);
digitalWrite(HEADLIGHT, LOW);
// init prev button states
prevBtnEngine = digitalRead(BTN_ENGINE);
prevBtnSensor = digitalRead(BTN_SENSOR);
}
void loop() {
// ===== Read buttons with edge detection =====
int curBtnEngine = digitalRead(BTN_ENGINE);
if (prevBtnEngine == HIGH && curBtnEngine == LOW) { // falling edge = pressed
engineOn = !engineOn;
if (engineOn) {
digitalWrite(LED_ENGINE, HIGH);
digitalWrite(LED_LOCK, LOW); // unlock
lcd.setCursor(0,1); lcd.print("Engine: ON ");
lcd.setCursor(0,2); lcd.print("Door: Unlocked ");
cancelAutoLock();
// Start auto-lock countdown for 5s
autoLockPending = true;
autoLockStartMillis = millis();
autoLockDelayMS = AUTO_LOCK_DELAY_MS;
} else {
digitalWrite(LED_ENGINE, LOW);
sensorOn = false;
lcd.setCursor(0,1); lcd.print("Engine: OFF ");
lcd.setCursor(0,3); lcd.print("Sensor: OFF ");
// Start auto-lock countdown for 15s if door unlocked
if (digitalRead(LED_LOCK) == LOW) { // unlocked
autoLockPending = true;
autoLockStartMillis = millis();
autoLockDelayMS = AUTO_LOCK_AFTER_OFF_MS;
lcd.setCursor(0,2); lcd.print("Door: Unlocked ");
} else {
digitalWrite(LED_LOCK, HIGH);
lcd.setCursor(0,2); lcd.print("Door: Locked ");
}
digitalWrite(RELAY_BRAKE, LOW);
digitalWrite(LED_BRAKE, LOW);
digitalWrite(HEADLIGHT, LOW);
}
delay(150); // debounce
}
prevBtnEngine = curBtnEngine;
int curBtnSensor = digitalRead(BTN_SENSOR);
if (engineOn && prevBtnSensor == HIGH && curBtnSensor == LOW) {
sensorOn = !sensorOn;
lcd.setCursor(0,3);
lcd.print(sensorOn ? "Sensor: ON " : "Sensor: OFF ");
delay(150);
}
prevBtnSensor = curBtnSensor;
// ===== Auto-lock handling =====
if (autoLockPending) {
unsigned long now = millis();
if (engineOn && autoLockDelayMS == AUTO_LOCK_AFTER_OFF_MS) {
cancelAutoLock(); // cancel exit lock if engine turned on
} else if (now - autoLockStartMillis >= autoLockDelayMS) {
lockDoorNow();
} else {
unsigned long remain = (autoLockDelayMS - (now - autoLockStartMillis)) / 1000;
lcd.setCursor(12,2);
if (remain < 10) lcd.print("0");
lcd.print(remain);
lcd.print("s");
}
} else {
lcd.setCursor(12,2); lcd.print(" ");
}
// ===== Sensor / Brake logic =====
if (engineOn && sensorOn) {
long front = readDistanceCM(TRIG_FRONT, ECHO_FRONT);
long back = readDistanceCM(TRIG_BACK, ECHO_BACK);
lcd.setCursor(0,3);
lcd.print("F:");
if (front < 0 || front > 400) lcd.print("---");
else lcd.print(front);
lcd.print("cm B:");
if (back < 0 || back > 400) lcd.print("---");
else lcd.print(back);
lcd.print("cm ");
if (front <= 40 || back <= 40) {
tone(BUZZER, 1000);
digitalWrite(RELAY_BRAKE, HIGH);
digitalWrite(LED_BRAKE, HIGH);
} else {
noTone(BUZZER);
digitalWrite(RELAY_BRAKE, LOW);
digitalWrite(LED_BRAKE, LOW);
}
} else {
noTone(BUZZER);
digitalWrite(RELAY_BRAKE, LOW);
digitalWrite(LED_BRAKE, LOW);
if (!sensorOn) {
lcd.setCursor(0,3);
lcd.print("Sensor: OFF ");
}
}
// ===== Headlight (LDR) =====
int ldrValue = analogRead(LDR_PIN);
if (engineOn) {
if (ldrValue < LDR_THRESHOLD) {
digitalWrite(HEADLIGHT, HIGH);
lcd.setCursor(0,1); lcd.print("Headlight: ON ");
} else {
digitalWrite(HEADLIGHT, LOW);
lcd.setCursor(0,1); lcd.print("Headlight: OFF ");
}
} else {
digitalWrite(HEADLIGHT, LOW);
}
delay(150);
}