IoT Otomasyon

IoT ile Su Kaçağı Tespiti: ESP32 Sensörler, MQTT Alarmları ve Otomatik Kesme Vanası

Retained MQTT alarmları yayınlayan ESP32 kaçak sensörleri ve su beslemesini otomatik olarak kesip biri sıfırlayana kadar kapalı tutan bir vana kontrolcüsü oluşturun.

Lavabo altında bir ESP32 probu ve ana boruda motorlu bir kesme vanası bulunan IoT ile su kaçağı tespiti düzeneği
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

IoT ile su kaçağı tespiti, lavabonun altındaki sessiz bir damlamayı telefonunuzda bir alarma ve daha da iyisi, zemin mahvolmadan kapanmış bir vanaya dönüştürür. Bu eğitimde, alarmları MQTT üzerinden yayınlayan düşük maliyetli ESP32 kaçak sensörleri ve her sensöre abone olan, su beslemesini otomatik olarak kesen ve biri sıfırlayana kadar kapalı kalan ayrı bir vana kontrolcüsü oluşturacaksınız.

Sisteme Genel Bakış

Tasarım, tespiti eylemden bilinçli olarak ayırır:

  1. Kaçak sensörü düğümleri suyun ortaya çıkabileceği her yerde durur: lavaboların altında, çamaşır makinesinin arkasında, şofbenin yanında. Her biri retained bir dry veya wet durumu yayınlar.
  2. Broker alarmları ilgilenen herkese dağıtır.
  3. Ana besleme hattının yakınındaki bir vana kontrolcüsü tek bir wildcard ile tüm kaçak topic'lerine abone olur ve ilk wet durumunda motorlu bir küresel vanayı kapatır.
  4. Telefonunuz, Home Assistant veya Node-RED de bildirimler ve geçmiş için abone olur.

Rolleri ayırmak, vana koduna dokunmadan sensör ekleyebileceğiniz ve istediğiniz sayıda uygulamanın aynı alarmı izleyebileceği anlamına gelir. Aynı zamanda vana kontrolcüsünün güvenli tarafta arızalanması (fail safe) gerektiği anlamına da gelir; bunu aşağıda ele alıyoruz.

Kaçak Sensörleri Nereye Yerleştirilmeli?

Kaçaklar öngörülebilir yerlerde başlar. Su aşağı doğru akıp yayılmadan önce biriktiği için sensörleri bu noktaların her birinin yakınındaki en alçak noktaya koyun:

Konum Tipik neden Yerleştirme ipucu
Mutfak lavabosunun altı Gevşek sifon, arızalı spiral hortum Dolap tabanının arkasında, besleme vanalarının altında
Çamaşır makinesinin arkası Patlamış giriş hortumu, tıkalı tahliye Zeminde, doğrudan hortum bağlantılarının altında
Şofbenin yanı Korozyona uğramış tank, emniyet ventili tahliyesi Damlama tavasının içinde veya en alçak kenarında
Bulaşık makinesi Kapı contası, giriş valfi Erişilebiliyorsa alt süpürgeliğin altında
Banyo klozetleri ve lavabo dolapları Doldurma valfi, çatlak besleme hattı Klozet tabanının arkasında, lavabo dolabının içinde
Bodrum veya tesisat odası Ana besleme, drenaj pompası arızası Yer süzgecinin yakınında, en alçak köşede

Her sensörü bir numarayla değil, konumuyla adlandırın. Gece saat 3'te bir alarm geldiğinde laundry nereye koşacağınızı söyler; sensor-4 söylemez.

Malzeme Listesi

Parça Adet Amaç
ESP32 DevKit Sensör başına 1 + vana için 1 Wi-Fi ve MQTT
İki paslanmaz çelik vida veya bir PCB probu Sensör başına 1 çift Suyun köprülediği elektrotlar
100 kΩ direnç Sensör başına 1 Analog okuma için pull-down
Uç durdurmalı, 12 V motorlu küresel vana 1 Ana beslemeyi keser
2 kanallı röle modülü 1 Vananın açma/kapama kablolarını sürer
12 V güç kaynağı 1 Vana gücü
İsteğe bağlı buzzer Sensör başına 1 Ağ olmadan yerel alarm

İki temas pedi olan hazır kaçak probları, küçük bir plastik kutudan geçirilmiş vidalar kadar iyi çalışır. Önemli olan, ince bir su tabakasının onları köprüleyebilmesi için elektrotların zeminden bir iki milimetre yukarıda durmasıdır.

Bir Kaçak Sensörünün Bağlantıları

Su, bir kabloya kıyasla elektriği zayıf iletir ve elektrotlardaki sabit bir DC gerilimi aylar içinde korozyona yol açar. Çözüm, probu yalnızca ölçüm yaparken beslemektir:

