Rehberler · 17 dk okuma

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 DevKit geliştirme kartı
ESP32 geliştirme kartı: USB'den gelen 5 V, kart üzerindeki regülatörle 3,3 V'a düşürülür. Brownout sorunlarının çoğu bu 3,3 V hattında yaşanan anlık çökmelerden kaynaklanır.

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üğünAnlamıNereye bakmalısın?
Brownout detector was triggeredBesleme 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) dolduBüyük yerel diziler, özyineleme
task_wdt: Task watchdog got triggeredBir görev 5 saniyeden uzun süre işlemciyi bırakmadıBeklemesiz döngüler, takılan görevler
Interrupt wdt timeout on CPU0 / CPU1Bir kesme fonksiyonu ya da kapalı kesmeler 300 ms'yi aştıUzun ISR, ISR içinde Serial
boot:0x3 (DOWNLOAD_BOOT...) waiting for downloadKart programlama modunda açıldıGPIO0 açılışta LOW
invalid header ya da flash read errFlaş 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 durumuTipik 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 MHz30–68 mA
Wi-Fi alım (RX)95–100 mA
Wi-Fi gönderim, 802.11b, 19,5 dBmYaklaşı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.
Multimetrede 3,3 V görmek beslemenin sağlam olduğu anlamına gelmez. Multimetre saniyede yalnızca birkaç ölçüm alır ve ortalamaya yakın bir değer gösterir; brownout'a sebep olan çökmeler ise mikrosaniyeler ile birkaç milisaniye arasında sürer ve ekranda hiç görünmez. Bu düşmeleri ancak bir osiloskopla görebilirsin. Osiloskobun yoksa aşağıdaki çözümleri sırayla uygula ve her adımdan sonra hatanın kaybolup kaybolmadığına bak. Ölçüm temellerini Multimetre Nasıl Kullanılır? yazısında bulabilirsin.

Çö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.

AMS1117 3,3 V voltaj regülatörü
AMS1117-3.3: ESP32 kartlarının çoğundaki regülatör. 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.
Besleme düzeniBrownout riskiNot
Kısa, kalın kablo ve arka panel USB portuDüşükGeliştirme sırasında en kolay çözüm
Uzun, ince kablo, ön panel portu ya da hubYüksekKablo direnci tepe akımda gerilimi düşürür
En az 1 A veren 5 V adaptör, 5V ya da VIN pinineDüşükKalıcı projeler için önerilir
Hazır 3,3 V kaynak doğrudan 3V3 pinineKaynağa bağlıEn az 500 mA vermeli ve 3,6 V'u asla aşmamalı
3,7 V Li-ion pil, AMS1117 üzerindenYüksekPil 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-boostDüşükPil boşalırken de kararlı 3,3 V sağlar
İki AA pil doğrudan 3V3 pinineÇok yüksekYü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.

Kondansatör çeşitleri
Elektrolitik kondansatörlerde uzun bacak artı (+) uçtur ve 3V3'e gelir; gövdedeki şeritli tarafın bacağı GND'ye bağlanır. 3,3 V hattı için 6,3 V ya da 10 V dayanımlı bir model yeterlidir.
Elektrolitik kondansatörü ters takma: ısınır, şişer ve patlayabilir. Kondansatörü 5V hattına bağlayacaksan en az 10 V dayanımlı bir model seç. Çok büyük kondansatörler (1000 µF ve üzeri) ilk açılışta yüksek bir şarj akımı çekerek USB portunu bir an zorlayabilir ve 3,3 V hattının yükselişini yavaşlatabilir; 3V3 hattında 470 µF çoğu proje için yeterlidir. Kondansatörlerin çalışma mantığını Kondansatör Nedir? yazısında bulabilirsin.

Çö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.

LM2596 step-down (buck) modülü
LM2596 düşürücü modül: 12 V'u verimli biçimde 5 V'a indirir; servo, röle ya da LED şerit gibi yükleri ESP32'den ayrı beslemek için idealdir. Çıkışı trimpotla ayarlanır, bağlamadan önce multimetreyle 5 V'a ayarla.
Yazılımla da akım tepelerini yumuşatabilirsin. Wi-Fi'yi servoları hareket ettirmeden ve LED şeridi yakmadan önce başlat; şeridin parlaklığını setBrightness() ile sınırla; servo ve röleleri aynı anda değil birkaç yüz milisaniye arayla çalıştır. Wi-Fi verici gücünü WiFi.setTxPower() ile düşürmek de tepe akımı azaltır; ayrıntılar ESP32 WiFi Bağlanmıyor yazısında.

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.

