ESP32 Brownout Detector Was Triggered ve Guru Meditation Çözümü
ESP32 brownout detector was triggered hatası ve sürekli reset: güç kaynağı, kablo, kondansatör, rst kodları, Guru Meditation, Task WDT ve Exception Decoder.
ESP32 brownout detector was triggered mesajı, kartın besleme geriliminin bir anlığına güvenli sınırın altına düştüğünü ve yonganın kendini korumak için yeniden başlatıldığını söyler. Sorun neredeyse her zaman kodda değil güç tarafındadır: zayıf bir USB portu, ince ve uzun bir kablo, yetersiz bir regülatör ya da ESP32 ile aynı hattan beslenen servo ve LED şeritler. ESP32'nin sürekli yeniden başlamasının ikinci büyük sebebi ise yazılım çökmeleridir; bu durumda Seri Monitör'de Guru Meditation Error, task_wdt ya da Stack canary gibi satırlar görürsün.
İyi haber şu: ESP32 neden yeniden başladığını kendisi söyler, yeter ki mesajları okumayı bil. Bu rehberde önce açılış satırlarındaki rst kodlarını ve hata mesajlarını tanıyacak, ardından brownout'u güç kaynağı, kablo ve kondansatörle kalıcı olarak çözeceksin. Sonra LoadProhibited ve StoreProhibited gibi Guru Meditation hatalarını, yığın taşmasını, null pointer'ı ve watchdog zaman aşımlarını ele alacak, ESP Exception Decoder ile çökmeyi kod satırına kadar izleyeceksin. Son olarak açılışı bozan strapping pinlerine (GPIO0, 2, 12 ve 15) bakacağız.

ESP32 neden sürekli yeniden başlıyor? Önce mesajı oku
Teşhise başlamadan önce Seri Monitör'ü 115200 baud hızında aç ve karttaki EN düğmesine bas. ESP32'nin içindeki ROM önyükleyici her açılışta önce "ets Jun 8 2016 00:22:57" gibi bir tarih satırı, ardından rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) biçiminde bir satır yazar. rst kısmı kartın neden yeniden başladığını, boot kısmı ise hangi modda açıldığını gösterir. Kart bir döngüye girdiyse bu satırların hemen üstünde, önceki çalışmanın son sözleri olan hata mesajını bulursun. Aşağıdaki tablo, göreceğin mesajları ve nereden başlaman gerektiğini özetler:
| Seri Monitör'de gördüğün | Anlamı | Nereye bakmalısın? |
|---|---|---|
| Brownout detector was triggered | Besleme gerilimi eşiğin altına düştü | Güç kaynağı, kablo, kondansatör |
| Guru Meditation Error: Core 1 panic'ed (LoadProhibited) | Kod geçersiz bir adresten okumaya çalıştı | Null pointer, dizi sınırı |
| Guru Meditation Error: Core 1 panic'ed (StoreProhibited) | Kod geçersiz bir adrese yazmaya çalıştı | Null pointer, taşan tampon |
| Stack canary watchpoint triggered (loopTask) | Görevin yığını (stack) doldu | Büyük yerel diziler, özyineleme |
| task_wdt: Task watchdog got triggered | Bir görev 5 saniyeden uzun süre işlemciyi bırakmadı | Beklemesiz döngüler, takılan görevler |
| Interrupt wdt timeout on CPU0 / CPU1 | Bir kesme fonksiyonu ya da kapalı kesmeler 300 ms'yi aştı | Uzun ISR, ISR içinde Serial |
| boot:0x3 (DOWNLOAD_BOOT...) waiting for download | Kart programlama modunda açıldı | GPIO0 açılışta LOW |
| invalid header ya da flash read err | Flaş bellek okunamadı | GPIO12 açılışta HIGH, yarım kalmış yükleme |
Brownout detector was triggered nedir, neden olur?
Brownout, gerilimin tamamen kesilmeden kısa bir süre için düşmesi demektir. ESP32'nin içinde besleme hattını sürekli izleyen bir brownout dedektörü vardır ve Arduino çekirdeğinde bu dedektörün eşiği en düşük seviyeye, yaklaşık 2,43 V'a ayarlıdır. Gerilim bu değerin altına indiği anda yonga radyoyu ve flaş belleği korumaya alır, Seri Monitör'e "Brownout detector was triggered" yazar ve kendini yeniden başlatır. Bunun sebebi basittir: gerilim düşükken flaş bellek yanlış okunabilir, kayıtlı veriler bozulabilir ve işlemci rastgele komutlar çalıştırabilir. Dedektör, kartın tahmin edilemez davranmasındansa temiz bir reset atmasını sağlar. ESP32-WROOM-32 modülü 3,0–3,6 V arasında çalışacak şekilde tasarlanmıştır; yani gerilim 2,43 V'a indiğinde hat zaten çoktan güvenli bölgenin dışına çıkmıştır.
Brownout mesajından sonraki açılış satırında, Arduino çekirdeğinin sürümüne göre rst:0xc (SW_CPU_RESET) ya da rst:0x3 (SW_RESET) görürsün, çünkü dedektörün kesmesi mesajı yazdıktan sonra yongayı yazılımla yeniden başlatır. Bu seni yanıltmasın: aynı kod, sebebin brownout olduğunu yonganın hafızasına not eder ve esp_reset_reason() fonksiyonu ESP_RST_BROWNOUT döndürür. Donanımın kendi brownout reseti devreye girdiğinde ise satırda rst:0xf (RTCWDT_BROWN_OUT_RESET) yazar. ESP-IDF 5 tabanlı 3.x çekirdeklerde ise bu satır bir bilgi (INFO) günlüğüne dönüştü (I BOD: Brownout detector was triggered). Arduino'nun hazır derlenmiş kütüphaneleri yalnızca hata seviyesindeki günlükleri yazdığı için mesaj çoğu zaman hiç görünmez ve kart sessizce yeniden başlar; açılışta nedensiz bir rst:0x3 ya da rst:0xc görüyorsan teşhis kodundaki reset nedenine bak. Gerilimin neden düştüğünü anlamak için ESP32'nin ne kadar akım çektiğine bakmak gerekir:
| Çalışma durumu | Tipik akım (ESP32 yongası) |
|---|---|
| Derin uyku (RTC zamanlayıcısı açık) | Yaklaşık 10 µA |
| Hafif uyku (light sleep) | Yaklaşık 0,8 mA |
| Wi-Fi kapalı, işlemci 240 MHz | 30–68 mA |
| Wi-Fi alım (RX) | 95–100 mA |
| Wi-Fi gönderim, 802.11b, 19,5 dBm | Yaklaşık 240 mA |
| Açılıştaki radyo kalibrasyonu ve bağlantı anı | Mikrosaniyeler süren tepelerde 400 mA'i aşabilir |
Tablodaki fark brownout'un özüdür: kod Wi-Fi'yi açana kadar kart 50 mA civarında sakin çalışır, WiFi.begin() satırında ise akım birkaç mikrosaniye içinde beş altı katına çıkar. Kaynak, kablo ve regülatör bu ani isteğe yetişemezse gerilim çöker. Espressif bu yüzden ESP32 için en az 500 mA verebilen bir güç kaynağı önerir. Belirti de çok tanıdıktır: kart açılır, Seri Monitör'e birkaç satır yazar, Wi-Fi ya da Bluetooth başladığı anda resetlenir ve bu sonsuz bir döngüye dönüşür. Aynı şey bir servo hareket ettiğinde, bir röle çektiğinde ya da LED şerit beyaza döndüğünde de olabilir.
Brownout'un en sık sebepleri
- İnce ya da uzun USB kablosu: Ucuz kablolardaki ince güç telleri gidiş ve dönüşte toplam 0,5 Ω'a varan direnç gösterir. Ohm kanununa göre 400 mA'lik bir tepe bu kabloda 0,2 V kaybettirir.
- Zayıf USB portu ya da hub: Klavye ve monitör üzerindeki portlar, güçsüz hub'lar ve bazı dizüstü bilgisayarların ön portları tepe akımda gerilimi düşürür.
- Regülatörün düşüm gerilimi: Kartların çoğundaki AMS1117, girişi ile çıkışı arasında 1,0–1,3 V fark ister. 5V pinindeki gerilim 4,3 V civarının altına inerse çıkış 3,3 V'u tutamaz.
- Doğrudan pil bağlamak: 3,7 V'luk bir Li-ion pili 5V pinine bağlamak, regülatörün düşümü yüzünden çıkışı 3 V'un altına indirir; iki AA pil ise yük altında kısa sürede ESP32'nin alt sınırının altına düşer.
- Arduino Uno'nun 3.3V pini: Bu pinden yalnızca yaklaşık 50 mA çekilmesi önerilir; Wi-Fi açık bir ESP32 için kesinlikle yetmez.
- Aynı hattan beslenen yükler: Servo, röle, buzzer, DC motor ve WS2812B şerit ESP32 ile aynı 5 V'tan beslenirse her hareket gerilimi aşağı çeker.
- Breadboard ve jumper kabloları: Gevşek kontaklar ve ince jumper kablolar her bağlantıda biraz daha direnç ekler; güç hattını breadboard üzerinden dolaştırmak sorunu büyütür.
- ESP32-CAM: Kamera, Wi-Fi ve flaş LED'i aynı anda çalışınca akım çok yükselir; bu kart 5 V ve en az 2 A ile beslenmeyi sever. Ayrıntılar için ESP32-CAM yazısına bakabilirsin.
Çözüm 1: Güç kaynağını ve kabloyu düzelt
İlk ve en etkili adım beslemeyi güçlendirmektir. Kartı kısa, kalın ve iyi olduğunu bildiğin bir veri kablosuyla doğrudan bilgisayarın arka panelindeki USB portuna ya da en az 1 A veren 5 V bir adaptöre bağla. USB 2.0 portları 500 mA, USB 3.0 portları 900 mA verecek şekilde tasarlanmıştır; Espressif'in önerdiği 500 mA bir USB 2.0 portunun tam sınırıdır ve üstüne kablo kaybı eklenince sorun başlar. Kabloyu değiştirmek tek başına hatayı çözüyorsa sebep büyük olasılıkla kablonun direnciydi. Bir kablonun ne kadar gerilim kaybettirdiğini Ohm Kanunu aracıyla V = I × R formülünden hesaplayabilirsin.

