ESP32 ve FreeRTOS ile Kesintisiz MQTT Iletisimi

mkcukadar
17 May 2026
95 okuma
ESP32 ve FreeRTOS ile Kesintisiz MQTT Iletisimi

ESP32 ve FreeRTOS ile Kesintisiz MQTT Iletisimi: Asenkron IoT Mimarisi

Nesnelerin Interneti (IoT) projelerinde en sik karsilasilan darbogazlardan biri, mikrodenetleyicinin Wi-Fi baglantisi ve MQTT mesajlarini beklerken ana döngüyü (main loop) bloklamasidir. Özellikle sensör verilerinin (örnegin ortam nemi veya LiDAR ile obje takibi) gerçek zamanli olarak okunup islendigi senaryolarda, delay() fonksiyonlari veya senkron bekleme süreleri tüm sistemin tepki süresini öldürür.

Iste tam bu noktada ESP32'nin çift çekirdekli yapisi ve yerlesik FreeRTOS yetenekleri devreye giriyor. Bu yazida, sensör okuma ve MQTT yayinlama (publish) islemlerini birbirinden izole edilmis görevlere (Task) bölerek nasil asenkron bir mimari kuracagimizi inceleyecegiz.

Neden FreeRTOS Task'lari Kullanmaliyiz?

Standart Arduino loop() döngüsü tek bir thread üzerinde çalisir. Eger MQTT sunucusuna baglanmak 2 saniye sürerse, o 2 saniye boyunca ESP32 baska hiçbir sensörü okuyamaz. FreeRTOS kullanarak:

  • Ag islemlerini Core 0'a,
  • Donanim/Sensör okuma islemlerini Core 1'e atayabiliriz.
  • Bir görev bloklandiginda (örnegin Wi-Fi koptugunda), diger görevler saniyede binlerce kez çalismaya devam eder.

Örnek Uygulama: Asenkron MQTT Publish

Asagidaki kod blogunda, standart loop() fonksiyonunu tamamen bos birakip, MQTT baglantisini ve sensör okuma islemlerini bagimsiz FreeRTOS görevleri olarak tanimladik.


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

// Ag ve MQTT Ayarlari
const char* ssid = "WIFI_SSID";
const char* password = "WIFI_PASSWORD";
const char* mqtt_server = "broker.hivemq.com";

WiFiClient espClient;
PubSubClient client(espClient);

// Sensör Verisi Için Task Handle
TaskHandle_t SensorTask;
TaskHandle_t MqttTask;

void setup() {
  Serial.begin(115200);
  
  // Wi-Fi Baglantisi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  client.setServer(mqtt_server, 1883);

  // Core 1 üzerinde Sensör Okuma Görevi olusturuluyor
  xTaskCreatePinnedToCore(
                    readSensorData,   /* Çalistirilacak Fonksiyon */
                    "SensorTask",     /* Görev Adi (Debug için) */
                    10000,            /* Stack Boyutu (Byte) */
                    NULL,             /* Parametre */
                    1,                /* Öncelik (Priority) */
                    &SensorTask,      /* Task Handle */
                    1);               /* Hangi Çekirdek (Core 1) */

  // Core 0 üzerinde MQTT Görevi olusturuluyor
  xTaskCreatePinnedToCore(
                    handleMqttConnection, 
                    "MqttTask", 
                    10000, 
                    NULL, 
                    2,                /* Ag islemleri önceliklidir */
                    &MqttTask, 
                    0);               /* Hangi Çekirdek (Core 0) */
}

void loop() {
  // FreeRTOS kullanildigi için loop bos birakilir.
  // Geleneksel delay() yerine vTaskDelay kullanilir.
  vTaskDelete(NULL); 
}

// Donanim Okuma Görevi
void readSensorData( void * pvParameters ){
  for(;;){
    // Dummy sensör verisi üretimi (Örn: Nem veya Lidar Mesafesi)
    float dummyHumidity = random(40, 60);
    Serial.printf("Sensör Okundu: %.2f\n", dummyHumidity);
    
    // MQTT üzerinden Publish (Eger baglanti varsa)
    if(client.connected()) {
      char payload[10];
      dtostrf(dummyHumidity, 4, 2, payload);
      client.publish("ta2kmk/sensors/humidity", payload);
    }
    
    // Diger görevlere nefes aldirmak için FreeRTOS gecikmesi
    vTaskDelay(2000 / portTICK_PERIOD_MS);
  }
}

// MQTT Ag Görevi
void handleMqttConnection( void * pvParameters ){
  for(;;){
    if (!client.connected()) {
      Serial.println("MQTT Broker'a baglaniliyor...");
      if (client.connect("ESP32_TA2KMK_Client")) {
        Serial.println("Baglanti Basarili!");
      } else {
        Serial.print("Hata, rc=");
        Serial.println(client.state());
        vTaskDelay(5000 / portTICK_PERIOD_MS); // 5 saniye sonra tekrar dene
      }
    }
    client.loop(); // Gelen mesajlari dinle
    vTaskDelay(10 / portTICK_PERIOD_MS); // Watchdog timer'i rahatlat
  }
}
Dökümantasyon Sonu
Geri Dön