#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP32Servo.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/* ================= WIFI ================= */
const char *ssid = "Wokwi-GUEST";
const char *password = "";
/* ================= MQTT ================= */
const char *mqtt_server = "broker.hivemq.com";
#define TOPIC_ENTRY_RFID "parking/rasya/entry/rfid"
#define TOPIC_EXIT_RFID "parking/rasya/exit/rfid"
#define TOPIC_EXIT_SERVO "parking/rasya/exit/servo"
#define TOPIC_LCD "parking/rasya/lcd"
/* ================= RFID ================= */
#define SS_ENTRY_PIN 5
#define RST_ENTRY_PIN 27
#define SS_EXIT_PIN 15
#define RST_EXIT_PIN 17
MFRC522 rfidEntry(SS_ENTRY_PIN, RST_ENTRY_PIN);
MFRC522 rfidExit(SS_EXIT_PIN, RST_EXIT_PIN);
/* ================= SERVO ================= */
Servo servoEntry;
Servo servoExit;
/* ================= OLED ================= */
Adafruit_SSD1306 display(128, 64, &Wire, -1);
bool oledOK = false;
/* ================= MQTT ================= */
WiFiClient espClient;
PubSubClient client(espClient);
/* ================= STATE ================= */
enum State {
IDLE,
MASUK,
MENUNGGU,
TAMPIL_BIAYA,
TERIMA_KASIH
};
State currentState = IDLE;
State lastState = IDLE;
/* ================= TIMER ================= */
unsigned long lastMillis = 0;
unsigned long lastScan = 0;
/* ================= SERVO TIMER ================= */
bool servoExitAktif = false;
unsigned long servoExitMillis = 0;
/* ================= OLED ================= */
void showOLED(String a, String b)
{
if (!oledOK) return;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println(a);
display.setCursor(0, 40);
display.println(b);
display.display();
}
/* ================= WIFI ================= */
void setup_wifi()
{
Serial.println("Connecting WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi Connected!");
}
/* ================= MQTT ================= */
void reconnect()
{
while (!client.connected())
{
Serial.println("Connecting MQTT...");
String clientId = "ESP32-" + String(random(1000));
if (client.connect(clientId.c_str()))
{
Serial.println("MQTT Connected!");
client.subscribe(TOPIC_EXIT_SERVO);
client.subscribe(TOPIC_LCD);
}
else
{
Serial.println("Retry MQTT...");
delay(2000);
}
}
}
/* ================= CALLBACK ================= */
void callback(char *topic, byte *payload, unsigned int length)
{
String msg = "";
for (int i = 0; i < length; i++)
msg += (char)payload[i];
// ===== SERVO EXIT =====
if (String(topic) == TOPIC_EXIT_SERVO)
{
if (msg == "OPEN")
{
servoExit.write(90);
servoExitAktif = true;
servoExitMillis = millis();
}
}
// ===== OLED BIAYA =====
if (String(topic) == TOPIC_LCD)
{
int sep = msg.indexOf('|');
if (sep != -1)
{
String biaya = msg.substring(0, sep);
currentState = TAMPIL_BIAYA;
lastMillis = millis();
showOLED("Total Bayar", "Rp " + biaya);
}
}
}
/* ================= RFID ================= */
String readRFID(MFRC522 &rfid)
{
if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial())
return "";
String uid = "";
for (byte i = 0; i < rfid.uid.size; i++)
{
uid += String(rfid.uid.uidByte[i], HEX);
}
uid.toUpperCase();
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
return uid;
}
/* ================= SETUP ================= */
void setup()
{
Serial.begin(115200);
SPI.begin();
rfidEntry.PCD_Init();
rfidExit.PCD_Init();
servoEntry.attach(32);
servoExit.attach(33);
servoEntry.write(0);
servoExit.write(0);
Wire.begin();
delay(100);
// OLED INIT
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
{
oledOK = false;
}
else
{
oledOK = true;
showOLED("Tempel Kartu", "");
}
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
/* ================= LOOP ================= */
void loop()
{
if (!client.connected())
reconnect();
client.loop();
// AUTO CLOSE SERVO
if (servoExitAktif && millis() - servoExitMillis > 3000)
{
servoExit.write(0);
servoExitAktif = false;
}
// UPDATE OLED
if (currentState != lastState)
{
lastState = currentState;
switch (currentState)
{
case IDLE:
showOLED("Tempel Kartu", "");
break;
case MASUK:
showOLED("Selamat Datang", "Silahkan Masuk");
break;
case MENUNGGU:
showOLED("Menunggu", "Petugas...");
break;
case TAMPIL_BIAYA:
break;
case TERIMA_KASIH:
showOLED("Terima Kasih", "Selamat Jalan");
break;
}
}
// ===== STATE TIMER =====
if (currentState == MASUK && millis() - lastMillis > 3000)
{
servoEntry.write(0);
currentState = IDLE;
}
if (currentState == TAMPIL_BIAYA && millis() - lastMillis > 5000)
{
currentState = TERIMA_KASIH;
lastMillis = millis();
}
if (currentState == TERIMA_KASIH && millis() - lastMillis > 3000)
{
currentState = IDLE;
}
// ===== RFID MASUK =====
String uidMasuk = readRFID(rfidEntry);
if (uidMasuk != "" && millis() - lastScan > 2000)
{
lastScan = millis();
String payload = "{\"rfid\":\"" + uidMasuk + "\"}";
client.publish(TOPIC_ENTRY_RFID, payload.c_str());
servoEntry.write(90);
currentState = MASUK;
lastMillis = millis();
}
// ===== RFID KELUAR =====
String uidKeluar = readRFID(rfidExit);
if (uidKeluar != "" && millis() - lastScan > 2000)
{
lastScan = millis();
String payload = "{\"rfid\":\"" + uidKeluar + "\"}";
client.publish(TOPIC_EXIT_RFID, payload.c_str());
currentState = MENUNGGU;
}
}Loading
ssd1306
ssd1306