| Besleme düzeni | Brownout riski | Not |
|---|---|---|
| Kısa, kalın kablo ve arka panel USB portu | Düşük | Geliştirme sırasında en kolay çözüm |
| Uzun, ince kablo, ön panel portu ya da hub | Yüksek | Kablo direnci tepe akımda gerilimi düşürür |
| En az 1 A veren 5 V adaptör, 5V ya da VIN pinine | Düşük | Kalıcı projeler için önerilir |
| Hazır 3,3 V kaynak doğrudan 3V3 pinine | Kaynağa bağlı | En az 500 mA vermeli ve 3,6 V'u asla aşmamalı |
| 3,7 V Li-ion pil, AMS1117 üzerinden | Yüksek | Pil 4 V'un altına inince çıkış 3 V'un altına düşer |
| Li-ion pil ve düşük düşümlü (LDO) 3,3 V regülatör ya da buck-boost | Düşük | Pil boşalırken de kararlı 3,3 V sağlar |
| İki AA pil doğrudan 3V3 pinine | Çok yüksek | Yük altında gerilim hızla ESP32'nin alt sınırının altına iner |
Pille çalışan projelerde dikkatli olman gerekir. 18650 gibi bir Li-ion hücre tam doluyken 4,2 V, boşken yaklaşık 3,0 V verir. Bu aralık ne 3V3 pinine doğrudan bağlamaya (4,2 V, 3,6 V sınırını aşar) ne de AMS1117'li 5V pinine bağlamaya uygundur. Doğru çözüm ya pili bir 5 V yükseltici (boost) modülle 5V pinine vermek ya da düşük düşümlü ve en az 500 mA verebilen bir LDO (örneğin ME6211 ya da HT7833) ve kondansatörle doğrudan 3V3 hattını beslemektir. Projenin pille ne kadar dayanacağını Pil ömrü aracıyla hesaplayabilir, şarj devresini TP4056 şarj modülü yazısında öğrenebilirsin.
Çözüm 2: 3V3 ve GND arasına kondansatör ekle
Kondansatör, akım tepesi geldiğinde regülatör ve kablo yetişene kadar enerjiyi kendisi veren küçük bir depo gibi çalışır. Kartın 3V3 ve GND pinleri arasına, karta olabildiğince yakın bir yere 100–470 µF'lık bir elektrolitik kondansatör ve yanına 100 nF'lık seramik bir kondansatör ekle. Elektrolitik kondansatör milisaniyelik düşüşleri, seramik olan ise çok kısa ve yüksek frekanslı dalgalanmaları karşılar. Etkisini kabaca ΔV = I × Δt / C formülüyle görebilirsin: 470 µF'lık bir kondansatör, 200 mA'lik fazladan bir akımı 200 µs boyunca tek başına karşılasa bile gerilim yalnızca 0,085 V düşer. Seramik kondansatörün üzerindeki 104 yazısı 100 nF demektir; diğer kodları Kondansatör kodu aracıyla çözebilirsin.

