IoT & Gömülü Sistemler

ESP32 ile MQTT Tabanlı IoT Sensör Ağı Kurulumu

Fatih Algül
12.03.2026 13 görüntülenme

MQTT Protokolüne Giriş ve IoT'deki Yeri

Nesnelerin İnterneti (IoT) projelerinde cihazlar arası iletişim, sistemin bel kemiğini oluşturur. Bu iletişimi sağlamak için kullanılan en popüler protokollerden biri MQTT (Message Queuing Telemetry Transport) protokolüdür. MQTT, düşük bant genişliği ve sınırlı kaynaklara sahip cihazlar için özel olarak tasarlanmış, hafif bir yayın-abone (publish-subscribe) mesajlaşma protokolüdür. ESP32 gibi mikrodenetleyicilerle birleştirildiğinde, güçlü ve ölçeklenebilir sensör ağları kurmak son derece kolaylaşır.

Bu yazıda, ESP32 mikrodenetleyicisi kullanarak MQTT tabanlı bir IoT sensör ağı kurmayı adım adım inceleyeceğiz. Sıcaklık ve nem sensöründen veri okuma, bu verileri MQTT broker'a gönderme ve birden fazla düğümü yönetme konularını ele alacağız.

Gerekli Donanım ve Yazılım Bileşenleri

Donanım Listesi

  • ESP32 DevKit v1 (veya benzeri bir ESP32 geliştirme kartı)
  • DHT22 sıcaklık ve nem sensörü (alternatif olarak DHT11 veya BME280)
  • 10kΩ pull-up direnci (DHT22 data hattı için)
  • Breadboard ve jumper kablolar
  • Micro USB kablo (programlama ve güç beslemesi için)

Yazılım Gereksinimleri

  • Arduino IDE (2.x veya üzeri) veya PlatformIO
  • ESP32 board desteği (Arduino Board Manager üzerinden kurulum)
  • PubSubClient kütüphanesi (MQTT istemcisi)
  • DHT sensor library (Adafruit)
  • Mosquitto MQTT broker (sunucu tarafı)

MQTT Broker Kurulumu

Sensör ağımızın merkezi olan MQTT broker'ı kurmakla başlayalım. Mosquitto, açık kaynaklı ve hafif bir MQTT broker'dır. Bir Linux sunucusu, Raspberry Pi veya bulut sunucusu üzerinde çalıştırabilirsiniz.

# Mosquitto kurulumu (Ubuntu/Debian)
sudo apt update
sudo apt install mosquitto mosquitto-clients -y

# Servisi başlat ve otomatik başlatmayı etkinleştir
sudo systemctl start mosquitto
sudo systemctl enable mosquitto

# Durumu kontrol et
sudo systemctl status mosquitto

Güvenlik için Mosquitto yapılandırmasını düzenleyerek kullanıcı adı ve şifre zorunluluğu ekleyelim:

# Şifre dosyası oluştur
sudo mosquitto_passwd -c /etc/mosquitto/passwd iot_kullanici

# Yapılandırma dosyasını düzenle
sudo nano /etc/mosquitto/conf.d/default.conf

Yapılandırma dosyasına aşağıdaki satırları ekleyin:

listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd

Değişikliklerin geçerli olması için servisi yeniden başlatın:

sudo systemctl restart mosquitto

Devre Şeması ve Bağlantılar

