Watchdog + Otomatik Yeniden Bağlanma ile Endüstriyel Güvenilirlik
Proje Amacı
ESP-IDF'in görev bazlı donanımsal Task Watchdog Timer'ını (TWDT) kullanarak, ana döngü belirli bir süre 'nefes almazsa' (donarsa) cihazı otomatik olarak yeniden başlatmayı; ayrıca WiFi bağlantısı koptuğunda üstel geri çekilmeyle (exponential backoff) otomatik yeniden bağlanmayı öğretir — insansız çalışan sahadaki bir cihazın kendi kendini toparlaması için endüstriyel projelerde standart kabul edilen bir güvenilirlik desenidir. ESP32'nin FreeRTOS çekirdeği, her görevi (task) ayrı ayrı izleyebilen donanım destekli bir watchdog mekanizması sunar. Bu düzeyde bir izleme Arduino Uno'da kurulamaz: Uno'nun donanımsal watchdog'u (WDT) çok daha kaba bir genel zamanlayıcıdır, görev/task kavramı yoktur (bir RTOS çalıştıramaz) ve zaten yeniden bağlanacak bir WiFi bağlantısı da bulunmaz.
Gerekli Malzemeler
- ESP32 DevKit V1 (38 pin)
- Durum LED'i
- 220Ω direnç
- Pasif buzzer
- Breadboard
- Jumper kablolar
Gerekli Kütüphaneler
esp_task_wdt.h, WiFi.h (ikisi de ESP32 core ile gelir, ek kurulum gerekmez).
Pin Bağlantıları
| Bileşen Pini | Bağlantı |
|---|---|
| Durum LED anot (220Ω) | GPIO4 |
| LED katot | GND |
| Buzzer + | GPIO17 |
| Buzzer - | GND |
Devre Şeması
ESP32 Kodu
| 1 | #include <WiFi.h> |
| 2 | #include <esp_task_wdt.h> |
| 3 | |
| 4 | const int LED = 4; |
| 5 | const int BUZZER = 17; |
| 6 | const char* ssid = "WIFI_ADINIZ"; |
| 7 | const char* password = "WIFI_SIFRENIZ"; |
| 8 | |
| 9 | #define WDT_SURESI_SN 10 // 10 saniye içinde besleme gelmezse yeniden başlat |
| 10 | |
| 11 | unsigned long sonBaglantiDenemesi = 0; |
| 12 | int denemeSayaci = 0; |
| 13 | |
| 14 | void wifiBaglan() { |
| 15 | Serial.println("WiFi'ye bağlanılıyor..."); |
| 16 | WiFi.begin(ssid, password); |
| 17 | } |
| 18 | |
| 19 | void setup() { |
| 20 | Serial.begin(115200); |
| 21 | pinMode(LED, OUTPUT); |
| 22 | pinMode(BUZZER, OUTPUT); |
| 23 | |
| 24 | // NOT: esp_task_wdt_init(saniye, panik) imzası arduino-esp32 core 2.x |
| 25 | // içindir. Core >= 3.0 (IDF5 tabanlı) bir esp_task_wdt_config_t struct'ı |
| 26 | // bekler ve bu iki parametreli çağrıyla DERLENMEZ — Boards Manager'da |
| 27 | // "esp32" paketiniz 3.x ise Espressif'in güncel esp_task_wdt.h örneğine |
| 28 | // bakıp config struct'ına geçin. |
| 29 | esp_task_wdt_init(WDT_SURESI_SN, true); // true = zaman aşımında panik/reset |
| 30 | esp_task_wdt_add(NULL); // mevcut görevi (loopTask) izlemeye al |
| 31 | |
| 32 | wifiBaglan(); |
| 33 | } |
| 34 | |
| 35 | void loop() { |
| 36 | esp_task_wdt_reset(); // watchdog'u besle — bu satır çağrılmazsa 10sn sonra reset |
| 37 | |
| 38 | if (WiFi.status() != WL_CONNECTED) { |
| 39 | digitalWrite(LED, LOW); |
| 40 | unsigned long simdi = millis(); |
| 41 | unsigned long bekleme = min(30000UL, (unsigned long)(1000UL << min(denemeSayaci, 5))); // üstel geri çekilme, max 30sn |
| 42 | if (simdi - sonBaglantiDenemesi > bekleme) { |
| 43 | sonBaglantiDenemesi = simdi; |
| 44 | denemeSayaci++; |
| 45 | Serial.printf("Yeniden bağlanma denemesi #%d (%.0f sn sonra tekrar)\n", denemeSayaci, bekleme / 1000.0); |
| 46 | tone(BUZZER, 1500, 100); // kısa uyarı sesi |
| 47 | WiFi.disconnect(); |
| 48 | wifiBaglan(); |
| 49 | } |
| 50 | } else { |
| 51 | digitalWrite(LED, HIGH); |
| 52 | denemeSayaci = 0; // bağlantı sağlandı, sayaç sıfırlanır |
| 53 | } |
| 54 | |
| 55 | delay(500); // WDT süresinin (10sn) çok altında, güvenli marj |
| 56 | } |
Çalışma Açıklaması
esp_task_wdt_reset() çağrılmadan geçen süre WDT_SURESI_SN değerini aşarsa ESP-IDF bir panik mesajı basıp cihazı otomatik olarak yeniden başlatır — bu istenen bir davranıştır çünkü aksi halde donan bir cihaz insan müdahalesi olmadan asla kendini toparlayamaz. Üstel geri çekilme (exponential backoff) stratejisi, hatalı veya geçici olarak erişilemeyen bir ağa saniyede onlarca bağlanma denemesi yaparak hem router'ı hem enerjiyi boşa harcamayı önler; bu, pil ile çalışan cihazlarda özellikle önemlidir.
Test Bilgisi
Kodu yükleyip Seri Monitör'de (115200 baud) bağlantı loglarını izleyin. Router'ı geçici olarak kapatıp açarak bağlantı kopmasını simüle edin; LED sönmeli, buzzer kısa bip vermeli ve artan bekleme süreleriyle (1sn, 2sn, 4sn... en fazla 30sn) yeniden bağlanmayı denemeli. Watchdog'u gerçekten test etmek için loop() içine bilinçli bir 'while(true);' sonsuz döngüsü ekleyip cihazın 10 saniye sonra otomatik olarak resetlendiğini doğrulayın (testten sonra bu satırı mutlaka kaldırın, aksi halde cihaz sürekli açılış-kapanış döngüsüne girer).
Olası Sorunlar ve Çözümleri
'esp_task_wdt_init' çağrısı derlenmiyorsa (parametre sayısı/tipi uyuşmazlığı hatası): Boards Manager'daki 'esp32' paketiniz 3.x sürümündedir, bu core'da fonksiyon iki parametre yerine bir esp_task_wdt_config_t struct'ı alır — ya paketi 2.0.x'e düşürün ya da güncel imzaya uyarlayın. Cihaz sürekli beklenmedik şekilde resetleniyorsa (brown-out): WiFi bağlantı anındaki ani akım çekişi USB gücünün yetersiz kalmasına neden olabilir, harici 5V/1A (veya daha güçlü) bir adaptör deneyin ve Seri Monitör'de 'Brownout detector was triggered' mesajının görünüp görünmediğini kontrol edin. Watchdog hiç tetiklenmiyorsa: esp_task_wdt_add(NULL) çağrısının setup() içinde, mevcut görev (loopTask) bağlamında yapıldığından emin olun. Sürekli 'reconnecting' döngüsüne giriyorsa: SSID/şifrenin doğru girildiğinden ve ağın 2.4GHz olduğundan emin olun, ayrıca router'ın MAC filtreleme gibi bir kısıtlama uygulamadığını kontrol edin.
Alternatif Çözümler
Tek görev yerine xTaskCreate ile ayrı bir 'sensör' görevi de watchdog'a eklenip (esp_task_wdt_add) her ikisi bağımsız olarak izlenebilir, böylece hangi görevin donduğu ayrı ayrı tespit edilebilir. Kalıcı bir hata sayacı RTC memory'de (deep sleep'e dayanıklı, bkz. proje #07) tutularak 'art arda N kez reset olursa fabrika ayarlarına dön' gibi kendi kendini onaran bir mantık eklenebilir. Yerel buzzer/LED bildirimine ek olarak bir MQTT 'last will' mesajıyla, cihaz beklenmedik şekilde koparsa uzak bir sunucuya/dashboard'a otomatik bildirim gönderilebilir.
Benzer Projeler
OTA Kablosuz Firmware Güncelleme Sistemi
ESP32'nin dahili çift OTA (Over-The-Air) flash partisyon şemasını kullanarak, sahaya kurulmuş bir cihaza tekrar USB kablosu takmadan tamamen kablosuz şekilde yeni firmware yüklemeyi öğretir — özellikle tavana, duvara veya erişimi zor bir noktaya monte edilmiş onlarca cihazı yönetirken zaman ve emek kazandıran pratik bir yetenektir. ESP32'nin flash belleği kalkınma sırasında bir 'factory' bölümü ile iki ayrı OTA partisyonuna bölünebilir; cihaz yeni kodu ağdan indirip o an boş olan partisyona yazar, bütünlük kontrolünden geçerse oradan açılış yapar ve önceki çalışan sürüm otomatik olarak yedek konumunda kalır, böylece yarım kalan veya bozuk bir güncelleme cihazı kullanılamaz hale getirmez. Bu iki katmanlı flash mimarisi ESP32'ye özgüdür: Arduino Uno'nun ATmega328P'sinde toplam flash belleği zaten 32KB'dir ve sketch kodunun kendisi bu alanın büyük bölümünü kapladığından ikinci bir tam firmware kopyasına yer kalmaz; kartta WiFi donanımı da bulunmadığından ağ üzerinden güncelleme almak zaten söz konusu değildir.
SPIFFS/LittleFS ile Dahili Dosya Sisteminden Web Üzerinden Medya Streaming
ESP32'nin 4MB'lık dahili flash belleğinin bir kısmını LittleFS dosya sistemi olarak bölümleyip, içine yüklenen bir ses veya görüntü dosyasını WiFi üzerinden HTTP ile parça parça (chunked) akış olarak tarayıcıya sunmayı öğretir — harici bir SD kart olmadan, cihazın kendi hafızasından medya sunumu yapılabilmesini sağlar. ESP32'nin yeterli dahili flash'ı LittleFS gibi gerçek bir dosya sistemi partisyonuna ayırabilir ve WiFi ile bu dosyaları HTTP response olarak akıtabilecek bir ağ yığınına sahiptir. Bu senaryo Arduino Uno'da kurulamaz: toplam 32KB flash zaten sketch koduna gittiğinden bir medya dosyası bir yana, birkaç kilobaytlık bir metin dosyası için bile dosya sistemi partisyonu ayıracak yer kalmaz; WiFi de bulunmadığından zaten akıtacak bir ağ arayüzü de yoktur.
TLS/SSL ile Şifreli MQTT Veri Yayını
Sıcaklık/nem verisini, sertifika tabanlı TLS/SSL şifrelemesiyle (WiFiClientSecure) bir MQTT broker'a güvenli şekilde yayınlamayı öğretir — düz metin (plaintext) MQTT'nin aksine veri yolda kimse tarafından okunamaz veya değiştirilemez. ESP32'nin donanımsal AES/SHA kripto hızlandırıcısı, TLS el sıkışmasını (handshake) makul bir sürede tamamlayacak işlem gücünü sağlar; 520KB SRAM'i ise TLS oturum arabelleklerini, sertifika zincirini ve şifreleme durumunu aynı anda bellekte tutabilir. Bu kapasite Arduino Uno'da bulunmaz: kartın sadece 2KB SRAM'i vardır ve tek bir TLS sertifikası bile bu belleğe sığmaz; kripto hızlandırma donanımı ve WiFi radyosu da zaten mevcut değildir, dolayısıyla şifreli bir ağ bağlantısı kurmanın önünde temel bir donanım sınırı vardır.