Bağlantı ESP32 pini
Elektrot A GPIO 25 (uyarma, yalnızca örnekleme sırasında HIGH yapılır)
Elektrot B GPIO 34 (ADC girişi)
100 kΩ direnç GPIO 34'ten GND'ye
İsteğe bağlı buzzer GPIO 26

Kuruyken ADC sıfıra yakın okur. Islakken akım GPIO 25'ten suyun içinden GPIO 34'e akar ve okuma yükselir. Musluk suyu genellikle belirgin bir sıçrama verir; damıtılmış su neredeyse hiç iletmez, ancak gerçek kaçaklar nadiren damıtılmış sudur.

IoT ile Su Kaçağı Tespiti için Kaçak Sensörü Sketch'i

Düğüm iki saniyede bir örnekleme yapar, alarm vermeden önce art arda üç ıslak okuma bekler (paspas sırasında sıçrayan suyu yok saymak için) ve yeni abonelerin anında görmesi için retained bir durum yayınlar.

#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.connectmq.com";
const char* BASE = "connectmq/demo/w5n8c1/home1";   // your own random prefix
const char* LOCATION = "kitchen-sink";
const char* CLIENT_ID = "leak-kitchen-sink-w5n8c1";

const int EXCITE_PIN = 25;
const int SENSE_PIN = 34;
const int BUZZER_PIN = 26;
const int WET_THRESHOLD = 600;      // 0..4095, calibrate with a wet cloth
const int CONFIRM_SAMPLES = 3;

WiFiClient net;
PubSubClient mqtt(net);
char tState[96], tAvail[96], tRaw[96];
bool wet = false;
int wetCount = 0, dryCount = 0;

int readProbe() {
  digitalWrite(EXCITE_PIN, HIGH);
  delay(5);
  int v = analogRead(SENSE_PIN);
  digitalWrite(EXCITE_PIN, LOW);
  return v;
}

void connectMqtt() {
  while (!mqtt.connected()) {
    if (mqtt.connect(CLIENT_ID, nullptr, nullptr, tAvail, 1, true, "offline")) {
      mqtt.publish(tAvail, "online", true);
      mqtt.publish(tState, wet ? "wet" : "dry", true);
    } else {
      delay(3000);
    }
  }
}

void setup() {
  pinMode(EXCITE_PIN, OUTPUT);
  digitalWrite(EXCITE_PIN, LOW);
  pinMode(BUZZER_PIN, OUTPUT);
  snprintf(tState, sizeof tState, "%s/%s/leak/state", BASE, LOCATION);
  snprintf(tAvail, sizeof tAvail, "%s/%s/leak/availability", BASE, LOCATION);
  snprintf(tRaw, sizeof tRaw, "%s/%s/leak/raw", BASE, LOCATION);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  mqtt.setServer(BROKER, 1883);
}

void loop() {
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();

  static unsigned long last = 0;
  if (millis() - last < 2000) return;
  last = millis();

  int v = readProbe();
  if (v > WET_THRESHOLD) { wetCount++; dryCount = 0; }
  else { dryCount++; wetCount = 0; }

  if (!wet && wetCount >= CONFIRM_SAMPLES) {
    wet = true;
    mqtt.publish(tState, "wet", true);
  } else if (wet && dryCount >= 15) {   // 30 s dry before clearing
    wet = false;
    mqtt.publish(tState, "dry", true);
  }
  digitalWrite(BUZZER_PIN, wet ? HIGH : LOW);   // local alarm works offline

  static unsigned long lastRaw = 0;
  if (millis() - lastRaw > 60000) {
    lastRaw = millis();
    char buf[8];
    snprintf(buf, sizeof buf, "%d", v);
    mqtt.publish(tRaw, buf);   // useful for calibration and drift
  }
}

Buzzer yerel olarak sürülür; böylece Wi-Fi kapalıyken bile bir kaçak duyulabilir. Bu tür bir yerel yedek, güvenlikle ilgili her projede iyi bir alışkanlıktır.

Vana Kontrolcüsü

Vana düğümü, her odadaki her sensörle eşleşen <base>/+/leak/state topic'ine abone olur. İlk wet durumunda vanayı kapatır ve kilitlenir (latch): vana, biri OPEN gönderene ve hiçbir sensör hâlâ ıslak bildirmeyene kadar kapalı kalır.

#include <WiFi.h>
#include <PubSubClient.h>
#include <set>
#include <string>

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.connectmq.com";
const char* BASE = "connectmq/demo/w5n8c1/home1";
const char* CLIENT_ID = "valve-main-w5n8c1";

