ESP32 ve Arduino

ESP32 Deep Sleep MQTT: Yayınlayıp Uyuyan Pille Çalışan Sensörler

Zamanlayıcıyla uyanan, hızla bağlanan, retained bir ölçüm yayınlayan, mesajın broker'a ulaştığını doğrulayan ve yeniden deep sleep'e geçen pil dostu bir ESP32 sensörü yapın.

esp32 deep sleep mqtt döngüsünde yayın yapmak için uyanan pille çalışan ESP32 sensör düğümü
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

ESP32 deep sleep MQTT, pille çalışan bir sensörden günler yerine aylar boyunca verim almanın yoludur. Bu eğitimde zamanlayıcıyla uyanan, Wi-Fi'a olabildiğince hızlı yeniden bağlanan, broker.connectmq.com'a retained bir ölçüm yayınlayan, mesajın gerçekten broker'a ulaştığını doğrulayan ve yeniden uykuya geçen bir düğüm yapacaksınız. Ölçüm retained olduğu için cihaz neredeyse her zaman çevrimdışı olsa bile dashboard'lar her zaman son değeri gösterir.

Uyan, Yayınla, Uyu Döngüsü

Deep sleep'te ESP32 CPU'larını, RAM'in büyük kısmını ve radyoyu kapatır. Yalnızca RTC alanı açık kalır ve aktif akımın çok küçük bir kısmını tüketir. Zamanlayıcı tetiklendiğinde çip kaldığı yerden devam etmez: yeniden başlar ve setup()'ı en baştan çalıştırır. Bu tasarımda loop() hiç çalışmaz.

Her uyanma döngüsü aynı adımları izler:

  1. Açılın ve radyo kartı ısıtmadan önce sensörü hemen okuyun.

  2. Önceki döngüden kaydedilen kanalı ve erişim noktasını yeniden kullanarak Wi-Fi'a bağlanın.

  3. MQTT broker'a bağlanın ve ölçümü retained mesaj olarak yayınlayın.

  4. Broker'ın mesajı aldığını doğrulayın.

  5. Bağlantıyı düzgünce kesin, radyoyu kapatın ve deep sleep'e geçin.

  6. ve 5. adımlar arasında geçen süre enerji tüketimine hâkimdir; çünkü en fazla akımı açık ara Wi-Fi radyosu çeker. Bu makaledeki her optimizasyon bu pencereyi kısaltmayı ya da zaten başarısız olacaksa tamamen atlamayı hedefler.

Aşama Göreli güç Nasıl kısaltılır
Açılış ve sensör okuma Düşük ila orta Önce sensörü okuyun, kodu küçük tutun
Wi-Fi ilişkilendirme ve DHCP Yüksek Kanalı ve BSSID'yi yeniden kullanın, isteğe bağlı statik IP
MQTT bağlantısı ve yayın Yüksek Düz veya hafif oturumlu bağlantı, tek yayın
Doğrulama beklemesi Yüksek Kısa zaman aşımı, çabuk vazgeçin
Deep sleep Çok düşük Kart tasarımı: regülatör, LED'ler, USB çipi

Son satır sık karşılaşılan bir sürprizdir: birçok geliştirme kartı voltaj regülatöründe, güç LED'inde ve USB-seri çipinde, ESP32'nin deep sleep'te harcadığından çok daha fazlasını boşa harcar. Gerçek pil ömrü için çipi değil kartı ölçün. Pille çalışan ESP32 sensörleri hakkındaki tamamlayıcı makale donanım seçimlerini ve akım ölçümlerini daha ayrıntılı ele alır.

Retained Mesajlar Burada Neden Vazgeçilmez?

Uyuyan bir sensör bir kez yayınlar ve kaybolur. Bir dashboard veya telefon uygulaması bir dakika sonra abone olursa normal bir mesaj çoktan gitmiştir. Retain bayrağı ayarlandığında broker o topic'teki son mesajı saklar ve her yeni aboneye anında iletir. Dashboard, cihazın en son ne zaman uyandığından bağımsız olarak açıldığı anda en güncel ölçümü gösterir.

Tüketicilerin retained değerin ne kadar eski olduğunu anlayabilmesi için payload'a bir zaman damgası veya sıra numarası koyun. Dört saat önceki bir ölçümün güncel görünmesi yanıltıcıdır ve uyuyan bir cihaz için "eski" olmak normal durumdur. Retained mesajlar size yabancıysa, bir MQTT broker'ın ne yaptığına dair genel bakış broker'ın bunları nasıl sakladığını açıklar.