Çözüm 3: Servo, motor ve LED şeridi ayrı besle
ESP32'nin kendisi doğru beslense bile aynı hatta bağlı yükler gerilimi aşağı çekebilir. SG90 gibi küçük bir servo bile harekete başlarken birkaç yüz mA çeker; bir WS2812B LED tam beyazda yaklaşık 60 mA harcar, yani 30 LED'lik bir şerit 1,8 A'e kadar çıkabilir. Bu yükleri ESP32'nin 5V ya da 3V3 pininden değil, ayrı bir 5 V kaynaktan besle; örneğin 12 V bir adaptörü LM2596 düşürücü modülle 5 V'a indirebilirsin. En önemli kural, iki kaynağın GND uçlarını birbirine bağlamaktır; ortak toprak olmadan sinyal hattı referanssız kalır ve servo ya da şerit rastgele davranır. Bu konuyu Arduino Kendini Resetliyor mu? ve GND ve ortak toprak yazılarında ayrıntılı anlattık.

Brownout dedektörünü kapatmak çözüm mü?
İnternette en sık önerilen "çözüm", dedektörü tek satırla kapatmaktır. Aşağıdaki kod ESP32'nin brownout kaydını sıfırlayarak dedektörü devre dışı bırakır ve hata mesajı kaybolur. Ama gerilim düşmesi devam eder; sadece artık kimse sana haber vermez. Bu kodu yalnız teşhis için kullan: dedektör kapalıyken kart sorunsuz çalışıyorsa sorunun kesinlikle besleme olduğunu doğrulamış olursun. Ardından satırı sil ve beslemeyi düzelt.
1#include "soc/soc.h"
2#include "soc/rtc_cntl_reg.h"
3
4void setup() {
5 // YALNIZ TEŞHİS İÇİN: brownout dedektörünü kapat / DIAGNOSIS ONLY: disable the brownout detector
6 WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
7
8 Serial.begin(115200);
9 Serial.println("Brownout dedektoru kapali / brownout detector disabled");
10}
11
12void loop() {
13}rst cause kodları: ESP32 neden yeniden başladığını söyler
Her açılışta ROM'un yazdığı rst: değeri, bir önceki çalışmanın nasıl bittiğini gösterir. Normal bir açılışta boot değeri 0x13 (SPI_FAST_FLASH_BOOT) olur, yani kart programını flaş bellekten başlatır. Aşağıdaki tablo en sık karşılaşacağın kodları özetler. ROM kodları her zaman tek başına yeterli değildir: ESP.restart() ile Guru Meditation sonrası yeniden başlatma aynı 0xc koduyla görünür, brownout ise çekirdek sürümüne göre 0xc ya da 0x3 olarak çıkar. Ayrımı yapmak için bir sonraki bölümdeki esp_reset_reason() kodunu kullan.
| rst kodu | Adı | Ne anlama gelir? |
|---|---|---|
| 0x1 | POWERON_RESET | Güç ilk kez verildi ya da EN düğmesine basıldı |
| 0x3 | SW_RESET | Yazılım tüm dijital sistemi resetledi; yeni çekirdek sürümlerinde brownout sonrası da görülür |
| 0x5 | DEEPSLEEP_RESET | Kart derin uykudan uyandı (normaldir) |
| 0x7 / 0x8 | TG0WDT_SYS_RESET / TG1WDT_SYS_RESET | Zamanlayıcı grubu watchdog'u sistemi donanımla resetledi; kesmeler çok uzun süre kapalı kaldı ya da panik işleyicisi bile çalışamadı |
| 0x9 | RTCWDT_SYS_RESET | RTC watchdog'u dijital çekirdeği resetledi |
| 0xc | SW_CPU_RESET | Yazılımla yeniden başlatma: ESP.restart(), Guru Meditation sonrası ya da Arduino'da brownout sonrası |
| 0xf | RTCWDT_BROWN_OUT_RESET | Donanım brownout reseti: besleme gerilimi kararsız |
| 0x10 | RTCWDT_RTC_RESET | RTC watchdog'u RTC dahil tüm yongayı resetledi; çoğunlukla açılış sırasında takılan kartlarda görülür |
Teşhis kodu: reset nedenini, belleği ve yığını yazdır
Aşağıdaki kodu ayrı bir taslak olarak yükle ya da içindeki satırları sorunlu projenin setup() ve loop() fonksiyonlarına ekle. Kart her açıldığında reset nedenini okunabilir bir yazıyla, kaçıncı kez açıldığını ve bellek durumunu Seri Monitör'e yazar. RTC_DATA_ATTR ile işaretlenen sayaç RTC belleğinde tutulduğu için yazılım resetlerinde ve derin uykuda korunur, yalnızca güç tamamen kesilince sıfırlanır. Böylece sayaç her birkaç saniyede bir artıyorsa kartın bir reset döngüsünde olduğunu hemen anlarsın.
1#include <esp_system.h>
2
3RTC_DATA_ATTR uint32_t bootCount = 0; // yazılım resetinde korunur / survives software resets
4
5// Reset nedenini okunabilir yazıya çevir / turn the reset reason into readable text
6const char* reasonText(esp_reset_reason_t r) {
7 switch (r) {
8 case ESP_RST_POWERON: return "POWERON: guc acilisi ya da EN / power-on or EN button";
9 case ESP_RST_SW: return "SW: ESP.restart()";
10 case ESP_RST_PANIC: return "PANIC: Guru Meditation";
11 case ESP_RST_INT_WDT: return "INT_WDT: kesme watchdog'u / interrupt watchdog";
12 case ESP_RST_TASK_WDT: return "TASK_WDT: gorev watchdog'u / task watchdog";
13 case ESP_RST_WDT: return "WDT: diger watchdog / other watchdog";
14 case ESP_RST_DEEPSLEEP: return "DEEPSLEEP: derin uykudan uyanma / deep sleep wake-up";
15 case ESP_RST_BROWNOUT: return "BROWNOUT: gerilim dusmesi / supply voltage dropped";
16 default: return "UNKNOWN: bilinmiyor / unknown";
17 }
18}
19
20void setup() {
21 Serial.begin(115200);
22 delay(1000); // Seri Monitör'ün açılmasını bekle / wait for the Serial Monitor
23 bootCount++;
24 Serial.printf("Acilis sayisi / boot count: %u\n", (unsigned)bootCount);
25 Serial.printf("Reset nedeni / reset reason: %s\n", reasonText(esp_reset_reason()));
26}
27
28void loop() {
29 // Bellek durumu / memory status
30 Serial.printf("Bos heap / free heap: %u B, en dusuk / minimum: %u B, en buyuk blok / largest block: %u B\n",
31 (unsigned)ESP.getFreeHeap(), (unsigned)ESP.getMinFreeHeap(), (unsigned)ESP.getMaxAllocHeap());
32 // loopTask yığınında hiç kullanılmamış en küçük alan / smallest unused space on the loopTask stack
33 Serial.printf("loopTask bos yigin / free stack: %u B\n", (unsigned)uxTaskGetStackHighWaterMark(NULL));
34 delay(5000);
35}Kodun döngüde yazdığı değerler sessiz sorunları da ortaya çıkarır. Boş heap (free heap) değeri her turda biraz azalıyorsa programında bir bellek sızıntısı vardır ve kart eninde sonunda çökecektir. En büyük blok değeri boş heap'ten çok küçükse bellek parçalanmıştır; bu durum genellikle döngü içinde sürekli büyüyüp küçülen String nesnelerinden kaynaklanır. loopTask'ın boş yığın değeri birkaç yüz baytın altına iniyorsa yığın taşması kapıdadır. Reset nedeni BROWNOUT çıkıyorsa güç bölümüne, PANIC, TASK_WDT ya da INT_WDT çıkıyorsa aşağıdaki yazılım bölümlerine odaklan.
Guru Meditation Error nedir? Çökme çıktısını satır satır oku
Guru Meditation Error, ESP32'nin işlemcisi düzeltemeyeceği bir hatayla karşılaştığında panik işleyicisinin bastığı çökme raporudur; adı eski Amiga bilgisayarlarının hata ekranından gelir. Rapor ilk bakışta korkutucu görünür, ama yalnızca birkaç satırı önemlidir. Core 1 ifadesi hatanın hangi çekirdekte olduğunu söyler: Arduino'da setup() ve loop() 1. çekirdekte, Wi-Fi yığını ise 0. çekirdekte çalışır. Parantez içindeki ad istisnanın türüdür. Rapor bittikten sonra kart "Rebooting..." yazar ve yeniden başlar; açılış satırında rst:0xc görürsün.
| Satır | Anlamı |
|---|---|
| Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled. | 1. çekirdekteki kod geçersiz bir adresten okumaya çalıştı ve hata yakalanamadı |
| PC : 0x400d1a2c | Çökmenin olduğu komutun adresi; 0x400d ile başlıyorsa senin kodun ya da bir kütüphane flaştan çalışıyordur |
| EXCCAUSE: 0x0000001c | İstisna kodu; 0x1c yani 28, LoadProhibited demektir |
| EXCVADDR: 0x00000000 | Erişilmeye çalışılan adres; 0 ya da çok küçük bir sayı null pointer'ı gösterir |
| Backtrace: 0x400d1a29:0x3ffb2270 0x400d0f6e:0x3ffb2290 ... | Çağrı zinciri; her çift PC:SP biçimindedir ve decoder ile kod satırına çevrilir |
| ELF file SHA256: ... | Çöken programın parmak izi; decoder için aynı derlemeyi kullanman gerekir |
| Rebooting... | Panik işleyicisi yongayı yazılımla yeniden başlatıyor |
LoadProhibited, StoreProhibited ve diğer istisna türleri
| İstisna | EXCCAUSE | Ne oldu? | Sık sebep |
|---|---|---|---|
| LoadProhibited | 28 (0x1c) | Geçersiz adresten okuma | Null ya da başlatılmamış işaretçi, silinmiş nesne |
| StoreProhibited | 29 (0x1d) | Geçersiz adrese yazma | Null işaretçiye yazma, dizi sınırını aşan tampon |
| InstrFetchProhibited | 20 (0x14) | Geçersiz adresten komut okuma | Atanmamış fonksiyon işaretçisi ya da geri çağırma (callback) |
| IllegalInstruction | 0 (0x0) | Geçersiz komut | Bozulmuş yığın, değer döndürmesi gereken fonksiyonda unutulan return |
| LoadStoreAlignment | 9 (0x9) | Hizalanmamış bellek erişimi | Bayt dizisini uint32_t* gibi bir türe zorla çevirmek |
| IntegerDivideByZero | 6 (0x6) | Tamsayıyı sıfıra bölme | Sıfır olabilen bir sayaçla bölme |
| Unhandled debug exception | - | Hata ayıklama istisnası | Stack canary watchpoint triggered: yığın taşması |
| Interrupt wdt timeout on CPU0/CPU1 | - | Kesme watchdog'u doldu | Uzun ISR, ISR içinde Serial ya da delay |
| Cache disabled but cached memory region accessed | - | Flaş meşgulken flaştaki koda erişim | IRAM_ATTR olmayan kesme fonksiyonu |
Bu hataların en yaygını null pointer kullanımıdır. NULL adresi 0'dır ve ESP32'de 0 adresinin çevresinde okunabilir bir bellek yoktur; bu yüzden boş bir işaretçinin gösterdiği yerden okumak LoadProhibited, oraya yazmak StoreProhibited hatası verir. EXCVADDR değeri bu durumda tam bir ipucudur: 0x00000000 işaretçinin kendisini, 0x00000004 ya da 0x00000010 gibi küçük değerler ise boş bir işaretçinin içindeki bir alanı (NULL + alanın konumu) gösterir. Arduino projelerinde en sık sebep, bir fonksiyonun "bulamadım" anlamında NULL döndürmesi ve bu değerin kontrol edilmeden kullanılmasıdır. Aşağıdaki örnekte strstr() aranan metni bulamazsa NULL döner; kontrol yapılmazsa kart EXCVADDR 0x00000005 ile çöker.
1const char* response = "temp=23.5;hum=40"; // sunucudan gelen yanıt / reply from a server
2
3void setup() {
4 Serial.begin(115200);
5 delay(500);
6
7 // YANLIŞ: "pres=" yoksa strstr NULL döner ve kart çöker (EXCVADDR 0x00000005)
8 // WRONG: if "pres=" is missing strstr returns NULL and the board crashes (EXCVADDR 0x00000005)
9 // float pressure = atof(strstr(response, "pres=") + 5);
10
11 // DOĞRU: işaretçiyi kullanmadan önce NULL kontrolü yap / RIGHT: check for NULL before using the pointer
12 const char* found = strstr(response, "pres=");
13 if (found != nullptr) {
14 float pressure = atof(found + 5);
15 Serial.println(pressure);
16 } else {
17 Serial.println("pres alani bulunamadi / pres field not found");
18 }
19}
20
21void loop() {
22}Yığın taşması: Stack canary watchpoint triggered hatası
ESP32'de her görevin (task) sabit boyutlu bir yığını (stack) vardır; yerel değişkenler, fonksiyon çağrıları ve dönüş adresleri bu yığında tutulur. Arduino'da setup() ve loop() fonksiyonlarını çalıştıran loopTask görevinin yığını 8192 bayttır. loop() içinde 10 000 baytlık yerel bir dizi tanımlamak, kendini çağıran (özyinelemeli) bir fonksiyon ya da çok sayıda yerel değişken kullanan bir kütüphane fonksiyonu bu sınırı aşar. Yığının sonunda bir bekçi (canary) bölge vardır; yığın oraya ulaştığında kart Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception) ve hemen altında Debug exception reason: Stack canary watchpoint triggered (loopTask) yazar. Parantez içindeki ad, yığını taşan görevin adıdır. Aynı sorun bazen ***ERROR*** A stack overflow in task loopTask has been detected. mesajıyla da görünür. Çözüm yolları şunlardır:
- Büyük dizileri yığından çıkar: Diziyi global tanımla ya da başına static ekle; böylece yığında değil kalıcı RAM'de durur.
- loopTask yığınını büyüt: Taslağın en üstüne SET_LOOP_TASK_STACK_SIZE(16 * 1024); yazarak loop() yığınını 16 KB'a çıkarabilirsin.
- Kendi görevlerine yeterli yer ver: ESP32'de xTaskCreate ve xTaskCreatePinnedToCore fonksiyonlarına verilen yığın boyutu, FreeRTOS'un başka platformlarındaki gibi kelime (word) değil bayt cinsindendir. 1024 bayt, Serial.printf kullanan bir görev için bile azdır; 4096 ile başla.
- Ölç: uxTaskGetStackHighWaterMark(NULL), görevin o ana kadar hiç kullanmadığı en küçük yığın miktarını bayt olarak verir; bu değer birkaç yüz baytın altına iniyorsa yığını büyüt.
- Özyinelemeden kaçın: Kendini çağıran fonksiyonları döngüye çevir ya da derinliğini sınırla.
Task watchdog: "task_wdt: Task watchdog got triggered" hatası
Watchdog (bekçi köpeği), takılan bir programı fark edip kartı kurtaran bir zamanlayıcıdır. ESP32'nin görev watchdog'u (Task WDT), kendisine kayıtlı görevlerin belirli aralıklarla "yaşıyorum" sinyali vermesini bekler. Arduino çekirdeğinde varsayılan olarak 0. çekirdeğin boşta (IDLE) görevini izler ve süresi 5 saniyedir. 0. çekirdekte çalışan bir görev 5 saniye boyunca işlemciyi hiç bırakmazsa IDLE görevi çalışamaz ve Seri Monitör'de E (10257) task_wdt: Task watchdog got triggered. ile başlayan bir mesaj belirir. Hemen ardından watchdog'u zamanında sıfırlamayan görevlerin listesi (çoğunlukla - IDLE (CPU 0)) ve Tasks currently running: başlığı altında o anda çalışan görevler gelir. Arduino çekirdeğinde bu durumda task_wdt: Aborting. satırıyla panik başlar ve kart yeniden başlar.
En sık sebepler şunlardır: xTaskCreatePinnedToCore ile 0. çekirdeğe yerleştirilmiş ve içinde hiç vTaskDelay() olmayan bir döngü, bir sensörden zaman aşımı olmadan yanıt bekleyen bir while döngüsü ya da AsyncWebServer gibi kütüphanelerin geri çağırma fonksiyonlarında delay() ya da uzun işlemler. Son durumda listede IDLE yerine async_tcp görevini görürsün. Çözüm, uzun işleri küçük parçalara bölmek ve döngülere vTaskDelay(1) gibi kısa beklemeler eklemektir. loop() fonksiyonunun kendisi varsayılan olarak izlenmez; istersen setup() içinde enableLoopWDT() çağırarak loop() 5 saniyeden uzun takıldığında da kartın yeniden başlamasını sağlayabilirsin. Watchdog'u disableCore0WDT() ile kapatmak hatayı gizler ama takılan kodu düzeltmez. Görevler ve çekirdekler hakkında daha fazlası için ESP32 FreeRTOS ve çift çekirdek yazısına bakabilirsin. Aşağıdaki kod hem doğru görev yapısını hem de yığın taşmasına karşı alınacak önlemleri gösterir:
1SET_LOOP_TASK_STACK_SIZE(16 * 1024); // loop() yığını 8 KB yerine 16 KB / loop() stack 16 KB instead of 8 KB
2
3volatile uint32_t sampleCount = 0;
4
5// 0. çekirdekte çalışan görev / task running on core 0
6void sensorTask(void* parameter) {
7 for (;;) {
8 sampleCount = sampleCount + 1; // sensörünü burada oku / read your sensor here
9 vTaskDelay(pdMS_TO_TICKS(10)); // IDLE görevine sıra ver, task_wdt tetiklenmez / let IDLE run, no task_wdt
10 }
11}
12
13void setup() {
14 Serial.begin(115200);
15 // Yığın boyutu bayt cinsindendir: 4096 bayt / stack size is in bytes: 4096 bytes
16 xTaskCreatePinnedToCore(sensorTask, "sensorTask", 4096, NULL, 1, NULL, 0);
17}
18
19void loop() {
20 static uint8_t buffer[10000]; // static: yığında değil kalıcı RAM'de / static: in RAM, not on the stack
21 memset(buffer, 0, sizeof(buffer));
22
23 Serial.printf("Ornek / samples: %u, loopTask bos yigin / free stack: %u B\n",
24 (unsigned)sampleCount, (unsigned)uxTaskGetStackHighWaterMark(NULL));
25 delay(1000);
26}Interrupt wdt timeout ve IRAM_ATTR: kesmelerde çökme
Kesme watchdog'u (Interrupt WDT) çok daha sabırsızdır: bir kesme fonksiyonu (ISR) ya da kesmelerin kapalı tutulduğu bir kod parçası 300 ms'yi aşarsa kart Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1) hatasıyla çöker. ISR içinde Serial.print, delay(), I2C ya da Wi-Fi işlemleri yapmak en sık sebeptir. Bir başka tuzak da flaş bellektir: Preferences, EEPROM ya da LittleFS flaşa yazarken flaş önbelleği bir anlığına kapanır. Bu sırada gelen bir kesmenin fonksiyonu flaşta duruyorsa kart Cache disabled but cached memory region accessed hatası verir. Çözüm, ISR'leri IRAM_ATTR ile işaretleyip RAM'e koymak ve içlerinde yalnızca bir bayrak kaldırmaktır; asıl işi loop() yapar. ISR ile loop() arasında paylaşılan değişkenler volatile olmalıdır.
1const int BUTTON_PIN = 27; // buton GPIO 27 ile GND arasında / button between GPIO 27 and GND
2volatile bool buttonPressed = false; // ISR ile loop arasında paylaşılan bayrak / flag shared by the ISR and loop
3uint32_t pressCount = 0;
4
5void IRAM_ATTR onButton() { // IRAM_ATTR: fonksiyon flaşta değil RAM'de durur / the function lives in RAM, not flash
6 buttonPressed = true; // yalnızca bayrak kaldır, Serial yok / only set a flag, no Serial
7}
8
9void setup() {
10 Serial.begin(115200);
11 pinMode(BUTTON_PIN, INPUT_PULLUP);
12 attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), onButton, FALLING);
13}
14
15void loop() {
16 if (buttonPressed) {
17 buttonPressed = false;
18 pressCount++;
19 Serial.printf("Butona basildi / button pressed: %u\n", (unsigned)pressCount); // yavaş iş burada / slow work here
20 }
21}ESP Exception Decoder ile Backtrace'i kod satırına çevirmek
Backtrace satırındaki adresler tek başına bir şey söylemez; onları kaynak kodundaki dosya, fonksiyon ve satır numarasına çeviren araca ESP Exception Decoder denir. Eski Arduino IDE 1.8'de bu araç Araçlar menüsüne eklenen bir eklentiydi. Arduino IDE 2'de ise topluluğun geliştirdiği aynı adlı uzantıyı kullanırsın:
- GitHub'daki dankeboy36/esp-exception-decoder projesinin Releases bölümünden .vsix uzantılı dosyayı indir. Arduino IDE 2 için 1.x sürümlerini seç; yeni 2.x sürümleri VS Code için hazırlanmıştır.
- Arduino IDE'yi kapat ve dosyayı Windows'ta %UserProfile%\.arduinoIDE\plugins, macOS ve Linux'ta ~/.arduinoIDE/plugins klasörüne kopyala; klasör yoksa oluştur.
- IDE'yi aç, çöken taslağı aç, Doğrula ile derle ve karta yükle.
- Seri Monitör'ü aç ve çökmenin yeniden olmasını bekle.
- Ctrl+Shift+P (macOS'ta Cmd+Shift+P) ile komut paletini aç ve ESP Exception Decoder: Show Decoder Terminal komutunu çalıştır.
- Seri Monitör'deki Guru Meditation bloğunu Backtrace satırıyla birlikte kopyalayıp açılan terminale yapıştır; araç her adresi dosya adı, fonksiyon ve satır numarasıyla gösterir.
Uzantıyı kuramıyorsan aynı işi elle de yapabilirsin. Sketch > Export Compiled Binary menüsü, taslak klasörünün içindeki build klasörüne .elf uzantılı bir dosya bırakır. ESP32 araç zincirindeki xtensa-esp32-elf-addr2line -pfiaC -e taslak.ino.elf 0x400d1a29 0x400d0f6e komutu bu adresleri fonksiyon adlarına ve satır numaralarına çevirir. PlatformIO kullanıyorsan platformio.ini dosyasına monitor_filters = esp32_exception_decoder satırını eklemen yeterlidir; çökme çıktısı seri monitörde kendiliğinden çözülür.
Strapping pinleri: GPIO0, GPIO2, GPIO12 ve GPIO15 açılışı nasıl bozar?
ESP32 açılırken bazı pinlerin seviyesine bakarak nasıl başlayacağına karar verir. Bu pinlere strapping pinleri denir ve yalnızca reset anındaki seviyeleri önemlidir; açılış bittikten sonra normal GPIO gibi kullanılabilirler. Sorun, bu pinlere bağladığın bir sensörün, butonun ya da modülün açılış anında pini yanlış seviyeye çekmesidir. Bu durumda kart programını hiç başlatmaz, programlama moduna girer ya da flaş belleği okuyamaz; dışarıdan bakınca bu da "ESP32 açılmıyor" ya da "sürekli resetleniyor" gibi görünür. Kartının tam pin haritasını Pinout aracında görebilirsin.
| Pin | Dahili direnç | Açılıştaki görevi | Yanlış seviyede ne olur? |
|---|---|---|---|
| GPIO0 | Pull-up | LOW ise programlama (download) modu, HIGH ise normal açılış | boot:0x3 (DOWNLOAD_BOOT) ve waiting for download; program çalışmaz |
| GPIO2 | Pull-down | Programlama moduna girmek için LOW ya da boşta olmalı; normal açılışta önemsizdir | HIGH'a çeken bir devre kod yüklemeyi engeller |
| GPIO12 (MTDI) | Pull-down | Flaşın besleme gerilimini seçer: LOW 3,3 V, HIGH 1,8 V | HIGH ise 3,3 V'luk flaş beslenemez; kart açılmaz ya da reset döngüsüne girer |
| GPIO15 (MTDO) | Pull-up | LOW ise ROM'un açılış mesajlarını susturur | Seri Monitör'de açılış satırları görünmez, teşhis zorlaşır |
| GPIO5 | Pull-up | SDIO zamanlamasını belirler | Geliştirme kartlarında nadiren sorun çıkarır |
Yeni nesil kartlarda strapping pinleri farklıdır: ESP32-S3'te GPIO0, GPIO3, GPIO45 ve GPIO46, ESP32-C3'te ise GPIO2, GPIO8 ve GPIO9 açılışı etkiler. ESP32-S3 klasik ESP32 ile aynı Xtensa istisna adlarını kullanır. RISC-V çekirdekli ESP32-C3'te ise LoadProhibited yerine Load access fault, StoreProhibited yerine Store access fault görürsün ve EXCVADDR'ın görevini MTVAL kaydı üstlenir. Brownout mesajı ise bütün modellerde aynıdır.
MicroPython'da ESP32 ve Raspberry Pi Pico
ESP32'yi MicroPython ile programlıyorsan brownout tamamen aynı şekilde olur, çünkü sorun yazılımda değil donanımdadır. Python kodundaki hatalar ise Guru Meditation yerine okunabilir bir Traceback olarak görünür ve kart nadiren çöker. Reset nedenini machine.reset_cause() ile okuyabilirsin, ama dikkat: MicroPython'un ESP32 sürümü brownout'u ayrı bir değer olarak döndürmez, güç açılışıyla birlikte PWRON_RESET olarak raporlar. Kart sen dokunmadığın halde sürekli PWRON_RESET ile açılıyorsa yine beslemeden şüphelen. Aşağıdaki kod ESP32 içindir; Raspberry Pi Pico'da machine modülü daha az reset türü tanır. Pico'da VSYS girişindeki buck-boost regülatör 1,8–5,5 V arasındaki gerilimlerle çalışabildiği için brownout sorunları çok daha seyrektir; kartı tanımak için Raspberry Pi Pico Nedir? yazısına bakabilirsin.
1import machine, gc, time
2
3# Reset nedenleri (ESP32 için) / reset causes (for ESP32)
4causes = {
5 machine.PWRON_RESET: "PWRON: guc acilisi ya da brownout / power-on or brownout",
6 machine.HARD_RESET: "HARD: cokme ya da machine.reset() / crash or machine.reset()",
7 machine.WDT_RESET: "WDT: watchdog",
8 machine.DEEPSLEEP_RESET: "DEEPSLEEP: derin uykudan uyanma / deep sleep wake-up",
9 machine.SOFT_RESET: "SOFT: Ctrl+D ile yazilim reseti / soft reset with Ctrl+D",
10}
11print("Reset nedeni / reset cause:", causes.get(machine.reset_cause(), "bilinmiyor / unknown"))
12
13while True:
14 gc.collect() # çöp toplayıcıyı çalıştır / run the garbage collector
15 print("Bos RAM / free RAM:", gc.mem_free(), "bayt / bytes")
16 time.sleep(5)Sık hatalar ve çözümleri
| Belirti | Olası sebep | Çözüm |
|---|---|---|
| Wi-Fi başlarken Brownout detector was triggered | Kablo, port ya da regülatör tepe akıma yetişmiyor | Kısa kalın kablo, 1 A adaptör, 3V3-GND arasına 470 µF + 100 nF |
| Servo dönünce ya da röle çekince reset | Yük ESP32 ile aynı hattan besleniyor | Yükü ayrı 5 V kaynaktan besle, GND'leri birleştir |
| Pil biraz boşalınca resetler başlıyor | AMS1117'nin düşüm gerilimi | LDO ya da buck-boost dönüştürücü kullan |
| Guru Meditation, EXCVADDR 0x00000000 | Null pointer | İşaretçiyi kullanmadan önce kontrol et |
| Stack canary watchpoint triggered (loopTask) | loop() yığını doldu | Büyük dizileri static yap ya da SET_LOOP_TASK_STACK_SIZE kullan |
| task_wdt: - IDLE (CPU 0) | 0. çekirdekte beklemesiz döngü | Döngüye vTaskDelay ekle |
| Interrupt wdt timeout on CPU1 | ISR çok uzun | ISR'de yalnız bayrak kaldır, IRAM_ATTR kullan |
| Kart sessiz, boot:0x3 ve waiting for download | GPIO0 açılışta LOW | GPIO0'a bağlı devreyi kaldır, EN'e bas |
| Kart hiç açılmıyor, flaş okuma hatası | GPIO12 açılışta HIGH | GPIO12'deki pull-up'ı ya da modülü başka bir pine taşı |
| Kod yüklerken Failed to connect to ESP32 | GPIO2 HIGH ya da kart programlama moduna giremiyor | GPIO2'yi boşalt, yükleme başlarken BOOT'a basılı tut |
Kartın kararlı çalışıyor: sırada ne var?
- Pil dostu cihaz: ESP32 deep sleep ile kartı ölçümler arasında uyutup mikroamper seviyesinde akım çek.
- Kablosuz güncelleme: ESP32 OTA ile kodu USB kablosuz yükle.
- Gerçek zamanlı panel: ESP32 WebSocket ile sensör verisini tarayıcıda canlı izle.
- Bildirim gönder: ESP32 Telegram bot ile kart her yeniden başladığında reset nedenini telefonuna mesaj olarak al.
- Işık şovu: WS2812B NeoPixel şeridini ayrı beslemeyle güvenle sür.
ESP32'nin yeniden başlama sorunlarının çoğu ya bir güç sorunudur ya da birkaç satırlık bir kod hatası; mesajı doğru okuduğunda ikisi de hızla çözülür. Kartın temellerini tazelemek için ESP32 Nedir? yazısına göz atabilirsin. BlueGrays uygulamasında ESP32 ile LED, servo, NeoPixel şerit, Wi-Fi bağlantısı, web sunucu, OTA güncelleme ve derin uyku projelerini adım adım devre şeması ve kodlarıyla bulabilir, burada öğrendiğin güç ve teşhis yöntemlerini gerçek projelerde deneyebilirsin.
Sıkça sorulan sorular
ESP32 brownout detector was triggered hatası nasıl düzelir?
Bu hata, ESP32'nin besleme geriliminin bir anlığına 2,43 V civarının altına düştüğünü gösterir. Önce kısa ve kalın bir USB kablosuyla en az 1 A veren 5 V bir kaynak kullan, ardından 3V3 ile GND arasına 100–470 µF elektrolitik ve 100 nF seramik kondansatör ekle. Servo, röle ve LED şerit gibi yükleri ayrı bir kaynaktan besleyip GND'leri birleştir.
ESP32 neden sürekli yeniden başlıyor?
En sık sebepler yetersiz besleme (brownout), yazılım çökmeleri (Guru Meditation), watchdog zaman aşımları ve açılışta yanlış seviyede kalan strapping pinleridir. Seri Monitör'ü 115200 baud hızında açıp EN düğmesine bas; resetten önceki son mesaj ve açılıştaki rst kodu sebebi gösterir. esp_reset_reason() fonksiyonu da sebebi kodun içinden okumanı sağlar.
Guru Meditation Error LoadProhibited ne demek?
ESP32'deki kodun geçersiz bir bellek adresinden okumaya çalıştığı anlamına gelir. EXCVADDR değeri 0 ya da çok küçük bir sayıysa neredeyse her zaman bir null pointer kullanılmıştır. Backtrace satırını ESP Exception Decoder'a yapıştırarak hatanın hangi dosya ve satırda olduğunu bulabilirsin.
ESP32 brownout dedektörü kapatılabilir mi?
Evet, WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) satırıyla kapatılabilir, ama bu yalnızca uyarıyı susturur. Gerilim düşmesi sürdüğü için flaştaki veriler bozulabilir ve kart başka hatalarla çökebilir. Bu yöntemi yalnızca sorunun güçten kaynaklandığını doğrulamak için kısa süreli kullan.
ESP32 Task watchdog got triggered hatası nasıl çözülür?
Bu mesaj, izlenen bir görevin 5 saniye boyunca işlemciyi bırakmadığını gösterir; Arduino'da listede genellikle 0. çekirdeğin IDLE görevi yer alır. Kendi oluşturduğun görevlerdeki döngülere vTaskDelay() ekle, sensör beklerken zaman aşımı kullan ve web sunucusu geri çağırmalarında delay() ya da uzun işlemler yapma. Watchdog'u kapatmak hatayı gizler, sebebi düzeltmez.
ESP32 için kaç amperlik adaptör gerekir?
Espressif, ESP32 için en az 500 mA verebilen bir güç kaynağı önerir; pratikte 5 V ve 1 A'lik bir adaptör güvenli bir pay bırakır. ESP32-CAM kullanıyorsan ya da servo, LED şerit gibi yükler eklediysen 2 A ve üzeri bir kaynak seç ve bu yükleri mümkünse ayrı bir hattan besle.
Bu yazıdan sonra yapabileceğin projeler
Tüm projeleri gör
ESP32 ile LED Yakma
ESP32 ile temel GPIO çıkışı kullanımını öğretir. Bir LED'i dijital pinden açıp kapatarak yanıp sönme efekti elde ederiz. Arduino UNO'daki klasik blink projesinin ESP32 versiyonu; Arduino ortamındaki temel blink komutları aynıdır, ancak ESP32'nin pin yerleşimi ve 3,3 V GPIO seviyeleri Arduino UNO'dan farklıdır.

