// Proje: ESP32 MQTT Interkom Kontrol Ünitesi
// Platform: Lolin32 OLED (SDA=4, SCL=5 → OLED'e ayrılmış, dokunulmuyor)
#include <WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ── OLED ────────────────────────────────────────────────────────────────────
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ── WiFi & MQTT ──────────────────────────────────────────────────────────────
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqttServer = "broker.emqx.io";
const int port = 1883;
// ── Pin Tanımlamaları ────────────────────────────────────────────────────────
// GPIO 4 → OLED SDA (kullanılmıyor)
// GPIO 5 → OLED SCL (kullanılmıyor)
const int pinRelay = 16; // Röle (eski GPIO 5, OLED SCL'den taşındı)
const int doorSensorPin = 17; // Kapı reed sensörü
// ── DIP Switch (8 adet) ──────────────────────────────────────────────────────
const int DIP_COUNT = 8;
const int dipPins[] = {33, 32, 13, 12, 14, 27, 26, 25};
String blokDaire[]= {"A11","A21","B11","B21","C11","C21","D11","D21"};
bool lastDipStates[DIP_COUNT];
// ── MQTT ─────────────────────────────────────────────────────────────────────
char clientId[50];
WiFiClient espClient;
PubSubClient client(espClient);
Ticker relayTimer;
// ── Kapı sensörü zamanlama ───────────────────────────────────────────────────
unsigned long lastPublishTime = 0;
const long interval = 2000;
bool lastSentState = HIGH;
// ── OLED yardımcı: tek satır mesaj ──────────────────────────────────────────
void oledMsg(const char* line1, const char* line2 = "", const char* line3 = "") {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0); display.println(line1);
display.setCursor(0, 20); display.println(line2);
display.setCursor(0, 40); display.println(line3);
display.display();
}
// ── Röle otomatik kapat ──────────────────────────────────────────────────────
void turnOffRelay() {
digitalWrite(pinRelay, LOW);
Serial.println("Zaman Doldu: Role KAPANDI");
client.publish("role/lock", "OFF");
oledMsg("INTERKOM", "Kapi Kilitledi", "role: OFF");
}
// ── WiFi Bağlantısı ──────────────────────────────────────────────────────────
void wifiConnect() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
oledMsg("WiFi...", ssid);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nWiFi Baglandi!");
oledMsg("WiFi OK", WiFi.localIP().toString().c_str());
delay(1000);
}
// ── MQTT Callback ─────────────────────────────────────────────────────────────
void callback(char* topic, byte* message, unsigned int length) {
String payload = "";
for (unsigned int i = 0; i < length; i++) payload += (char)message[i];
Serial.print("MQTT ["); Serial.print(topic); Serial.print("]: "); Serial.println(payload);
if (payload == "ON") {
digitalWrite(pinRelay, HIGH);
relayTimer.once(1.5, turnOffRelay);
oledMsg("INTERKOM", "Kapi Acildi!", "role: ON");
} else if (payload == "OFF") {
digitalWrite(pinRelay, LOW);
relayTimer.detach();
oledMsg("INTERKOM", "Kapi Kilitledi", "role: OFF");
}
}
// ── MQTT Yeniden Bağlanma ─────────────────────────────────────────────────────
void mqttReconnect() {
while (!client.connected()) {
oledMsg("MQTT...", mqttServer);
if (client.connect(clientId)) {
client.subscribe("role/lock");
Serial.println("MQTT Bagli");
oledMsg("MQTT OK", "role/lock", "subscribe edildi");
delay(800);
} else {
Serial.print("MQTT hata: "); Serial.println(client.state());
delay(5000);
}
}
}
// ── DIP Switch Kontrolü ───────────────────────────────────────────────────────
void checkDipSwitches() {
for (int i = 0; i < DIP_COUNT; i++) {
bool currentState = digitalRead(dipPins[i]);
if (currentState == HIGH && lastDipStates[i] == LOW) {
char topic[30];
sprintf(topic, "daire/%s/open", blokDaire[i].c_str());
client.publish(topic, "DING");
Serial.print("Daire Butonu: "); Serial.println(topic);
oledMsg("ZILI CALINDI", blokDaire[i].c_str(), topic);
delay(50); // debounce
}
lastDipStates[i] = currentState;
}
}
// ── Setup ─────────────────────────────────────────────────────────────────────
void setup() {
Serial.begin(115200);
snprintf(clientId, sizeof(clientId), "ESP32-%ld", random(1000000));
// OLED başlat (Wire varsayılan olarak SDA=4, SCL=5 — Lolin32 OLED için SDA=5, SCL=4)
// https://randomnerdtutorials.com/esp32-built-in-oled-ssd1306/
Wire.begin(4, 5);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED bulunamadi!");
while (true); // OLED yoksa dur
}
display.clearDisplay();
oledMsg("Baslatiliyor...");
// Pin modları
pinMode(pinRelay, OUTPUT);
digitalWrite(pinRelay, LOW);
pinMode(doorSensorPin, INPUT_PULLUP);
for (int i = 0; i < DIP_COUNT; i++) {
pinMode(dipPins[i], INPUT_PULLDOWN);
lastDipStates[i] = digitalRead(dipPins[i]); // Açılış durumunu kaydet
}
wifiConnect();
client.setServer(mqttServer, port);
client.setCallback(callback);
}
// ── Loop ──────────────────────────────────────────────────────────────────────
void loop() {
if (!client.connected()) mqttReconnect();
client.loop();
checkDipSwitches();
// Kapı sensörü
bool currentDoorState = digitalRead(doorSensorPin);
unsigned long currentMillis = millis();
if (currentDoorState == LOW) {
if (currentMillis - lastPublishTime >= interval) {
lastPublishTime = currentMillis;
client.publish("door/status", "DOOROPEN");
lastSentState = LOW;
}
} else if (currentDoorState == HIGH && lastSentState == LOW) {
client.publish("door/status", "DOORCLOSE");
lastSentState = HIGH;
}
}KAPI DURUM SW
KAPI OMATİĞİ RÖLE
DAİRE NO
Loading
ssd1306
ssd1306