QoS 1 Yayını Olmadan Teslimatı Doğrulamak

PubSubClient yalnızca QoS 0 ile yayın yapabilir; bu "alındı" değil "gönderildi" anlamına gelir. Sürekli açık bir cihazda bu genellikle kabul edilebilir. Uykulu bir cihazda ise gerçek bir sorundur: publish()'ten hemen sonra esp_deep_sleep_start() çağırırsanız, paket hâlâ bir tampondayken radyo kapanabilir ve mesaj sessizce kaybolur.

Aşağıdaki sketch basit ve güvenilir bir hile kullanır. Yayınlamadan önce kendi durum topic'ine abone olur, ardından broker yeni mesajı geri gönderene kadar bekler. Kendi mesajınızın geri yansıdığını görmek, broker'ın onu aldığını ve yönlendirdiğini kanıtlar. RTC belleğinde saklanan bir sıra numarası, taze mesajı broker'ın abonelik sırasında yine ilettiği eski retained mesajdan ayırt eder.

Tam ESP32 Deep Sleep MQTT Sketch'i

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

const char* WIFI_SSID     = "YOUR_WIFI";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST     = "broker.connectmq.com";
const uint16_t MQTT_PORT  = 1883;
const char* CLIENT_ID     = "sleepy-3e7f10";                 // unique
const char* TOPIC_STATE   = "connectmq/demo/sleepy-3e7f10/state";

const uint64_t SLEEP_SECONDS   = 300;                       // 5 minutes
const uint32_t WIFI_TIMEOUT_MS = 8000;
const uint32_t ACK_TIMEOUT_MS  = 3000;

// Survives deep sleep (lost on power-off or reset)
RTC_DATA_ATTR uint32_t seq = 0;
RTC_DATA_ATTR uint32_t failures = 0;
RTC_DATA_ATTR uint8_t savedBssid[6];
RTC_DATA_ATTR int32_t savedChannel = 0;
RTC_DATA_ATTR bool haveSaved = false;

WiFiClient net;
PubSubClient mqtt(net);
volatile bool acked = false;
char expected[24];

void goToSleep() {
  mqtt.disconnect();
  net.stop();
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  // Back off when things keep failing, so a dead network does not drain the battery
  uint64_t seconds = SLEEP_SECONDS * (failures > 3 ? 4 : 1);
  Serial.printf("Sleeping %llu s (failures=%lu)\n", seconds, (unsigned long)failures);
  Serial.flush();
  esp_sleep_enable_timer_wakeup(seconds * 1000000ULL);
  esp_deep_sleep_start();
}

float readSensor() {
  // Replace with your sensor; simulated value keeps the example self-contained
  return 20.0 + (esp_random() % 500) / 100.0;
}

void onMessage(char* topic, byte* payload, unsigned int length) {
  // Our payload contains "seq":N; look for the one we just sent
  String msg;
  for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
  if (msg.indexOf(expected) >= 0) acked = true;
}

bool connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.persistent(false);
  if (haveSaved) {
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD, savedChannel, savedBssid, true);   // fast path
  } else {
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  }
  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED) {
    if (millis() - start > WIFI_TIMEOUT_MS) {
      haveSaved = false;              // AP may have changed channel: full scan next time
      return false;
    }
    delay(20);
  }
  memcpy(savedBssid, WiFi.BSSID(), 6);
  savedChannel = WiFi.channel();
  haveSaved = true;
  return true;
}

void setup() {
  unsigned long t0 = millis();
  Serial.begin(115200);
  float temperature = readSensor();                 // read before the radio warms the board
  seq++;

  if (!connectWifi()) { failures++; goToSleep(); }

  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setCallback(onMessage);
  mqtt.setSocketTimeout(4);
  if (!mqtt.connect(CLIENT_ID)) { failures++; goToSleep(); }

  mqtt.subscribe(TOPIC_STATE, 0);
  snprintf(expected, sizeof(expected), "\"seq\":%lu,", (unsigned long)seq);

  char payload[128];
  snprintf(payload, sizeof(payload),
           "{\"seq\":%lu,\"temperature\":%.2f,\"rssi\":%d,\"awakeMs\":%lu,\"failures\":%lu}",
           (unsigned long)seq, temperature, WiFi.RSSI(),
           millis() - t0, (unsigned long)failures);
  mqtt.publish(TOPIC_STATE, payload, true);         // retained

  unsigned long start = millis();
  while (!acked && millis() - start < ACK_TIMEOUT_MS) {
    mqtt.loop();
    delay(5);
  }
  if (acked) failures = 0; else failures++;
  Serial.printf("seq=%lu acked=%d awake=%lu ms\n", (unsigned long)seq, acked, millis() - t0);
  goToSleep();
}