ESP32 Wi-Fi STA Bağlantısı (LCD Ekranlı)
Bu projede ESP32'yi Station (STA) modunda evdeki Wi-Fi ağına güvenli ve hata toleranslı şekilde bağlıyoruz. SSID/şifreyi secrets.h dosyasına ayırarak Git'e sızmasını önlüyor, otomatik yeniden bağlanma mekanizması kuruyor, RSSI sinyal seviyesini ve IP adresini I2C LCD ekranda gösteriyoruz. Dahili LED durum göstergesi olarak çalışır. Üretim seviyesi bir bağlantı yöneticisidir.

ESP32 Servo Motor (Potansiyometre Kontrolü)
Bu projede potansiyometre ile SG90 servo motoru kontrol ediyoruz. Potansiyometreden okunan analog değeri 0-180 derece aralığına map'leyerek servo açısını ayarlıyoruz. ESP32Servo kütüphanesi, ESP32'nin çıkış verebilen uygun GPIO'larında servo sinyali üretir; bu projede GPIO 18 kullanılır. Bu, robotik kollar, kamera gimbal'ları ve otomatik kapı mekanizmaları için temel bir kontrol yöntemidir.

ESP32 WS2812B NeoPixel Şerit Kontrolü
WS2812B (NeoPixel) adreslenebilir LED'ler, tek bir veri pini üzerinden zincirleme kontrol edilebilen akıllı RGB LED'lerdir. Bu projede 8 LED'lik bir WS2812B şeridi Adafruit_NeoPixel kütüphanesi ile kontrol edip akıcı bir gökkuşağı animasyonu üreteceğiz. ESP32'nin 3.3V mantık seviyesi çoğu WS2812B partisinde sorunsuz çalışsa da, kararsızlık durumunda 470Ω seri direnç ve 1000µF kondansatör çözümünü göstereceğiz. Animasyon, HSV renk uzayında ton (hue) değerini kaydırarak elde edilir.