const int RELAY_OPEN = 32;
const int RELAY_CLOSE = 33;
const unsigned long TRAVEL_MS = 8000;   // check your valve's datasheet

WiFiClient net;
PubSubClient mqtt(net);
char tLeakAll[96], tValve[96], tValveSet[96], tAvail[96];
std::set<std::string> wetSensors;
bool closedLatched = false;

void driveValve(bool close) {
  digitalWrite(close ? RELAY_OPEN : RELAY_CLOSE, LOW);
  digitalWrite(close ? RELAY_CLOSE : RELAY_OPEN, HIGH);
  delay(TRAVEL_MS);
  digitalWrite(RELAY_OPEN, LOW);
  digitalWrite(RELAY_CLOSE, LOW);
  mqtt.publish(tValve, close ? "closed" : "open", true);
}

void onMessage(char* topic, byte* payload, unsigned int len) {
  std::string t(topic), p((char*)payload, len);
  if (t == tValveSet) {
    if (p == "CLOSE") { closedLatched = true; driveValve(true); }
    else if (p == "OPEN") {
      if (wetSensors.empty()) { closedLatched = false; driveValve(false); }
      else mqtt.publish(tValve, "closed (sensor still wet)", true);
    }
    return;
  }
  if (p == "wet") {
    wetSensors.insert(t);
    if (!closedLatched) { closedLatched = true; driveValve(true); }
  } else if (p == "dry") {
    wetSensors.erase(t);
  }
}

void connectMqtt() {
  while (!mqtt.connected()) {
    if (mqtt.connect(CLIENT_ID, nullptr, nullptr, tAvail, 1, true, "offline")) {
      mqtt.publish(tAvail, "online", true);
      mqtt.subscribe(tLeakAll, 1);
      mqtt.subscribe(tValveSet, 1);
    } else {
      delay(3000);
    }
  }
}

void setup() {
  pinMode(RELAY_OPEN, OUTPUT);
  pinMode(RELAY_CLOSE, OUTPUT);
  snprintf(tLeakAll, sizeof tLeakAll, "%s/+/leak/state", BASE);
  snprintf(tValve, sizeof tValve, "%s/utility/main-valve/state", BASE);
  snprintf(tValveSet, sizeof tValveSet, "%s/utility/main-valve/state/set", BASE);
  snprintf(tAvail, sizeof tAvail, "%s/utility/main-valve/availability", BASE);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  mqtt.setServer(BROKER, 1883);
  mqtt.setCallback(onMessage);
}

void loop() {
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();
}

Sensör durumları retained olduğundan, vana kontrolcüsü yeniden başlatılırken meydana gelen herhangi bir kaçağı yeniden abone olduğu anda öğrenir. Alarm durumlarını tek seferlik olaylar göndermek yerine retained yapmanın asıl nedeni budur.

Sistemi Test Etmek

Her şeyi izleyin, ardından ıslak bir bezle veya elle yayın yaparak bir kaçağı simüle edin:

B=connectmq/demo/w5n8c1/home1
mosquitto_sub -h broker.connectmq.com -p 1883 -i mon-w5n8c1 -t "$B/#" -v
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-w5n8c1 -r -q 1 -t $B/laundry/leak/state -m wet
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-w5n8c1 -r -q 1 -t $B/laundry/leak/state -m dry
mosquitto_pub -h broker.connectmq.com -p 1883 -i sim-w5n8c1 -q 1 -t $B/utility/main-valve/state/set -m OPEN

Testten sonra simüle edilen retained topic'i boş bir retained mesajla (-r -n) temizleyin. Herkese açık MQTT test broker'ı bu tezgâh aşaması için idealdir, ancak topic'leri herkes tarafından okunabilir; bu yüzden gerçek bir vanayı orayı dinler hâlde bırakmayın.

Hazırlıklı Olunması Gereken Arıza Durumları

  1. Sensörün gücü kesilir. Last will mesajı offline yayınlar. Bunun için de alarm verin; çalışmayan bir sensör hiçbir şeyi korumaz.
  2. Vana kontrolcüsü Wi-Fi'ı kaybeder. Alarmları duyamaz. En kritik sensörü (şofben) kablolu bir yedek olarak doğrudan vana kontrolcüsünün GPIO'suna bağlamayı düşünün.
  3. Vana sıkışır. Hiç hareket etmeyen küresel vanalar tutukluk yapabilir. Vanayı gündüz zamanlanmış bir CLOSE/OPEN ile ayda bir çalıştırın.
  4. Yanlış alarmlar. WET_THRESHOLD değerini raw topic'ini kullanarak kalibre edin ve doğrulama sayısını koruyun.
  5. Şebeke elektriği kesintisi. Küçük bir UPS, modemi ve vana kontrolcüsünü ayakta tutar; pilli sensörler prob üzerinde ext0 uyandırmalı deep sleep kullanabilir.

