#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <ESP32Servo.h>
#include <LiquidCrystal.h>
#include <SPI.h>
#include <MFRC522.h>
// ========= WiFi =========
const char* ssid = "Wokwi-GUEST";
const char* password = "";
String SERVER_URL = "http://eugenie-confabulatory-undespotically.ngrok-free.dev/api/update";
// ========= Ultrasonic Pins =========
const int TRIG1 = 32; const int ECHO1 = 34;
const int TRIG2 = 33; const int ECHO2 = 35;
const int TRIG3 = 25; const int ECHO3 = 36;
const int TRIG_ENTRY = 26; const int ECHO_ENTRY = 39;
const int TRIG_EXIT = 27; const int ECHO_EXIT = 4;
// ========= Servo =========
const int SERVO_ENTRY_PIN = 13;
const int SERVO_EXIT_PIN = 12;
// ========= LEDs =========
const int LED_GREEN = 16;
// ========= LCD =========
LiquidCrystal lcd(23, 22, 21, 19, 18, 5);
// ========= RFID =========
#define RFID_SS 14
#define RFID_RST 2
MFRC522 rfid(RFID_SS, RFID_RST);
// ========= Allowed Cards =========
String allowedCards[] = {
"DE AD BE EF",
"12 34 56 78"
};
const int allowedCount = 2;
// ========= States =========
bool spot1=false, spot2=false, spot3=false;
bool entryGateOpen=false, exitGateOpen=false;
// ========= Objects =========
Servo entryServo;
Servo exitServo;
// ========= Helpers =========
void setGate(Servo &s, bool openNow) {
s.write(openNow ? 90 : 0);
}
bool hasFreeSpot() {
return (!spot1 || !spot2 || !spot3);
}
long readDistanceCM(int trigPin, int echoPin) {
digitalWrite(trigPin, LOW); delayMicroseconds(2);
digitalWrite(trigPin, HIGH); delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long d = pulseIn(echoPin, HIGH, 25000);
if (d == 0) return 999;
return d * 0.034 / 2;
}
bool isOccupied(int trig, int echo) {
return readDistanceCM(trig, echo) <= 10;
}
bool isCarAtGate(int trig, int echo) {
return readDistanceCM(trig, echo) <= 15;
}
// ========= RFID Check =========
bool isCardAllowed() {
if (!rfid.PICC_IsNewCardPresent()) return false;
if (!rfid.PICC_ReadCardSerial()) return false;
String uid="";
for (byte i=0;i<rfid.uid.size;i++) {
if (rfid.uid.uidByte[i]<0x10) uid+="0";
uid+=String(rfid.uid.uidByte[i],HEX);
if (i<rfid.uid.size-1) uid+=" ";
}
uid.toUpperCase();
Serial.println(uid);
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
for (int i=0;i<allowedCount;i++) {
if (uid==allowedCards[i]) return true;
}
return false;
}
// ========= LCD =========
void showSlots() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("S1:");
lcd.print(spot1?"F":"E");
lcd.print(" S2:");
lcd.print(spot2?"F":"E");
lcd.setCursor(0,1);
lcd.print("S3:");
lcd.print(spot3?"F":"E");
}
// ========= Setup =========
void setup() {
Serial.begin(115200);
pinMode(TRIG1,OUTPUT); pinMode(ECHO1,INPUT);
pinMode(TRIG2,OUTPUT); pinMode(ECHO2,INPUT);
pinMode(TRIG3,OUTPUT); pinMode(ECHO3,INPUT);
pinMode(TRIG_ENTRY,OUTPUT); pinMode(ECHO_ENTRY,INPUT);
pinMode(TRIG_EXIT,OUTPUT); pinMode(ECHO_EXIT,INPUT);
pinMode(LED_GREEN,OUTPUT);
entryServo.attach(SERVO_ENTRY_PIN);
exitServo.attach(SERVO_EXIT_PIN);
setGate(entryServo,false);
setGate(exitServo,false);
lcd.begin(16,2);
lcd.setCursor(0,0); lcd.print("Welcome in our");
lcd.setCursor(0,1); lcd.print("Parking");
delay(3000);
lcd.clear();
WiFi.begin(ssid,password);
while(WiFi.status()!=WL_CONNECTED) delay(200);
rfid.PCD_Init(); // ✅ استخدم SPI الافتراضي
spot1=isOccupied(TRIG1,ECHO1);
spot2=isOccupied(TRIG2,ECHO2);
spot3=isOccupied(TRIG3,ECHO3);
showSlots();
}
// ========= Main Loop =========
void loop() {
// Update slots
spot1=isOccupied(TRIG1,ECHO1);
spot2=isOccupied(TRIG2,ECHO2);
spot3=isOccupied(TRIG3,ECHO3);
digitalWrite(LED_GREEN, hasFreeSpot());
// ENTRY GATE
if (!entryGateOpen && isCarAtGate(TRIG_ENTRY,ECHO_ENTRY)) {
if (!isCardAllowed()) {
lcd.clear();
lcd.print("ACCESS DENIED");
delay(1500);
showSlots();
return;
}
if (!hasFreeSpot()) {
lcd.clear();
showSlots();
return;
}
entryGateOpen=true;
setGate(entryServo,true);
delay(1500);
entryGateOpen=false;
setGate(entryServo,false);
}
// ========= EXIT GATE =========
if (!exitGateOpen && isCarAtGate(TRIG_EXIT,ECHO_EXIT)) {
exitGateOpen = true;
setGate(exitServo,true);
delay(3000);
}
if (exitGateOpen && !isCarAtGate(TRIG_EXIT,ECHO_EXIT)) {
setGate(exitServo,false);
exitGateOpen = false;
delay(1000);
}
showSlots();
delay(300);
}