void loop() {
  // Never reached: the ESP32 restarts in setup() after every wake-up
}

Her optimizasyon ne işe yarar?

Kanal ve BSSID önbellekleme. Normal bir WiFi.begin() erişim noktasını bulmak için tüm kanalları tarar. RTC belleğinde saklanan kanalı ve BSSID'yi vermek bu taramayı atlar; bu da genellikle en büyük tek tasarruftur. Router kanal değiştirirse hızlı yol zaman aşımına uğrar, önbellek temizlenir ve bir sonraki uyanmada tam tarama yapılır.

Önce sensörü okumak. Radyo kartı belirgin şekilde ısıtır ve bu da sıcaklık ölçümlerini saptırır. Bağlanmadan önce ölçüm almak bunu önler.

Hata durumunda backoff. Ağ kapalıyken her uyanma, başarılı olamayacak denemelere enerji harcar. Tekrarlanan hatalardan sonra düğüm, bir yayın yeniden başarılı olana kadar dört kat daha uzun uyur.

Payload'da awakeMs. Cihazın önceki aşamada ne kadar uyanık kaldığını raporlamak, enerji maliyetine dair ücretsiz ve sürekli bir görünüm sağlar. Bu değer yavaş yavaş artıyorsa ağda bir şey değişmiştir.

Last Will yok. Uyuyan bir cihaz her döngüde bilerek bağlantıyı keser; bu yüzden offline bir Last Will anlamsız olur. Bunun yerine canlılığı son retained ölçümün yaşına göre değerlendirin.

İsteğe bağlı olarak statik IP, DHCP alışverişinden de tasarruf sağlar. WiFi.begin()'den önce WiFi.config(ip, gateway, subnet, dns) çağırın; ancak bunu yalnızca adres atamasını kontrol ettiğiniz ağlarda yapın.

Çalıştığını Doğrulayın

Bilgisayarınızdan abone olun:

mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-3e7f10 -v -t "connectmq/demo/sleepy-3e7f10/#"

Test için SLEEP_SECONDS değerini 20'ye düşürün. Her döngüde bir mesaj görmelisiniz:

connectmq/demo/sleepy-3e7f10/state {"seq":7,"temperature":22.81,"rssi":-61,"awakeMs":1180,"failures":0}

Şimdi ESP32 uyurken aboneyi durdurup yeniden başlatın. Son ölçüm anında görünür; bir dashboard'un yaşadığı da tam olarak budur. Ardından router'ınızı birkaç döngü boyunca kapatın: seri monitör artan failures değerini gösterir ve toparlanmadan sonraki ilk mesaj kaç döngünün kaçırıldığını bildirir.