ESP32 Async Web Server (LCD'de IP Göstergeli)
Bu projede ESP32'yi aynı Wi-Fi ağındaki telefonunuzdan veya bilgisayarınızdan kontrol edebileceğiniz asenkron bir web sunucusuna dönüştürüyoruz. ESPAsyncWebServer kütüphanesi sayesinde sunucu birden fazla isteği aynı anda işleyebiliyor (klasik WebServer.h gibi tek istekte bloklamıyor). Tarayıcıdan ESP32'nin IP adresine bağlanıp ON/OFF butonlarına basarak (/on ve /off adresleri) GPIO 5'e bağlı LED'i açıp kapatabileceksiniz.

ESP32 Deep Sleep — Pil Tasarrufu (OLED + RTC RAM Sayaç)
ESP32'nin Deep Sleep modu, CPU ve çoğu çevre birimini kapatarak akım tüketimini ~10µA seviyesine düşürür ve pille çalışan IoT cihazları için kritik öneme sahiptir. Bu projede üç farklı uyandırma kaynağını kullanıyoruz: zamanlayıcı (timer, 15sn), harici pin (EXT0 — buton GPIO 33) ve touch (T0/GPIO 4). RTC_DATA_ATTR ile işaretlenen değişkenler deep sleep boyunca korunur — boot sayacı, timer wake sayacı ve buton wake sayacı kalıcı olarak izlenir. SSD1306 OLED ekranda her uyanışta wake reason, say

ESP32 OTA Update — Kablosuz Firmware Yükleme (LCD Ekranlı)
Bu projede ESP32'ye USB kablosu olmadan, Wi-Fi üzerinden yeni firmware yüklemeyi öğreneceksin. ArduinoOTA kütüphanesi ile ESP32 ağda görünür hale gelir ve Arduino IDE'nin "Network port" sekmesinde bluegrays-ota olarak otomatik listelenir. İlk yükleme USB ile yapılır, sonrasında tüm güncellemeler kablosuz olur — saha cihazları için çok kritik bir özelliktir. I2C LCD ekranda WiFi durumu, IP, hostname, OTA yükleme yüzdesi ve hata mesajları hem Türkçe hem İngilizce gösterilir. Parola koruması, h

ESP32 Hareket Alarm Sistemi (PIR + Buzzer + LED + Telegram)
PIR sensörü hareket algıladığında buzzer ve LED'i aktif eden, aynı anda Telegram üzerinden sahibine anlık bildirim gönderen akıllı bir güvenlik alarm sistemidir. Tekrarlayan alarmların sıklığını sınırlamak için 30 saniyelik cooldown (bekleme süresi) mekanizması vardır; bu mekanizma PIR sensörünün yanlış algılamalarını doğrulamaz veya ortadan kaldırmaz. Ev güvenliği, garaj izleme, depo veya çalışma odası gibi alanlarda kullanılabilir. Telegram entegrasyonu sayesinde nerede olursanız olun anında h
Diğer yazılar
BlueGrays uygulaması
Bu devreyi telefonunda adım adım kur
Devre şeması, kod ve parça listesi tek ekranda. 200'den fazla Arduino, ESP32 ve Pico projesi seni bekliyor.
Telefonunla tara
Kamerayı koda tut; telefonunun uygulama mağazası açılır.
ya da mağazada aç