DHT22 sensörünü ESP32'ye bağlamak oldukça basittir. Aşağıdaki bağlantı tablosunu takip edin:

  • DHT22 VCC → ESP32 3.3V
  • DHT22 DATA → ESP32 GPIO 4 (10kΩ pull-up direnci ile 3.3V'a bağlanmalı)
  • DHT22 GND → ESP32 GND

Birden fazla sensör düğümü oluşturacaksanız, her bir ESP32 kartı için aynı bağlantıyı tekrarlayın. Her düğüme benzersiz bir isim vererek ağda ayırt edilmelerini sağlayacağız.

ESP32 Firmware Geliştirme

Şimdi ESP32 üzerinde çalışacak olan ana kodu yazalım. Bu kod; Wi-Fi bağlantısı kurma, sensörden veri okuma, MQTT broker'a bağlanma ve verileri belirli aralıklarla yayınlama işlemlerini gerçekleştirir.

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

// Wi-Fi ayarları
const char* ssid = "WIFI_ADINIZ";
const char* password = "WIFI_SIFRENIZ";

// MQTT Broker ayarları
const char* mqtt_server = "192.168.1.100";
const int mqtt_port = 1883;
const char* mqtt_user = "iot_kullanici";
const char* mqtt_password = "iot_sifre";

// Düğüm kimliği - her sensör düğümü için benzersiz olmalı
const char* node_id = "sensor_dugum_01";

// DHT sensör ayarları
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

// MQTT topic tanımlamaları
char topic_sicaklik[50];
char topic_nem[50];
char topic_durum[50];

WiFiClient espClient;
PubSubClient client(espClient);

unsigned long sonOkumaZamani = 0;
const long okumaAraligi = 30000; // 30 saniye

void setup_wifi() {
  Serial.print("Wi-Fi'ye baglaniliyor: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  int deneme = 0;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    deneme++;
    if (deneme > 40) {
      Serial.println("\nWi-Fi baglantisi basarisiz. Yeniden baslatiliyor...");
      ESP.restart();
    }
  }

  Serial.println();
  Serial.print("Baglandi. IP adresi: ");
  Serial.println(WiFi.localIP());
}

void mqtt_callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Mesaj geldi [");
  Serial.print(topic);
  Serial.print("]: ");

  String mesaj = "";
  for (unsigned int i = 0; i < length; i++) {
    mesaj += (char)payload[i];
  }
  Serial.println(mesaj);

  // Gelen komutlara göre işlem yapılabilir
  char topic_komut[50];
  snprintf(topic_komut, sizeof(topic_komut), "iot/%s/komut", node_id);
  if (String(topic) == String(topic_komut)) {
    if (mesaj == "durum") {
      veriGonder();
    }
  }
}

void mqtt_baglan() {
  while (!client.connected()) {
    Serial.print("MQTT broker'a baglaniliyor...");

    char client_id[30];
    snprintf(client_id, sizeof(client_id), "esp32_%s", node_id);

    if (client.connect(client_id, mqtt_user, mqtt_password)) {
      Serial.println(" baglandi!");

      // Durum bilgisi gönder
      snprintf(topic_durum, sizeof(topic_durum), "iot/%s/durum", node_id);
      client.publish(topic_durum, "cevrimici");

      // Komut topic'ine abone ol
      char topic_komut[50];
      snprintf(topic_komut, sizeof(topic_komut), "iot/%s/komut", node_id);
      client.subscribe(topic_komut);
    } else {
      Serial.print(" basarisiz, rc=");
      Serial.print(client.state());
      Serial.println(" 5 saniye sonra tekrar denenecek...");
      delay(5000);
    }
  }
}

void veriGonder() {
  float sicaklik = dht.readTemperature();
  float nem = dht.readHumidity();

  if (isnan(sicaklik) || isnan(nem)) {
    Serial.println("DHT sensorden okuma hatasi!");
    return;
  }

  // JSON formatında veri hazırla
  char json_veri[200];
  snprintf(json_veri, sizeof(json_veri),
    "{\"dugum\":\"%s\",\"sicaklik\":%.1f,\"nem\":%.1f,\"rssi\":%d}",
    node_id, sicaklik, nem, WiFi.RSSI());

  // Topic'lere yayınla
  snprintf(topic_sicaklik, sizeof(topic_sicaklik), "iot/%s/sicaklik", node_id);
  snprintf(topic_nem, sizeof(topic_nem), "iot/%s/nem", node_id);
  char topic_json[50];
  snprintf(topic_json, sizeof(topic_json), "iot/%s/veri", node_id);

  char sicaklik_str[10];
  char nem_str[10];
  dtostrf(sicaklik, 4, 1, sicaklik_str);
  dtostrf(nem, 4, 1, nem_str);

  client.publish(topic_sicaklik, sicaklik_str);
  client.publish(topic_nem, nem_str);
  client.publish(topic_json, json_veri);

  Serial.print("Veri gonderildi - Sicaklik: ");
  Serial.print(sicaklik);
  Serial.print("°C, Nem: ");
  Serial.print(nem);
  Serial.println("%");
}

void setup() {
  Serial.begin(115200);
  dht.begin();

  setup_wifi();

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(mqtt_callback);

  // Topic dizilerini hazırla
  snprintf(topic_sicaklik, sizeof(topic_sicaklik), "iot/%s/sicaklik", node_id);
  snprintf(topic_nem, sizeof(topic_nem), "iot/%s/nem", node_id);
  snprintf(topic_durum, sizeof(topic_durum), "iot/%s/durum", node_id);
}

void loop() {
  if (!client.connected()) {
    mqtt_baglan();
  }
  client.loop();

  unsigned long simdikiZaman = millis();
  if (simdikiZaman - sonOkumaZamani >= okumaAraligi) {
    sonOkumaZamani = simdikiZaman;
    veriGonder();
  }
}

Topic Yapısı ve Tasarım Prensipleri

MQTT'de topic yapısı, sisteminizin düzeni ve ölçeklenebilirliği açısından kritik öneme sahiptir. Projemizde aşağıdaki hiyerarşik yapıyı kullanıyoruz:

  • iot/{dugum_id}/sicaklik — Ham sıcaklık değeri
  • iot/{dugum_id}/nem — Ham nem değeri
  • iot/{dugum_id}/veri — JSON formatında tüm veriler
  • iot/{dugum_id}/durum — Düğüm çevrimiçi/çevrimdışı durumu
  • iot/{dugum_id}/komut — Düğüme gönderilen komutlar

Bu yapı sayesinde, iot/+/sicaklik şeklinde bir wildcard aboneliği ile tüm düğümlerin sıcaklık verilerini tek seferde dinleyebilirsiniz. Benzer şekilde iot/sensor_dugum_01/# ile belirli bir düğümün tüm topic'lerine abone olabilirsiniz.

Broker Üzerinden Test ve Doğrulama

Sistemi test etmek için Mosquitto istemci araçlarını kullanabilirsiniz. Bir terminal penceresinde abone olarak verileri dinleyin, diğerinde komut gönderin:

# Tüm sensör verilerini dinle
mosquitto_sub -h localhost -u iot_kullanici -P iot_sifre -t "iot/#" -v

# Belirli bir düğümün verilerini dinle
mosquitto_sub -h localhost -u iot_kullanici -P iot_sifre -t "iot/sensor_dugum_01/veri"

# Bir düğüme komut gönder
mosquitto_pub -h localhost -u iot_kullanici -P iot_sifre -t "iot/sensor_dugum_01/komut" -m "durum"

Birden Fazla Düğüm ile Ağı Genişletme

Sensör ağını genişletmek için her yeni ESP32 kartında yalnızca node_id değerini değiştirmeniz yeterlidir. Örneğin:

  • Oturma odası: node_id = "salon_01"
  • Yatak odası: node_id = "yatak_odasi_01"
  • Sera: node_id = "sera_01"
  • Dış mekan: node_id = "dis_mekan_01"

Her düğüm bağımsız olarak çalışır, kendi topic'lerine veri yayınlar ve merkezi broker üzerinden koordine edilir. Bu mimari, onlarca hatta yüzlerce düğüme kadar rahatlıkla ölçeklenebilir.

Derin Uyku ile Enerji Optimizasyonu

Pil ile çalışan sensör düğümleri için ESP32'nin derin uyku (deep sleep) özelliğini kullanmak büyük avantaj sağlar. Aşağıdaki değişikliklerle düğümünüzün enerji tüketimini drastik şekilde azaltabilirsiniz:

#define uS_TO_S_FACTOR 1000000ULL
#define UYKU_SURESI 300  // 5 dakika (saniye cinsinden)

void setup() {
  Serial.begin(115200);
  dht.begin();

  setup_wifi();

  client.setServer(mqtt_server, mqtt_port);
  mqtt_baglan();
  veriGonder();

  // Bağlantıyı düzgün kapat
  client.disconnect();
  WiFi.disconnect(true);

  // Derin uykuya geç
  esp_sleep_enable_timer_wakeup(UYKU_SURESI * uS_TO_S_FACTOR);
  Serial.println("Derin uykuya geciliyor...");
  esp_deep_sleep_start();
}

void loop() {
  // Derin uyku modunda loop() çalışmaz
}

Bu yapılandırmayla ESP32, yalnızca veri gönderme anlarında aktif olur ve geri kalan sürede mikro amperler düzeyinde akım çeker. Tipik bir 18650 Li-ion pil ile aylarca çalışma süresi elde edebilirsiniz.

Veri Görselleştirme ve İzleme

Toplanan verileri anlamlı hale getirmek için popüler araçları entegre edebilirsiniz:

  • Node-RED: MQTT topic'lerine abone olarak verileri akış tabanlı bir şekilde işleyin. Eşik değeri aşıldığında e-posta veya Telegram bildirimi gönderin.
  • InfluxDB + Grafana: Zaman serisi veritabanına verileri kaydedin ve Grafana ile zengin panolar oluşturun. Geçmişe dönük analiz ve trend takibi için idealdir.
  • Home Assistant: MQTT entegrasyonu ile sensör verilerini akıllı ev sisteminize dahil edin. Otomasyon kuralları oluşturun.

Güvenlik Önerileri

Üretim ortamında bir IoT sensör ağı çalıştırırken dikkat edilmesi gereken güvenlik hususları vardır:

  1. TLS/SSL şifreleme: MQTT bağlantılarını 8883 portu üzerinden TLS ile şifreleyin. WiFiClientSecure sınıfını kullanarak ESP32 tarafında sertifika doğrulaması yapın.
  2. Güçlü kimlik doğrulama: Her düğüm için ayrı kullanıcı adı ve şifre tanımlayın. Mümkünse istemci sertifikası tabanlı kimlik doğrulama kullanın.
  3. ACL (Erişim Kontrol Listesi): Her düğümün yalnızca kendi topic'lerine yazabilmesini ve yalnızca kendi komut topic'ine abone olabilmesini sağlayın.
  4. Firmware güncellemeleri: OTA (Over-The-Air) güncelleme mekanizması kurarak güvenlik yamalarını uzaktan dağıtın.
  5. Ağ segmentasyonu: IoT cihazlarını ayrı bir VLAN'da izole edin.

Sorun Giderme ve Yaygın Hatalar

Sensör ağı kurarken karşılaşabileceğiniz yaygın sorunlar ve çözümleri:

  • Wi-Fi bağlantı kopmaları: ESP32'nin Wi-Fi anteninin metalik yüzeylerden uzak olduğundan emin olun. Kodda otomatik yeniden bağlanma mekanizması bulunduğundan, kısa süreli kopmalar otomatik olarak ele alınır.
  • DHT sensör okuma hataları: Pull-up direncinin doğru bağlandığını kontrol edin. Okumalar arası minimum 2 saniye bekleyin; DHT22 sensörü bu aralıktan daha sık okunamaz.
  • MQTT bağlantı reddi: Broker'ın çalıştığını (systemctl status mosquitto), port numarasının doğru olduğunu ve güvenlik duvarı kurallarının 1883 portuna izin verdiğini kontrol edin.
  • Bellek taşması: Uzun süre çalışan düğümlerde ESP.getFreeHeap() ile boş belleği izleyin. Bellek sızıntısı tespit ederseniz String nesneleri yerine karakter dizileri (char array) kullanmayı tercih edin.

Sonuç

ESP32 ve MQTT kombinasyonu, düşük maliyetli ancak güçlü IoT sensör ağları kurmak için mükemmel bir platform sunar. Bu yazıda ele aldığımız mimari, birkaç düğümden oluşan basit bir ev otomasyonundan yüzlerce düğümü kapsayan endüstriyel izleme sistemlerine kadar ölçeklenebilir. MQTT'nin yayın-abone modeli, düğümlerin birbirinden bağımsız çalışmasını sağlarken merkezi bir broker üzerinden veri akışını kolayca yönetmenize olanak tanır. Enerji optimizasyonu, güvenlik önlemleri ve uygun topic tasarımı ile üretim kalitesinde bir IoT altyapısı oluşturabilirsiniz.

Yazar Hakkında
Fatih Algül
TechSoft Solutions
Proje mi var?

Yazılım, IoT veya otomasyon konularında destek almak ister misiniz?

İletişime Geç