#include <Wire.
h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
// Initialize the LCD (I2C address 0x27, 16 columns, 2 rows)
LiquidCrystal_I2C lcd(0x27, 16, 4);
const int trigPin1 = 7, echoPin1 = 6;
const int trigPin2 = 5, echoPin2 = 4;
const int trigPin3 = 3, echoPin3 = 2;
const int ledRed1 = 29, ledYellow1 = 31, ledGreen1 = 33;
const int ledRed2 = 35, ledYellow2 = 37, ledGreen2 = 39;
const int ledRed3 = 41, ledYellow3 = 43, ledGreen3 = 45;
bool isReserved1 = false, isReserved2 = false, isReserved3 = false;
int lastStatus1 = -1, lastStatus2 = -1, lastStatus3 = -1; // To track previous
status
//This is for the gate
const int trigPin4 = 8;
const int echoPin4 = 9;
const int gateControlServoPin = 10;
Servo gateControlServo;
String gateStatus = "Unknown";
void setup() {
Serial.begin(9600); // For serial communication with Serial Monitor (PC)
Serial2.begin(9600); // For serial communication with NodeMCU via Serial2
(GPIO1 and GPIO3)
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Parking System");
delay(2000);
lcd.clear();
pinMode(trigPin1, OUTPUT); pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT); pinMode(echoPin2, INPUT);
pinMode(trigPin3, OUTPUT); pinMode(echoPin3, INPUT);
pinMode(ledRed1, OUTPUT); pinMode(ledYellow1, OUTPUT); pinMode(ledGreen1,
OUTPUT);
pinMode(ledRed2, OUTPUT); pinMode(ledYellow2, OUTPUT); pinMode(ledGreen2,
OUTPUT);
pinMode(ledRed3, OUTPUT); pinMode(ledYellow3, OUTPUT); pinMode(ledGreen3,
OUTPUT);
pinMode(trigPin4, OUTPUT);
pinMode(echoPin4, INPUT);
gateControlServo.attach(gateControlServoPin);
gateControlServo.write(90); // Initial position
Serial.println("System Initialized!");
}
void loop() {
handleSerialInput();
controlEntranceGate(trigPin4, echoPin4, gateControlServo);
String slotStatus1 = getSlotStatus(1, trigPin1, echoPin1, ledRed1, ledYellow1,
ledGreen1, isReserved1, lastStatus1);
String slotStatus2 = getSlotStatus(2, trigPin2, echoPin2, ledRed2, ledYellow2,
ledGreen2, isReserved2, lastStatus2);
String slotStatus3 = getSlotStatus(3, trigPin3, echoPin3, ledRed3, ledYellow3,
ledGreen3, isReserved3, lastStatus3);
updateLCD(slotStatus1, slotStatus2, slotStatus3);
delay(1000);
}
void controlEntranceGate(int trig, int echo, Servo &servo) {
// Trigger ultrasonic pulse
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
// Read echo pulse
long duration = pulseIn(echo, HIGH, 30000); // Timeout at 30 ms
if (duration == 0) {
Serial.println("Entrance: Sensor error");
gateStatus = "Sensor error";
return;
}
// Calculate distance in cm
int distance = duration * 0.034 / 2;
// Gate control logic
if (distance <= 15) {
servo.write(0); // Close gate
Serial.println("Entrance: Object Detected - Gate Closed");
gateStatus = "Gate: Closed";
} else {
servo.write(90); // Open gate
Serial.println("Entrance: Clear - Gate Open");
gateStatus = "Gate: Open";
}
}
String getSlotStatus(int slot, int trig, int echo, int ledRed, int ledYellow, int
ledGreen, bool &isReserved, int &lastStatus) {
int distance = getDistance(trig, echo);
int currentStatus = (distance > 0 && distance <= 10) ? 1 : 0;
// If the slot is reserved and now occupied, auto-cancel the reservation
if (isReserved && currentStatus == 1) {
isReserved = false;
Serial.print("Slot ");
Serial.print(slot);
Serial.println(" reservation used - now cleared.");
}
if (isReserved) {
digitalWrite(ledYellow, HIGH);
digitalWrite(ledRed, LOW);
digitalWrite(ledGreen, LOW);
return "Slot " + String(slot) + ": Reserved";
}
// Status logic (only updates if changed)
if (currentStatus != lastStatus) {
lastStatus = currentStatus;
if (currentStatus == 1) {
digitalWrite(ledRed, HIGH);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, LOW);
sendStatusToNodeMCU(slot, 1);
} else {
digitalWrite(ledRed, LOW);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, HIGH);
sendStatusToNodeMCU(slot, 0);
}
}
return "Slot " + String(slot) + (currentStatus == 1 ? ": Occupied" : ":
Available");
}
void updateLCD(String status1, String status2, String status3) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(status1);
lcd.setCursor(0, 1);
lcd.print(status2);
lcd.setCursor(0, 2);
lcd.print(status3);
lcd.setCursor(0, 3); lcd.print(gateStatus);
}
int getDistance(int trig, int echo) {
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
long duration = pulseIn(echo, HIGH, 30000);
return (duration == 0) ? -1 : duration * 0.034 / 2;
}
void handleSerialInput() {
if (Serial2.available() > 0) {
String message = Serial2.readString();
message.trim();
message.toUpperCase(); // Make sure to handle case insensitivity.
Serial.print("Received from NodeMCU: ");
Serial.println(message);
// Handling slot reservations based on the message received from NodeMCU
if (message == "SLOT SLOT 1 RESERVED") {
isReserved1 = true;
Serial.println("Slot 1 RESERVED");
} else if (message == "SLOT 1 CANCELLED") {
isReserved1 = false;
Serial.println("Slot 1 Reservation CANCELED");
}
if (message == "SLOT SLOT 2 RESERVED") {
isReserved2 = true;
Serial.println("Slot 2 RESERVED");
} else if (message == "SLOT 2 CANCELLED") {
isReserved2 = false;
Serial.println("Slot 2 Reservation CANCELED");
}
if (message == "SLOT SLOT 3 RESERVED") {
isReserved3 = true;
Serial.println("Slot 3 RESERVED");
} else if (message == "SLOT 3 CANCELLED") {
isReserved3 = false;
Serial.println("Slot 3 Reservation CANCELED");
}
}
}
void sendStatusToNodeMCU(int slot, int status) {
String message = "SLOT " + String(slot) + " STATUS " + String(status);
Serial2.println(message); // Send the message to NodeMCU
Serial.print("Sending status to NodeMCU: ");
Serial.println(message); // Log the status being sent to NodeMCU
}