C++ (Arduino IDE)
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}
Dedektörü kalıcı olarak kapalı bırakma. WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) yalnızca uyarıyı susturmaz; dedektörün donanım resetini ve düşük gerilimde flaşı ve radyoyu kapatma görevini de devre dışı bırakır, yonga 3,0 V'luk alt sınırının çok altında korumasız çalışmaya devam eder. Gerilim 2,4 V'un altına indiğinde flaşa yazılan veriler (Preferences, EEPROM, LittleFS), hatta OTA güncellemesi sırasında programın kendisi bozulabilir, Wi-Fi açıklanamayan biçimde kopabilir ve kart bu kez Guru Meditation hatalarıyla ya da tamamen donarak çökebilir. Ayar kalıcı değildir: yonga her açılışta dedektörü yeniden etkinleştirir, bu yüzden satır setup()'ın ilk satırı olmalıdır ve sildiğinde koruma geri gelir. Bu kayıt klasik ESP32, S2, S3 ve C3'te bulunur; ESP32-C6 gibi yeni modellerde yoktur ve kod derlenmez. Gerçek çözüm her zaman beslemeyi düzeltmektir.

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 koduAdıNe anlama gelir?
0x1POWERON_RESETGüç ilk kez verildi ya da EN düğmesine basıldı
0x3SW_RESETYazılım tüm dijital sistemi resetledi; yeni çekirdek sürümlerinde brownout sonrası da görülür
0x5DEEPSLEEP_RESETKart derin uykudan uyandı (normaldir)
0x7 / 0x8TG0WDT_SYS_RESET / TG1WDT_SYS_RESETZamanlayıcı grubu watchdog'u sistemi donanımla resetledi; kesmeler çok uzun süre kapalı kaldı ya da panik işleyicisi bile çalışamadı
0x9RTCWDT_SYS_RESETRTC watchdog'u dijital çekirdeği resetledi
0xcSW_CPU_RESETYazılımla yeniden başlatma: ESP.restart(), Guru Meditation sonrası ya da Arduino'da brownout sonrası
0xfRTCWDT_BROWN_OUT_RESETDonanım brownout reseti: besleme gerilimi kararsız
0x10RTCWDT_RTC_RESETRTC 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.

C++ (Arduino IDE)
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ırAnlamı
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: 0x00000000Eriş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

İstisnaEXCCAUSENe oldu?Sık sebep
LoadProhibited28 (0x1c)Geçersiz adresten okumaNull ya da başlatılmamış işaretçi, silinmiş nesne
StoreProhibited29 (0x1d)Geçersiz adrese yazmaNull işaretçiye yazma, dizi sınırını aşan tampon
InstrFetchProhibited20 (0x14)Geçersiz adresten komut okumaAtanmamış fonksiyon işaretçisi ya da geri çağırma (callback)
IllegalInstruction0 (0x0)Geçersiz komutBozulmuş yığın, değer döndürmesi gereken fonksiyonda unutulan return
LoadStoreAlignment9 (0x9)Hizalanmamış bellek erişimiBayt dizisini uint32_t* gibi bir türe zorla çevirmek
IntegerDivideByZero6 (0x6)Tamsayıyı sıfıra bölmeSı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 dolduUzun ISR, ISR içinde Serial ya da delay
Cache disabled but cached memory region accessed-Flaş meşgulken flaştaki koda erişimIRAM_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.

C++ (Arduino IDE)
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}
Null pointer'a karşı birkaç alışkanlık edin: işaretçileri tanımlarken nullptr ile başlat, kütüphanelerin begin() fonksiyonlarının dönüş değerini kontrol et, bir nesneyi delete ettikten sonra işaretçiyi nullptr yap ve dizilere yazarken indeksin dizi boyutundan küçük olduğundan emin ol. Arduino IDE'de Dosya > Tercihler menüsündeki derleyici uyarıları ayarını Tümü yaparsan unutulan return ve benzeri hataları derleme sırasında görürsün.

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:

C++ (Arduino IDE)
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.