broker.connectmq.com'daki public alan, bu tür testlere uygun ücretsiz bir public MQTT broker'dır. Buradaki oturumlar en fazla 30 dakika sonra sona erer; sketch her uyanmada yeni bir oturumla bağlandığı için bu burada önemli değildir. Özel bir ConnectMQ broker'a geçtiğinizde sketch'in yalnızca kimlik bilgilerine (ve tercih ederseniz TLS'e) ihtiyacı olur; dikkat edilmesi gereken tek şey ücretsiz plandaki 25 bağlantı sınırıdır. Her sensör döngü başına yalnızca bir anlığına bağlı kaldığından uykulu sensörlerden oluşan bir filo bu sınıra nadiren ulaşır.

Pil Ömrü Kontrol Listesi

  1. Güç LED'ini sökün veya devre dışı bırakın ve düşük boşta akımlı regülatöre sahip bir kart kullanın ya da modülü doğrudan besleyin.
  2. Deep sleep akımını seri bağlı bir ölçü aletiyle ölçün; iyi tasarlanmış bir kartta bir miliamperin çok altında olmalıdır.
  3. Uyanık kalma penceresini kısa tutun: önbelleğe alınmış Wi-Fi, kısa zaman aşımları, tek yayın.
  4. Mantıklı bir aralık seçin. Aralığı yarıya indirmek radyonun açık kaldığı enerjiyi kabaca ikiye katlar; çoğu çevresel ölçüm dakika düzeyinde çözünürlük gerektirmez.
  5. Sensörü bir GPIO'dan besleyin ve uyumadan önce kapatın; böylece sensör arka planda pili tüketmez.
  6. Pil ömrü kritikse ve tehdit modeli özel bir ağda buna izin veriyorsa her uyanmada TLS kullanmaktan kaçının; şifrelemeye ihtiyacınız olduğunda ek el sıkışma süresini hesaba katın ve WiFiClientSecure ile ESP32 MQTT SSL rehberini izleyin.

Sorun Giderme

  • Mesajlar yalnızca bazen geliyor. Yayın radyodan çıkmadan uykuya geçiyorsunuz. Yansıma doğrulamasını koruyun ve ACK_TIMEOUT_MS değerini fazla kısaltmayın.
  • seq beklenmedik şekilde 1'e sıfırlanıyor. RTC belleği deep sleep'i atlatır ama elektrik kesintisini, brownout'u veya reset butonuna basılmasını atlatmaz. Düşen pil voltajının neden olduğu brownout'lar yaygın bir sebeptir.
  • Cihaz hiç uyanmıyor. esp_sleep_enable_timer_wakeup()'ı mikrosaniye cinsinden ve 64 bitlik bir değerle çağırdığınızı kontrol edin; 32 bitlik taşma çok daha kısa veya yanlış bir aralık üretir.
  • Seri çıktı yarıda kesiliyor. Sketch'te olduğu gibi uyumadan önce Serial.flush() çağırın.
  • Bazı döngülerde uyanık kalma süresi uzun. Hızlı Wi-Fi yolu başarısız oldu ve tam tarama çalıştı. Router'ınızın sabit bir kanal kullandığını kontrol edin.

Uykulu Sensörleri Üretimde Çalıştırmak

Retained değerler ancak onları tutan broker kadar güvenilirdir. Yönetilen bir MQTT broker, sensörleriniz uyurken bu uç noktayı erişilebilir tutar ve aynı retained topic'ler dashboard'larınıza, betiklerinize ve uygulamalarınıza hizmet eder. ConnectMQ ile portalda cihaz başına kimlik bilgileri oluşturur, her sensörün son retained değerini canlı topic gezgininde görür ve sıcaklık gibi ölçümler için eşik uyarı kuralları belirlersiniz. Bir bulut MQTT broker aynı zamanda tarladaki, mahzendeki ve depodaki sensörlerin hiçbir yerel sunucu olmadan tek bir uç noktaya raporlama yapabilmesi demektir. Karta yeni mi başladınız? ESP32 IoT eğitimi ile başlayın.

ConnectMQ ile Başlayın

app.connectmq.com adresinde kredi kartı olmadan ücretsiz bir Serverless broker oluşturun. Uykulu sensörlerinizi kendi kimlik bilgileriyle ona yönlendirin ve uyandıkça retained ölçümlerin portalda belirmesini izleyin.

Sık Sorulan Sorular

ESP32'm deep sleep'ten önce neden MQTT mesajlarını kaybediyor?

QoS 0 yayını veri kuyruğa alınır alınmaz geri döner; bu yüzden hemen uyumak mesajı yarıda kesebilir. Bu sketch'teki yansıma tekniği gibi bir doğrulama bekleyin, ardından bağlantıyı kesip uyuyun.

Deep sleep sensörü bir MQTT oturumunu korumalı mı?

Genellikle hayır. Her uyanmada yeni bir bağlantı daha basittir ve her broker ile çalışır. Kalıcı oturumlar yalnızca cihazın uyurken kuyruğa alınan komutları alması gerekiyorsa işe yarar.

Uyuyan bir ESP32 komutları nasıl alabilir?

Komutları, cihazın uyandığında abone olduğu bir topic'e retained mesaj olarak yayınlayın. Cihaz en son komutu hemen alır, uygular, ardından boş bir retained mesaj yayınlayarak temizler.

Pilli bir sensör için iyi bir yayın aralığı nedir?

Ölçülen değerin ne kadar hızlı değiştiğine bağlıdır. Çevresel sensörler genellikle beş ila on beş dakikalık aralıklarla iyi çalışır; daha kısa aralıklar orantılı olarak daha fazla enerji harcar.

İlgili yazılar

ESP32 NTP MQTT Zaman Damgası: Her Mesaja Doğru Zaman Ekleyin

ESP32 saatini NTP ile eşitleyin, ISO 8601 ve epoch milisaniye zaman damgalarını biçimlendirin ve bunları MQTT payload'larına ekleyin; böylece ölçümler geç yayınlansa bile gerçek alınma zamanlarını korur.

6 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.