İnsanların Gerçekten Fark Ettiği Alarm Eskalasyonu

Kimsenin görmediği bir alarm, alarm değildir. Basit bir eskalasyon basamağı iyi çalışır:

  1. Sensör üzerinde, hemen ve hiçbir ağ olmadan çalan yerel buzzer.
  2. Bir wet durumu geldiği anda Home Assistant, Node-RED veya küçük bir Python abonesinden anlık bildirim (push notification).
  3. Vana otomatik olarak kapanır ve kapalı durum ikinci bir bildirim olarak iletilir; böylece beslemenin kesildiğini bilirsiniz.
  4. Herhangi bir sensör ıslakken veya vana kilitliyken on beş dakikada bir tekrarlanan hatırlatmalar.
  5. Bir sensör veya vana kontrolcüsü offline yayınladığında çevrimdışı alarmları, çünkü sessizlik bir sorunu gizleyebilir.

Bildirim mantığını sensörlerin dışında tutun. Cihazlar olguları yayınlar; kime ve ne sıklıkla haber verileceğine aboneler karar verir.

Özel Bir Broker'a Geçiş

Gerçek bir kurulum için portalda bir broker oluşturun, ardından her iki sketch'i de WiFiClientSecure, 8883 portu, ISRG Root X1 CA ve oluşturulan YOUR_USERNAME, YOUR_PASSWORD ve YOUR_CLIENT_ID değerlerine geçirin. Her cihazın kendi client ID'si olmalıdır. ConnectMQ portalında her kaçak topic'ini canlı topic gezgininde izleyebilir ve örneğin ham prob değeri üzerinde eşik tabanlı alarm kuralları oluşturabilirsiniz.

Telefon bildirimleri için Home Assistant aynı wildcard'a abone olabilir; Home Assistant MQTT otomasyonları rehberimiz tetikleyici sözdizimini gösteriyor. Gece tüketiminden gizli kaçakları da fark etmek istiyorsanız bunu bir MQTT üzerinden su sayacı ile eşleştirin. Akıllı ev MQTT topic yapısı rehberi, burada kullanılan /set ve retained durum kurallarını açıklıyor.

Evinizi ConnectMQ ile Koruyun

Bir kaçak sisteminin önemli olduğu anda çevrimiçi olması gerekir; bu da barındırılan bir MQTT broker'ı mantıklı bir temel hâline getirir. ConnectMQ size TLS'i, otomatik oluşturulan kimlik bilgilerini ve alarm kurallarını tek bir portalda sunar. Kredi kartı gerektirmeden app.connectmq.com adresinde ücretsiz bir Serverless broker oluşturun ve sensörlerinizi dakikalar içinde taşıyın. Daha fazla ev projesi IoT otomasyon rehberinde bir araya getirildi.

Sık Sorulan Sorular

Zemin kuruduktan sonra vana neden kapalı kalıyor?

Bu bilinçli bir tercihtir. Bir kaçak genellikle bir şeyin bozulduğu anlamına gelir; bu yüzden vana, bir kişi kontrol edip OPEN gönderene kadar kilitli kalır ve bu da ancak her sensör kuru bildirdiğinde işe yarar.

Kaçak sensörlerini pille çalıştırabilir miyim?

Evet. Periyodik uyandırmalı deep sleep kullanın veya ext0 aracılığıyla prob üzerinden uyandırın ve yalnızca durum değiştiğinde bağlanın. Analog probun suyu algılamak için beslenmesi gerektiğinden devrede ince ayar yapmayı bekleyin.

Kaçak alarmları için neden retained mesajlar kullanmalı?

Retained bir wet durumu, abone olduğu anda her client'a iletilir; böylece bir kaçak sırasında yeniden başlayan bir vana kontrolcüsü veya uygulama bundan hemen haberdar olur.

Prob korozyona uğrar mı?

Elektrotlarda sürekli DC tutmak korozyonu hızlandırır. Sketch'te olduğu gibi probu her örnek için yalnızca birkaç milisaniye beslemek ve paslanmaz çelik elektrotlar kullanmak, uzun süre çalışmasını sağlar.

İlgili yazılar

Zigbee2MQTT Kurulum Rehberi: Koordinatörden Panoya

Zigbee2MQTT'yi Docker ile kurun, koordinatörü ve MQTT bağlantısını yapılandırın, cihazları eşleştirip yeniden adlandırın, onları MQTT üzerinden kontrol edin ve durumlarını bir panoda görüntüleyin; önce ücretsiz herkese açık bir broker'da test edin.

7 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.