C++ (Arduino IDE)
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:

  1. 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.
  2. 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.
  3. IDE'yi aç, çöken taslağı aç, Doğrula ile derle ve karta yükle.
  4. Seri Monitör'ü aç ve çökmenin yeniden olmasını bekle.
  5. Ctrl+Shift+P (macOS'ta Cmd+Shift+P) ile komut paletini aç ve ESP Exception Decoder: Show Decoder Terminal komutunu çalıştır.
  6. 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.

Decoder yalnızca çöken programla birebir aynı derlemenin .elf dosyasıyla doğru sonuç verir. Kodda tek satır değiştirip yeniden derlersen adresler kayar ve çıktı yanlış satırları gösterir. Backtrace satırının sonunda CORRUPTED yazıyorsa yığın bozulmuştur; bu da genellikle bir yığın taşmasının ya da sınırını aşan bir tamponun işaretidir.

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.

PinDahili dirençAçılıştaki göreviYanlış seviyede ne olur?
GPIO0Pull-upLOW ise programlama (download) modu, HIGH ise normal açılışboot:0x3 (DOWNLOAD_BOOT) ve waiting for download; program çalışmaz
GPIO2Pull-downProgramlama moduna girmek için LOW ya da boşta olmalı; normal açılışta önemsizdirHIGH'a çeken bir devre kod yüklemeyi engeller
GPIO12 (MTDI)Pull-downFlaşın besleme gerilimini seçer: LOW 3,3 V, HIGH 1,8 VHIGH ise 3,3 V'luk flaş beslenemez; kart açılmaz ya da reset döngüsüne girer
GPIO15 (MTDO)Pull-upLOW ise ROM'un açılış mesajlarını sustururSeri Monitör'de açılış satırları görünmez, teşhis zorlaşır
GPIO5Pull-upSDIO zamanlamasını belirlerGeliştirme kartlarında nadiren sorun çıkarır
GPIO12'ye bağlı ve açılışta pini HIGH'a çeken bir pull-up direnci, röle ya da sensör modülü, ESP32'nin hiç açılmamasının en gizli sebebidir. Bu pini kullanmak zorundaysan modülün açılış anında pini LOW bıraktığından emin ol. Alternatif olarak esptool ile gelen espefuse.py set_flash_voltage 3.3V komutu flaş gerilimini eFuse'a kalıcı olarak yazar ve GPIO12'nin açılıştaki etkisini kaldırır; ancak bu işlem geri alınamaz ve yalnızca 3,3 V flaş kullanan modüllerde (ESP32-WROOM-32 gibi) yapılmalıdı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.

MicroPython
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

BelirtiOlası sebepÇözüm
Wi-Fi başlarken Brownout detector was triggeredKablo, port ya da regülatör tepe akıma yetişmiyorKı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 resetYük ESP32 ile aynı hattan besleniyorYükü ayrı 5 V kaynaktan besle, GND'leri birleştir
Pil biraz boşalınca resetler başlıyorAMS1117'nin düşüm gerilimiLDO ya da buck-boost dönüştürücü kullan
Guru Meditation, EXCVADDR 0x00000000Null pointerİşaretçiyi kullanmadan önce kontrol et
Stack canary watchpoint triggered (loopTask)loop() yığını dolduBü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 CPU1ISR çok uzunISR'de yalnız bayrak kaldır, IRAM_ATTR kullan
Kart sessiz, boot:0x3 ve waiting for downloadGPIO0 açılışta LOWGPIO0'a bağlı devreyi kaldır, EN'e bas
Kart hiç açılmıyor, flaş okuma hatasıGPIO12 açılışta HIGHGPIO12'deki pull-up'ı ya da modülü başka bir pine taşı
Kod yüklerken Failed to connect to ESP32GPIO2 HIGH ya da kart programlama moduna giremiyorGPIO2'yi boşalt, yükleme başlarken BOOT'a basılı tut
Teşhiste sırayı bozma: önce kabloyu ve güç kaynağını değiştir, sonra kondansatörü ekle, ardından servoları ve LED'leri ayrı besle. Brownout mesajı kaybolduktan sonra hâlâ reset oluyorsa teşhis kodundaki reset nedenine bak ve yazılım bölümlerine geç. Araçlar > Core Debug Level ayarını Verbose yaparsan ESP32 çekirdeği Wi-Fi ve sistem olaylarıyla ilgili çok daha ayrıntılı mesajlar yazar. Kod yükleme sorunları için Arduino'ya kod yüklenmiyor yazısına da göz atabilirsin.

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.

Tüm projeleri gör
ESP32 ile LED Yakma
#103Başlangıç

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.

4.7(37)
99
ESP32 Wi-Fi STA Bağlantısı (LCD Ekranlı)
#127İleri

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.

4.4(21)
34
ESP32 Servo Motor (Potansiyometre Kontrolü)
#118Orta
Premium

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.

4.3(29)
42
ESP32 WS2812B NeoPixel Şerit Kontrolü
#126Orta
Premium

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.

4.9(19)
30
ESP32 Async Web Server (LCD'de IP Göstergeli)
#129İleri

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.

4.8(16)
26
ESP32 Deep Sleep — Pil Tasarrufu (OLED + RTC RAM Sayaç)
#135İleri
Premium

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

4.3(10)
16
ESP32 OTA Update — Kablosuz Firmware Yükleme (LCD Ekranlı)
#132İleri
Premium

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

4.6(14)
22
ESP32 Hareket Alarm Sistemi (PIR + Buzzer + LED + Telegram)
#145İleri
Premium

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

0.0(0)
9