Arduino IDE'de Yükle (Upload) düğmesine bastınız, çıktıda "Connecting......" satırı belirdi ve birkaç saniye sonra yükleme "A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header" hatasıyla durdu. ESP32'ye kod yüklenmiyor, ama kod derlendiğine göre sorun yükleme aracıyla çip arasındaki bağlantıdadır. Çoğu zaman kart indirme modunda (download mode) değildir, yanlış port seçilmiştir ya da portu başka bir program tutmaktadır. Daha seyrek olarak bir çevre birimi strapping pinlerinden (çipin açılışta okuduğu yapılandırma pinleri) birini yanlış seviyeye çeker, USB sürücüsü eksiktir ya da kartın otomatik reset devresi güvenilir çalışmıyordur. Bu rehberde çözümleri izlemesi kolay bir sırayla ele alıyoruz: mesajın anlamı, beş dakikalık kontrol listesi, Windows, macOS ve Linux'ta port ve sürücüler, otomatik reset devresi, ESP32-S2/S3/C3/C6'da yerleşik USB, donanım ve yazılım kaynaklı nedenler, esptool ile komut satırından teşhis, belirti tablosu ve tasarım önerileri. Komutlar Arduino IDE, PlatformIO, ESP-IDF ve tek başına kullanılan esptool için geçerlidir.
Hata aslında ne söylüyor?
Arduino IDE, PlatformIO ve ESP-IDF yüklemeyi Espressif'in seri yükleme aracı esptool ile yapar. esptool sizin programınızla konuşmaz; çipin ROM'undaki önyükleyiciyle (bootloader) konuşur ve bu önyükleyici yalnızca çip indirme modunda açıldığında dinler. Çıktıda "Connecting..." görününce esptool kartı USB-seri çipin DTR ve RTS hatları üzerinden (ya da çipin kendi USB birimi üzerinden) resetler, senkronizasyon paketleri gönderir ve yanıt bekler. Birkaç denemeden sonra (güncel sürümlerde varsayılan olarak yedi deneme) vazgeçer ve "Failed to connect to" ifadesinin ardından çip adını ve son hata nedenini yazar. Geriye üç olasılık kalır: Çip indirme modunda değildir, seri bağlantı yanlıştır ya da çip beslenmiyor veya hiç açılmıyordur.Forumlara en sık yapıştırılan biçimler şunlar:
Code:
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
A fatal error occurred: Failed to connect to ESP32: No serial data received.
A fatal error occurred: Failed to connect to ESP32: Wrong boot mode detected (0x13)! The chip needs to be in download mode.
A fatal error occurred: Failed to connect to ESP32-S3: Download mode successfully detected, but getting no sync reply: The serial TX path seems to be down.
A fatal error occurred: Could not open COM5, the port is busy or doesn't exist.
(could not open port 'COM5': PermissionError(13, 'Access is denied.', None, 5))
Hint: Check if the port is not used by another task
could not open port /dev/cu.usbserial-0001: [Errno 16] Resource busy: '/dev/cu.usbserial-0001'
could not open port /dev/ttyUSB0: [Errno 13] Permission denied: '/dev/ttyUSB0'
Failed uploading: uploading error: exit status 2
Bu satırları şöyle okuyun:
- Timed out waiting for packet header ile No serial data received. aynı arızadır: Çipten tek bir geçerli bayt bile gelmemiştir. esptool 3.1 ve öncesi ilk metni, 3.2 ve sonrası ikinci metni yazar. İnternette ikisine de rastlarsınız; Arduino-ESP32'nin sorun giderme sayfası bile hâlâ eski metni alıntılar.
- Wrong boot mode detected (0x13) daha fazla bilgi verir. Çip resetlenmiş ve ROM açılış kaydını (boot log) yazmıştır, ama ROM'un indirme modunda kalmak yerine flash'tan açılmıştır (SPI_FAST_FLASH_BOOT). Klasik ESP32'de 0x13, normal flash açılışında genellikle görülen değerdir; sayı çipten çipe değişir. Sonuç değişmez: Çip resetten çıkarken GPIO0 (ESP32-C3/C6'da GPIO9) düşük seviyede değildi.
- Download mode successfully detected, but getting no sync reply, çipin indirme modunda beklediğini ama bilgisayarı duymadığını gösterir: Bilgisayarın TX'inden ESP'nin RX'ine giden hat kopuktur.
- Could not open, Access is denied, Resource busy ve Permission denied mesajları, esptool daha çipe ulaşmadan işletim sisteminden gelir. Karta değil; porta, sürücüye ve izinlere bakın.
- exit status 2 yalnızca IDE'nin, esptool'un hatayla durduğunu bildirmesidir. İşe yarayan bilgi bir üstteki satırdadır.
USB-UART köprüsü olan kartlarda bağımsız ve hızlı bir test yapabilirsiniz: Seri monitörü 115200 baud'da açın, BOOT'a basılı tutun ve EN'e kısaca basın. İndirme moduna giren klasik bir ESP32 şuna benzer bir çıktı verir:
Code:
rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download
"waiting for download" görüyorsanız çip, beslemesi ve ESP'den bilgisayara giden hat çalışıyor demektir; sorun reset zamanlamasında, yükleme sırasında portu tutan başka bir programda ya da bilgisayardan ESP'ye giden hattadır. Bunun yerine SPI_FAST_FLASH_BOOT görüyorsanız GPIO0 düşük değildi. Hiçbir şey görmüyorsanız portu, kabloyu, beslemeyi ve monitörün baud hızını kontrol edin. Yüklemeye geçmeden önce monitörü kapatın.
Beş dakikalık kontrol listesi
- Veri kablosu kullanın. Pek çok USB kablosu yalnızca şarj içindir, veri hatları yoktur. Kartı taktığınızda yeni bir port belirmiyorsa her şeyden önce kabloyu değiştirin ve masada veri taşıdığından emin olduğunuz bir kablo bulundurun.
- Doğru portu ve kartı seçin. Kartı çıkarın, port listesine bakın, yeniden takın: Listeye yeni eklenen port sizinkidir. Arduino IDE'de Araçlar (Tools) > Kart (Board) ayarını da kontrol edin (ESP32 Dev Module, ESP32S3 Dev Module, ESP32C3 Dev Module vb.).
- Portu serbest bırakın. Başka IDE pencerelerindeki seri monitörleri, PuTTY, screen ve minicom'u, kendi Python betiklerinizi ve portları tarayan yazılımları (örneğin USB'ye bağlı 3D yazıcı arayan dilimleyicileri) kapatın. Windows ve macOS'te bir seri portu aynı anda yalnızca bir program açabilir; Linux'ta ikinci bir program da portu açabilir, ama bu kez esptool'un beklediği yanıtları o yutar.
- İndirme moduna BOOT butonuyla elle geçin. BOOT'a (IO0 ya da FLASH olarak da etiketlenir) basılı tutun, EN'e (RST) basıp bırakın, ardından BOOT'u bırakın ve yüklemeyi başlatın. Kart yükleme başlarken indirme modundan çıkıyorsa sırayı tersine çevirin: Yüklemeyi başlatın, "Connecting..." belirir belirmez BOOT'a basın ve çip tipi ya da "Writing at 0x..." satırları görünene kadar basılı tutun.
- Yükleme hızını düşürün. Arduino IDE: Araçlar > Upload Speed > 115200. PlatformIO: upload_speed = 115200. esptool: -b 115200. esptool ilk teması 115200 baud'da (daha düşük bir değer seçtiyseniz o değerde) kurar ve yüksek hıza ancak sonra geçer; bu yüzden hızı düşürmek en çok bağlantı kurulup aktarım yarıda kesildiğinde işe yarar.
- USB portunu değiştirin ve çevre birimlerini sökün. Hub, dock ya da monitör üzerindeki portlar yerine doğrudan bilgisayarın portunu kullanın; kartın TX/RX, GPIO0, GPIO2, GPIO12 veya GPIO15 pinlerine bağlı ne varsa sökün (bunlar klasik ESP32 pinleridir; diğer çipler aşağıdaki strapping tablosunda).
ESP32 portu görünmüyor mu? Portlar ve USB-UART sürücüleri
ESP32 kartlarının çoğunda USB soketiyle çipin UART0 birimi arasında bir USB-UART köprü çipi bulunur. ESP32-S2, S3, C3 ya da C6 kullanan kartlar soketi doğrudan çipin USB pinlerine bağlayabilir; bazı kartlarda ikisi birden vardır. Hangi köprünün kullanıldığını soketin yanındaki küçük çipin üzerindeki yazıdan ya da USB kimliğinden (VID| Köprü | USB kimliği | Windows | macOS | Linux |
|---|---|---|---|---|
| Silicon Labs CP2102/CP2104 | 10c4:ea60 | Silicon Labs CP210x USB to UART Bridge (COMx) | /dev/cu.usbserial-XXXX ya da /dev/cu.SLAB_USBtoUART | /dev/ttyUSB0 |
| WCH CH340 | 1a86:7523 | USB-SERIAL CH340 (COMx) | /dev/cu.usbserial-XXXX ya da /dev/cu.wchusbserialXXXX | /dev/ttyUSB0 |
| WCH CH9102 | 1a86:55d4 | USB Serial Device (COMx); üretici sürücüsüyle WCH adı | /dev/cu.usbmodemXXXX ya da /dev/cu.wchusbserialXXXX | /dev/ttyACM0 |
| FTDI FT232R | 0403:6001 | USB Serial Port (COMx) | /dev/cu.usbserial-XXXX | /dev/ttyUSB0 |
| Yerleşik USB-Serial/JTAG (S3, C3, C6) | 303a:1001 | USB Serial Device (COMx) | /dev/cu.usbmodemXXXX | /dev/ttyACM0 |
Windows
Aygıt Yöneticisi'nde Bağlantı Noktaları (COM ve LPT) dalını açın ve kartı çıkarıp takarak hangi COM numarasının kaybolup geri geldiğine bakın. "Diğer aygıtlar" altında sarı ünlem işaretiyle görünen bir cihazın sürücüsü yüklenmemiştir. Windows Update CP210x ve CH340 sürücülerini çoğu zaman kendisi bulur. Bulamazsa üreticilerin kendi sayfalarını kullanın: Silicon Labs "CP210x USB to UART Bridge VCP Drivers" paketini yayımlar; WCH ise CH341SER (CH340/CH341 için) ve CH343SER (CH9102/CH343 için) paketlerini indirme sitesinde sunar. Üçüncü taraf indirme sitelerindeki sürücü paketlerinden uzak durun.macOS
Kartı takmadan önce ve taktıktan sonra ls /dev/cu.* komutunu çalıştırın ve tty.* yerine cu.* adını kullanın; cu aygıtı modemin taşıyıcı sinyalini beklemez. Yeni macOS sürümleri yaygın CP210x ve CH340 köprülerini çoğu zaman ek sürücü gerektirmeden tanır ve /dev/cu.usbserial-XXXX adını verir; yani Mac için ayrı bir CH340 sürücüsü aramanıza gerek kalmayabilir. Üretici sürücüleri /dev/cu.SLAB_USBtoUART ya da /dev/cu.wchusbserialXXXX gibi adlar oluşturur; yerleşik USB'li kartlar /dev/cu.usbmodemXXXX olarak görünür. Sistem Bilgileri > USB bölümünde üretici kimliğini (Vendor ID) görebilirsiniz. Bilinen bir tuzak: CH9102'li kartlar macOS'in yerleşik sürücüsüyle seri monitörde çalışır, ama yükleme "Failed to write to target RAM (result was 01070000: Operation timed out)" hatasıyla durabilir. Kullanıcı raporlarına göre WCH'nin macOS sürücüsünü kurup Gizlilik ve Güvenlik bölümünden onaylamak ya da yükleme hızını düşürmek sorunu çözüyor.Linux
CP210x, CH340 ve FTDI adaptörleri /dev/ttyUSB0, yerleşik USB'li kartlar ve CH9102 köprüleri ise /dev/ttyACM0 olarak görünür. Kartı takarken çekirdek günlüğünü izleyin, ardından aygıtı ve gruplarınızı kontrol edin:
Bash:
sudo dmesg -w
lsusb
ls -l /dev/ttyUSB* /dev/ttyACM*
groups
sudo usermod -a -G dialout $USER
Debian, Ubuntu ve Fedora'da port dialout grubuna aittir; Arch'ta bu grup uucp'dir (sudo usermod -a -G uucp $USER). Grup değişikliğinden sonra oturumu kapatıp yeniden açın. "Permission denied: '/dev/ttyUSB0'" tam olarak bu sorundur ve güncel esptool sürümleri grupla ilgili bir ipucu da yazar.
Otomatik reset devresi nasıl çalışır, bazı kartlar neden takılır?
Tipik bir geliştirme kartında köprünün DTR hattı GPIO0'ı (C3/C6'da GPIO9), RTS hattı ise çipin etkinleştirme pini EN'i iki transistör üzerinden sürer. İki hat aynı durumdayken transistör çifti EN'i serbest, GPIO0'ı ise yüksek bırakır; böylece portu açarken iki hattı birden etkinleştiren bir terminal programı çipi resetlemez. esptool EN'i yaklaşık 100 ms düşük tutar, ardından GPIO0'ı düşüğe çekerken EN'i bırakır ve GPIO0'ı yaklaşık 50 ms sonra (dönüşümlü denemelerde yaklaşık yarım saniye sonra) serbest bırakır. Çip strapping pinlerini EN yükseldikten hemen sonra okuyup kilitler. Sorun aradaki andadır: İki hat tam aynı anda değişmezse kısa bir süre aynı durumda kalır; bu sırada EN serbesttir, GPIO0 ise hâlâ yüksektir. Çip tam o anda resetten çıkarsa programınızı başlatır ve esptool "Wrong boot mode detected" hatası verir. esptool Linux ve macOS'te iki hattı tek bir çağrıyla değiştirebilir; Windows'ta ise onları art arda ayarlamak zorundadır.Espressif'in boot mode selection sayfası, bu devre kullanıldığında güvenilir reset için EN ile GND arasında 1-10 µF aralığında bir kondansatör gerektiğini, bazı üçüncü taraf kartların bu kondansatörü koymadığını ve bunun özellikle Windows'ta otomatik reseti güvenilmez kıldığını belirtir. Kondansatör EN'in yükselişini yavaşlatır; böylece iki hat yerine oturana kadar çip resette kalır. Arduino-ESP32'nin sorun giderme sayfası EN (RST) ile GND arasına 10 µF önerir. Her yüklemede BOOT'a basmak zorunda kalıyorsanız önce şemaya ya da EN butonunun çevresine bakın. Kondansatör yoksa bu aralıkta bir tane eklemek çoğu zaman işe yarar; elektrolitik ya da tantal kondansatörde eksi uç GND'ye gelir. Espressif'in donanım tasarım kılavuzu da temiz bir açılış için EN pininde RC gecikme devresi önerir; başlangıç değeri genellikle 10 kΩ ve 1 µF'tır.
Kartların ve klonların sorun çıkarmasının diğer nedenleri:
- Yalnızca TX, RX ve GND çıkışı olan bir USB-UART adaptöründe DTR/RTS yoktur, yani çipi resetleyecek bir şey de yoktur; butonları ya da GPIO0'dan GND'ye bir jumper kullanın.
- Yanlış yerleştirilmiş transistörler, EN'deki zayıf ya da eksik pull-up direnci veya DTR ile RTS'yi düzensiz gecikmelerle değiştiren bir köprü sürücüsü.
- Espressif'e göre Linux'ta seri portlar, bağlı bir program yokken varsayılan olarak RTS'yi etkin tutar ve bu durum bazı kartları reset döngüsünde bırakabilir. sudo stty -F /dev/ttyUSB0 -hupcl komutu bu davranışı kapatır.
Yerleşik USB'li ESP32-S2, S3, C3 ve C6
ESP32-S3, C3 ve C6'da USB-Serial/JTAG denetleyicisi bulunur: çipin USB pinleri üzerinde donanımla sabitlenmiş bir seri port ve JTAG arayüzü (S3: GPIO19 D-, GPIO20 D+; C3: GPIO18 D-, GPIO19 D+; C6: GPIO12 D-, GPIO13 D+). Bu denetleyici çipi indirme moduna kendisi geçirebilir ve bir COM portu, /dev/ttyACM0 ya da /dev/cu.usbmodem... olarak görünür. ESP32-S2'de yalnızca USB-OTG denetleyicisi vardır, S3'te ise ikisi birden bulunur. Arduino'da USB-OTG'yi programınızın içindeki TinyUSB yığını çalıştırır; dolayısıyla bu port ancak kodunuz USB yığınını çalışır durumda tuttuğu sürece vardır.Arduino IDE'nin Araçlar menüsünde önemli olan ayarlar:
- USB CDC On Boot: Enabled seçiliyse Serial çıktısı yerleşik USB portundan, Disabled seçiliyse UART0'dan gider. Kullandığınız sokete göre seçin.
- USB Mode (S3): "Hardware CDC and JTAG" sabit donanım denetleyicisini, "USB-OTG (TinyUSB)" yazılım yığınını kullanır.
- Upload Mode: S3'te "UART0 / Hardware CDC" ya da "USB-OTG CDC (TinyUSB)", S2'de "UART0" ya da "Internal USB". TinyUSB yükleme modunda IDE önce çalışan programdan önyükleyiciye geçmesini ister ("1200 bps touch" yöntemi); çökmüş bir program bunu yapamaz.
Espressif'in kendi kartları dâhil pek çok DevKit'te UART ve USB olarak etiketlenmiş iki soket bulunur. TinyUSB, USB tanımlayıcıları (descriptor) ya da uyku modlarıyla denemeler yaparken yüklemeyi UART soketinden yapın; bu yol firmware'inize bağlı değildir.
Donanım kaynaklı nedenler: strapping pinleri, besleme ve arızalı kartlar
Çip, nasıl açılacağına resetten çıktığı anda strapping pinlerinin seviyesine bakarak karar verir; bu pinlere bağlı her devre bu kararı etkiler:| Çip | İndirme modu koşulu | Reset anında dikkat |
|---|---|---|
| ESP32 | GPIO0 düşük | GPIO2 boşta ya da düşük; GPIO12 (MTDI) düşük olmalı, yüksekse flash için 1,8 V seçilir; GPIO15 (MTDO) düşükse ROM açılış kaydı susar; GPIO5 de strapping pinidir |
| ESP32-S2 | GPIO0 düşük | GPIO46 boşta ya da düşük; GPIO45 de strapping pinidir |
| ESP32-S3 | GPIO0 düşük | GPIO46 boşta ya da düşük; GPIO45 yüksekse VDD_SPI 1,8 V olur (bir eFuse sabitlemediyse); GPIO3 de strapping pinidir |
| ESP32-C3 | GPIO9 düşük | GPIO8 yüksek olmalı (GPIO8 = 0 ve GPIO9 = 0 geçersiz bir kombinasyondur); GPIO2'ye pull-up önerilir |
| ESP32-C6 | GPIO9 düşük | GPIO8 yüksek olmalı; GPIO4, GPIO5 ve GPIO15 de strapping pinidir |
Tablo Espressif'in esptool ve donanım tasarım belgelerine dayanır; seri üretime gidecek bir tasarımda çipinizin veri sayfasındaki (datasheet) "Strapping Pins" ya da "Boot Configurations" bölümünü mutlaka kontrol edin. Röle modülleri, GND'ye bağlı LED'ler, I2C pull-up dirençleri ve sensör çıkışları en sık karşılaşılan sorun kaynaklarıdır. Klasik örnek ilk ESP32'deki GPIO12'dir: Reset anında yüksekse flash beslemesi (VDD_SDIO) 1,8 V'a geçer ve ESP32-WROOM-32 gibi 3,3 V flash kullanan modüller flash'ı artık güvenilir biçimde okuyamaz. Yükleme başarısız olur ya da kart açılışta döngüye girer; forumlarda paylaşılan kayıtlarda çoğunlukla boot:0x33 ve ardından "flash read err, 1000" satırı görülür. O sinyali başka bir pine taşıyın. Son çare olarak ve yalnızca 3,3 V flash'lı modüllerde, espefuse set-flash-voltage 3.3V (v4'te set_flash_voltage) komutu gerilimi kalıcı olarak sabitler ve GPIO12 artık dikkate alınmaz. eFuse işlemleri geri alınamaz; önce modülün veri sayfasını okuyun.
Şunlara da bakın:
- UART0 pinleri: TX0/RX0 (klasik ESP32'de GPIO1/GPIO3) köprüyle paylaşılır. Bu pinlere bağlı bir GPS modülü, RS-485 dönüştürücü, ekran ya da ikinci bir mikrodenetleyici yüklemeyle çakışır.
- Besleme: esptool belgeleri 200-300 mA'lik akım tepelerinden söz eder. Zayıf bir USB portu, beslemesiz bir hub ya da uzun ve ince bir kablo gerilimin düşmesine (brownout) yol açar. Yükleme sırasında bu durum "Invalid head of packet" hatası ya da yarıda kesilen bir aktarım olarak, sonrasında ise seri monitörde "Brownout detector was triggered" mesajı olarak görünebilir.
- Pin karışıklığı: DevKitC tipi kartlarda CMD pini 5V'un yanındadır; Arduino-ESP32 belgeleri, kart pinlerden beslenirken bu pinin GND ile kolayca karıştırıldığı konusunda uyarır.
- Breadboard: esptool belgeleri breadboard'ların flash pinlerini kısa devre edebildiğini belirtir. Kartı breadboard dışında deneyin.
- Arızalı regülatör ya da kalitesiz klon: Multimetreyle ölçtüğünüzde 3V3 pini 3,3 V'a yakın, EN 3,3 V'a yakın (RST basılıyken 0 V), GPIO0 da 3,3 V'a yakın (BOOT basılıyken 0 V) olmalıdır. Isınan bir regülatör ya da 3,3 V'tan belirgin biçimde sapan bir 3V3 hattı, kartın onarılması veya değiştirilmesi gerektiğini gösterir.
Yazılım kaynaklı nedenler: kart ayarları, eski araçlar, Linux ve WSL
- Yanlış kart seçimi: "This chip is ESP32-S3, not ESP32. Wrong chip argument?" (esptool 5) ya da "This chip is ESP32 not ESP32-S2. Wrong --chip argument?" (esptool 4). Modülün üzerinde yazan çiple eşleşen kartı seçin.
- Flash modu ve boyutu: Yükleme tamamlanıyor ama hiçbir şey çalışmıyorsa Flash Mode'u DIO yapmayı deneyin, Flash Size'ı kontrol edin ve bir kez Erase All Flash Before Sketch Upload seçeneğini etkinleştirin. esptool belgelerine göre bazı cihazlar yalnızca dio modunu destekler; qio ile yazma başarılı görünse de çip flash'ı geri okuyamayabilir.
- Eski araçlar: Yeni çipler ve silikon revizyonları güncel bir esptool ve çekirdek ister. Arduino-ESP32'yi Kart Yöneticisi'nden (Boards Manager), PlatformIO'da espressif32 platformunu, ayrı kurduğunuz esptool'u da bir sanal ortamda (virtual environment) pip ile güncelleyin.
- Windows'ta güvenlik yazılımları: Bazı antivirüs ürünleri esptool.exe'yi karantinaya alabilir ya da COM portlarına erişimi engelleyebilir. Yükleme daha "Connecting..." aşamasına gelmeden eksik dosya hatasıyla düşüyorsa karantina listesine bakın.
- Ubuntu'da brltty: Bazı sürümlerde, özellikle 22.04'te, Braille ekranlar için çalışan brltty servisi CH340/CH341 adaptörlerini sahiplenir (Launchpad hata kaydı 1990189). dmesg çıktısında önce "usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1", ardından "ch341-uart converter now disconnected from ttyUSB0" satırı görünür. Braille ekran kullanmıyorsanız sudo apt remove brltty sorunu giderir. Kullanıyorsanız hata kaydının yorumlarındaki geçici çözümü uygulayın: /lib/udev/rules.d/85-brltty.rules dosyasını /etc/udev/rules.d/ altına kopyalayın, kopyadaki 1a86/7523 satırını silin, sudo udevadm control --reload komutunu çalıştırın ve adaptörü çıkarıp yeniden takın.
- ModemManager: esptool belgeleri bu servisi yeni seri portlarla konuşmaya çalışabilen bir Linux servisi olarak anar. Mobil modem kullanmıyorsanız servisi durdurarak (sudo systemctl stop ModemManager) bu olasılığı ortadan kaldırabilirsiniz.
- WSL 2: WSL varsayılan olarak USB cihazlarını görmez. Kartı usbipd-win ile paylaşın (Microsoft'un rehberi adımları anlatır) ya da yüklemeyi Windows tarafında COM portuyla yapın.
Code:
winget install usbipd
usbipd list
usbipd bind --busid 2-3
usbipd attach --wsl --busid 2-3 --auto-attach
esptool ile komut satırından teşhis
esptool'u doğrudan çalıştırmak, sorunun IDE'de mi donanımda mı olduğunu ayırt etmenizi sağlar. Arduino ve PlatformIO kendi esptool kopyalarıyla gelir; ayrı bir kopya için onu bir Python sanal ortamına kurun:
Bash:
python3 -m venv ~/esptool-venv
source ~/esptool-venv/bin/activate
python3 -m pip install --upgrade esptool
esptool version
esptool --port /dev/ttyUSB0 chip-id
esptool --port /dev/ttyUSB0 flash-id
esptool --port /dev/ttyUSB0 read-mac
esptool --port /dev/ttyUSB0 --trace chip-id
esptool --port /dev/ttyUSB0 --connect-attempts 0 chip-id
esptool --port /dev/ttyUSB0 erase-flash
esptool --port /dev/ttyUSB0 --baud 460800 write-flash 0x0 MySketch.ino.merged.bin
- Yazım farkı: esptool 5 tireli adlar kullanır (chip-id, flash-id, read-mac, erase-flash, write-flash, default-reset). esptool 4.x, eski IDE çıktıları ve eğitim içeriklerinin çoğu alt çizgili adları (chip_id, write_flash, default_reset) ve esptool.py adını kullanır. Sürüm 5 eski adları hâlâ kabul eder, ancak bunların ileride kaldırılacağını belirten bir uyarı (deprecation warning) verir. Emin değilseniz esptool --help (ya da esptool.py --help) çalıştırın ve listelenen adları kullanın.
- chip-id bağlanır; çip tipini, özelliklerini, kristal frekansını ve MAC adresini, ardından çip kimliğini yazar. Klasik ESP32 gibi çip kimliği olmayan çiplerde bunun yerine MAC adresini okur. Bu komut çalışıyor ama IDE başarısız oluyorsa IDE ayarlarına bakın.
- flash-id flash üreticisini, aygıt kimliğini ve algılanan boyutu okur. chip-id çalıştığı hâlde flash-id başarısız oluyorsa flash'tan ya da flash beslemesinden şüphelenin (GPIO12'yi hatırlayın).
- --trace gidip gelen her baytı ekrana döker; hiç yanıt gelmiyorsa donanım tarafına bakın: port, kablo, reset ya da besleme. --connect-attempts 0 denemeyi durmadan sürdürür ve butonlarla uğraşmanız için size zaman kazandırır.
- erase-flash kayıtlı Wi-Fi bilgileri ve NVS verileri dâhil her şeyi siler. Açılışta USB'yi kapatan bir programdan kurtulmanın yolu budur.
- write-flash 0x0 ...merged.bin: Güncel Arduino-ESP32 çekirdekleri derleme klasörüne bir .merged.bin dosyası da yazar: Önyükleyici, bölüm tablosu ve uygulama, flash boyutuna kadar 0xFF ile doldurulmuş tek bir imajda birleşir ve 0x0 adresine yazılır. Bu dolgu yüzünden NVS ve dosya sistemi verileri dâhil bütün çip yeniden yazılır; işlem, parçaları ayrı ayrı yazmaktan daha uzun sürer. Dosyaları ayrı ayrı yazacaksanız adresleri farklıdır: önyükleyici ESP32 ve ESP32-S2'de 0x1000, S3, C3 ve C6'da 0x0; bölüm tablosu 0x8000; Arduino'nun boot_app0.bin dosyası 0xe000; uygulama 0x10000.
PlatformIO'da port ve hızı platformio.ini dosyasında belirtin (Windows'ta upload_port = COM5):
INI:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
upload_port = /dev/ttyUSB0
upload_speed = 115200
monitor_speed = 115200
ESP-IDF'te portu ve düşük hızı açıkça verin, çünkü idf.py varsayılan olarak 460800 baud ile yazar. ESPPORT ve ESPBAUD ortam değişkenleri varsayılan değerleri belirler; monitörden Ctrl+] ile çıkılır:
Bash:
idf.py -p /dev/ttyUSB0 -b 115200 flash monitor
idf.py -p /dev/ttyUSB0 erase-flash
Belirti tablosu
| Mesaj ya da belirti | En olası neden | Çözüm |
|---|---|---|
| Timed out waiting for packet header / No serial data received. | İndirme modunda değil, yanlış port, kopuk RX/TX, besleme yok | BOOT + EN ile elle indirme moduna geçin, portu ve kabloyu kontrol edin, chip-id ile deneyin |
| Wrong boot mode detected (0x13)! | Otomatik reset GPIO0'ı erken bırakıyor ya da bir şey boot pinini yukarı çekiyor | Connecting... sırasında BOOT'u basılı tutun, EN kondansatörü ekleyin, GPIO0 ve GPIO2'yi boşaltın |
| Download mode successfully detected, but getting no sync reply | Bilgisayardan ESP'ye giden hat (ESP RX) kopuk | Adaptör TX'inden ESP RX'ine giden hattı kontrol edin, RX0'a bağlı cihazları sökün |
| Invalid head of packet / Serial data stream stopped | Gürültü, kötü kablo, breadboard, gerilim düşmesi | Daha iyi kablo, düşük baud ve güçlü besleme kullanın, kartı breadboard dışında deneyin |
| Could not open port / Access is denied / Resource busy | Portu başka bir program tutuyor | Monitörleri ve port tarayan yazılımları kapatın |
| Permission denied: '/dev/ttyUSB0' | Kullanıcı seri port grubunda değil | Kullanıcıyı dialout ya da uucp grubuna ekleyin, oturumu yeniden açın |
| Hiç port görünmüyor | Şarj kablosu, eksik sürücü, brltty, usbipd'siz WSL, çalışmayan yerleşik USB | Kabloyu değiştirin, üretici sürücüsünü kurun, brltty'yi kaldırın, usbipd kullanın, BOOT + RESET deneyin |
| This chip is ESP32-S3, not ESP32 | Yanlış kart seçili | Eşleşen kartı seçin |
| Failed to write to target RAM (result was 01070000: Operation timed out) | Kararsız sürücü ya da adaptör | Üretici sürücüsünü kurun (macOS'te CH9102), baud hızını düşürün, kısa kablo ve hub'sız bağlantı kullanın |
| Yükleme başarılı ama hiçbir şey çalışmıyor; açılış döngüsü ya da flash read err, 1000 | Flash modu ya da boyutu, GPIO12 yüksek, gerilim düşmesi | DIO modunu ve doğru flash boyutunu seçin, GPIO12'yi boşaltın, beslemeyi güçlendirin |
Önleme ve tasarım önerileri
- Her kartı portu ve köprü tipiyle etiketleyin; masada denenmiş bir veri kablosu bulundurun.
- Prototiplerde strapping pinlerini ve UART0'ı boş bırakın. Bir strapping pinini kullanmak zorundaysanız reset sırasında hiçbir şeyin sürmediği ya da çekmediği bir sinyal için kullanın ve veri sayfasındaki varsayılan seviyeyi kontrol edin.
- Kendi PCB'nizde BOOT ve EN butonlarını, Espressif'in DevKitC referans şemasındaki iki transistörlü otomatik reset devresini (ya da S3/C3/C6'da yerleşik USB pinlerine giden hattı), EN'de RC gecikmesini ve GPIO0'da (C3/C6'da GPIO9) harici bir pull-up direncini unutmayın. Bu pine büyük kondansatör koymayın; tasarım kılavuzu, aksi hâlde çipin indirme moduna girebileceği konusunda uyarır. TX, RX, EN, BOOT, 3V3 ve GND için test noktaları ekleyin ve ana besleme girişine ek bir 10 µF dâhil olmak üzere kılavuzun kondansatör önerilerine uyun.
- Sahadaki cihazlar için OTA güncellemeyi baştan planlayın; böylece sahada kimsenin USB kablosuna ihtiyacı kalmaz. IoT proje desenleri konumuz OTA'yı ve saha hata ayıklamasını anlatıyor; ESP32, STM32, Raspberry Pi ve RP2040 karşılaştırmamız ise baştan doğru kartı seçmenize yardımcı olur.
Sık sorulan sorular
Her yüklemede BOOT'a basmak zorunda mıyım?Hayır. Otomatik reset devresi sağlıklı çalışan bir kartta bunu esptool sizin yerinize yapar. Her seferinde butona basmanız gerekiyorsa otomatik reset sınırdadır (çoğunlukla EN kondansatörü eksiktir) ya da GPIO0'a bağlı bir şey ona karşı çalışıyordur. Buton geçici bir çözümdür; kodunuzda sorun olduğunu göstermez.
"Timed out waiting for packet header" ile "No serial data received" farklı hatalar mı?
Hayır. İkisi de aynı durumu anlatır; biri eski (3.1 ve öncesi), diğeri yeni (3.2 ve sonrası) esptool sürümlerinin metnidir: Çip hiç yanıt göndermemiştir. Aynı kontrol listesini uygulayın.
Başarısız bir yükleme ESP32'yi kullanılamaz hâle getirir mi?
Normal bir yüklemeyle hayır. Seri önyükleyici maske ROM'dadır ve normal bir yükleme onun üzerine yazamaz. İndirme modunu kapatan ya da kısıtlayan güvenlik eFuse'ları yakılmadığı sürece BOOT ve EN ile indirme moduna dönüp yeniden yükleme yapabilirsiniz. eFuse komutları ise ayrı bir konudur, çünkü kalıcıdır.
Hangi yükleme hızını kullanmalıyım?
Arduino-ESP32 çoğu kart için varsayılan olarak 921600 kullanır; iyi bir kablo ve köprüyle bu hız genellikle sorun çıkarmaz. Aktarım yarıda kesiliyorsa 460800 ya da 115200'e inin. Bağlantı hiç kurulamıyorsa 921600'den 115200'e inmek sonucu değiştirmez, çünkü ilk temas zaten 115200'de kurulur; esptool belgeleri, baud hızının sorun olmadığından emin olmak için -b 9600 ile denemeyi önerir.
ESP32-S3 ya da C3 kartımın portu yüklemeden sonra neden kayboluyor?
Yerleşik USB'de port çipin kendisine aittir. Yeni firmware TinyUSB'ye geçiyor (S3), USB pinlerini başka bir işe atıyor, derin uykuya giriyor ya da USB-OTG kullanırken USB başlamadan çöküyorsa port kaybolur. BOOT ve RESET ile indirme moduna geçin, beliren portu seçin ve düzeltilmiş programı yükleyin. Günlük çalışmada "Hardware CDC and JTAG" modu ya da UART soketi daha az sorun çıkarır.
Sonuç ve sonraki adımlar
"Failed to connect" hatası neredeyse her zaman bir kabloya, bir porta, bir butona ya da bir pine çıkar. Dıştan içe doğru ilerleyin: önce kablo ve port, sonra indirme modu, ardından sürücüler ve izinler, en son da kartın reset devresi ve strapping pinleri. Her mesajın ayrıntılı açıklaması için Espressif'in esptool sorun giderme sayfasına başvurabilirsiniz.- Yükleme çıktısındaki hata satırını ve esptool sürüm satırını olduğu gibi kopyalayın.
- Beş dakikalık kontrol listesini uygulayın, ardından esptool chip-id komutunu tek başına çalıştırın.
- chip-id yalnızca BOOT basılıyken çalışıyorsa otomatik reseti düzeltin (EN kondansatörü) ya da butonla çalışmaya devam edin.
- Kendi PCB'nizde her strapping pinini veri sayfasıyla karşılaştırın ve sonraki revizyona BOOT/EN butonlarıyla test noktaları ekleyin.
You press Upload, the output shows "Connecting......", and a few seconds later the upload stops with "A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header". The code compiled, so the failure is in the link between the flashing tool and the chip. Usually the board is not in download mode, the wrong port is selected or another program is holding the port. Less often a peripheral pulls a strapping pin the wrong way, the USB driver is missing or the board's reset circuit is marginal. This guide works through the fixes in a sensible order: what the message means, a five-minute checklist, ports and drivers on Windows, macOS and Linux, the auto-reset circuit, native USB on ESP32-S2/S3/C3/C6, hardware and software causes, command-line diagnosis with esptool, a symptom table and design tips. The commands apply to Arduino IDE, PlatformIO, ESP-IDF and standalone esptool.
What the error actually means
Arduino IDE, PlatformIO and ESP-IDF all flash through esptool, Espressif's serial flashing tool. esptool does not talk to your sketch. It talks to the bootloader in the chip's ROM, and that bootloader only listens when the chip starts in download mode. When "Connecting..." appears, esptool resets the board through the DTR and RTS lines of the USB-serial chip (or through the chip's own USB peripheral), sends sync packets and waits for a reply. After several attempts (seven by default in current versions) it gives up and prints "Failed to connect to", the chip name and the last reason. That leaves three possibilities: the chip is not in download mode, the serial link is wrong, or the chip is not powered or not starting at all.These are the variants people usually paste:
Code:
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
A fatal error occurred: Failed to connect to ESP32: No serial data received.
A fatal error occurred: Failed to connect to ESP32: Wrong boot mode detected (0x13)! The chip needs to be in download mode.
A fatal error occurred: Failed to connect to ESP32-S3: Download mode successfully detected, but getting no sync reply: The serial TX path seems to be down.
A fatal error occurred: Could not open COM5, the port is busy or doesn't exist.
(could not open port 'COM5': PermissionError(13, 'Access is denied.', None, 5))
Hint: Check if the port is not used by another task
could not open port /dev/cu.usbserial-0001: [Errno 16] Resource busy: '/dev/cu.usbserial-0001'
could not open port /dev/ttyUSB0: [Errno 13] Permission denied: '/dev/ttyUSB0'
Failed uploading: uploading error: exit status 2
How to read them:
- Timed out waiting for packet header and No serial data received. are the same failure: not one valid byte came back from the chip. esptool 3.1 and older print the first text, 3.2 and newer the second. You will find both online, partly because Arduino-ESP32's troubleshooting page still quotes the old wording.
- Wrong boot mode detected (0x13) tells you more. The chip did reset and printed its ROM boot log, but it booted from flash (SPI_FAST_FLASH_BOOT) instead of staying in the ROM's download mode. On the classic ESP32, 0x13 is the value a normal flash boot usually shows; the number differs between chips. Either way, GPIO0 (GPIO9 on ESP32-C3/C6) was not low when the chip came out of reset.
- Download mode successfully detected, but getting no sync reply means the chip is waiting in download mode but cannot hear the computer: the line from the computer's TX to the ESP's RX is broken.
- Could not open, Access is denied, Resource busy and Permission denied come from the operating system before esptool reaches the chip. Look at the port, the driver and permissions, not at the board.
- exit status 2 is only the IDE reporting that esptool stopped with an error. The useful line is the one above it.
A quick independent test on boards with a USB-UART bridge: open a serial monitor at 115200 baud, hold BOOT and tap EN. A classic ESP32 that enters download mode prints something like this:
Code:
rst:0x1 (POWERON_RESET),boot:0x3 (DOWNLOAD_BOOT(UART0/UART1/SDIO_REI_REO_V2))
waiting for download
If you see "waiting for download", the chip, its power and the ESP-to-computer line all work, and the problem lies in reset timing, in another program holding the port during the upload, or in the computer-to-ESP line. If you see SPI_FAST_FLASH_BOOT instead, GPIO0 was not low. If you see nothing, check the port, cable, power and the monitor's baud rate. Close the monitor before you upload.
Five-minute checklist
- Use a data cable. Many USB cables carry only power. If no new port appears when you plug the board in, swap the cable before anything else, and keep one cable on the bench that you know carries data.
- Pick the right port and board. Unplug the board, look at the port list, plug it back in: the port that appears is yours. In Arduino IDE also check Tools > Board (ESP32 Dev Module, ESP32S3 Dev Module, ESP32C3 Dev Module and so on).
- Free the port. Close serial monitors in other IDE windows, PuTTY, screen, minicom, your own Python scripts and anything that scans ports, such as slicers looking for USB-connected 3D printers. On Windows and macOS only one program can open a serial port at a time; on Linux a second program may open it as well, but it then swallows the replies esptool is waiting for.
- Enter download mode with the BOOT button. Hold BOOT (also labelled IO0 or FLASH), press and release EN (also labelled RST), release BOOT, then start the upload. If the board drops out of download mode when the upload starts, do it the other way round: start the upload, hold BOOT as soon as "Connecting..." appears, and release it when the chip type or "Writing at 0x..." lines show up.
- Lower the upload speed. Arduino IDE: Tools > Upload Speed > 115200. PlatformIO: upload_speed = 115200. esptool: -b 115200. esptool makes first contact at 115200 baud (or at your setting if it is lower) and only then switches to the faster rate, so this helps most when the connection succeeds and the transfer fails halfway.
- Change the USB port and unplug peripherals. Use a port on the computer itself rather than a hub, dock or monitor, and disconnect whatever is wired to the board's TX/RX, GPIO0, GPIO2, GPIO12 or GPIO15 (classic ESP32 pins; the strapping table below lists the other chips).
ESP32 not detected? Ports and USB-UART drivers
Most ESP32 boards carry a USB-UART bridge between the USB socket and the chip's UART0. Boards with an ESP32-S2, S3, C3 or C6 may instead wire the socket to the chip's own USB pins, and some have both. The marking on the small chip next to the socket, or the USB ID (VID| Bridge | USB ID | Windows | macOS | Linux |
|---|---|---|---|---|
| Silicon Labs CP2102/CP2104 | 10c4:ea60 | Silicon Labs CP210x USB to UART Bridge (COMx) | /dev/cu.usbserial-XXXX or /dev/cu.SLAB_USBtoUART | /dev/ttyUSB0 |
| WCH CH340 | 1a86:7523 | USB-SERIAL CH340 (COMx) | /dev/cu.usbserial-XXXX or /dev/cu.wchusbserialXXXX | /dev/ttyUSB0 |
| WCH CH9102 | 1a86:55d4 | USB Serial Device (COMx), or a WCH name with the vendor driver | /dev/cu.usbmodemXXXX or /dev/cu.wchusbserialXXXX | /dev/ttyACM0 |
| FTDI FT232R | 0403:6001 | USB Serial Port (COMx) | /dev/cu.usbserial-XXXX | /dev/ttyUSB0 |
| Native USB-Serial/JTAG (S3, C3, C6) | 303a:1001 | USB Serial Device (COMx) | /dev/cu.usbmodemXXXX | /dev/ttyACM0 |
Windows
Open Device Manager > Ports (COM & LPT) and replug the board to see which COM number comes and goes. A device under "Other devices" with a yellow warning sign has no driver. Windows Update often finds CP210x and CH340 drivers on its own. If it does not, use the vendors' own pages: Silicon Labs publishes the "CP210x USB to UART Bridge VCP Drivers", and WCH offers CH341SER (for CH340/CH341) and CH343SER (for CH9102/CH343) on its download site. Avoid driver bundles from third-party download sites.macOS
Run ls /dev/cu.* before and after plugging in, and use the cu.* name rather than tty.*, because the cu device does not wait for a modem carrier signal. Recent macOS versions often recognise the common CP210x and CH340 bridges without extra drivers and name them /dev/cu.usbserial-XXXX, so you may not need a separate CH340 driver for your Mac at all. Vendor drivers create names such as /dev/cu.SLAB_USBtoUART or /dev/cu.wchusbserialXXXX, and native USB boards appear as /dev/cu.usbmodemXXXX. System Information > USB shows the vendor ID. One known trap: CH9102 boards work with the built-in driver for the serial monitor, yet uploads stop with "Failed to write to target RAM (result was 01070000: Operation timed out)". Users report that installing WCH's macOS driver and approving it under Privacy & Security, or lowering the upload speed, fixes this.Linux
CP210x, CH340 and FTDI adapters appear as /dev/ttyUSB0; native USB boards and CH9102 bridges as /dev/ttyACM0. Watch the kernel log while you plug the board in, then check the device and your groups:
Bash:
sudo dmesg -w
lsusb
ls -l /dev/ttyUSB* /dev/ttyACM*
groups
sudo usermod -a -G dialout $USER
On Debian, Ubuntu and Fedora the port belongs to the dialout group; on Arch it is uucp (sudo usermod -a -G uucp $USER). Log out and back in after changing groups. "Permission denied: '/dev/ttyUSB0'" is exactly this problem, and current esptool versions print a hint about the group.
How the auto-reset circuit works, and why some boards fail
On a typical development board the bridge's DTR line drives GPIO0 (GPIO9 on C3/C6) and RTS drives EN, the chip enable pin, through two transistors. When both lines are in the same state, the pair leaves EN released and GPIO0 high, so a terminal program that asserts both lines when it opens the port does not reset the chip. esptool holds EN low for about 100 ms, then releases EN while pulling GPIO0 low, and lets GPIO0 go about 50 ms later (about half a second on alternate attempts). The chip latches its strapping pins just after EN goes high. The catch is the moment in between: if the two lines do not change at exactly the same instant, they briefly match, so EN is released while GPIO0 is still high. A chip that leaves reset in that moment boots your sketch, and esptool reports "Wrong boot mode detected". On Linux and macOS esptool can switch both lines in a single call; on Windows it has to set them one after the other.Espressif's boot mode selection page states that with this circuit a capacitor of 1-10 µF between EN and GND is needed for reliable resets, and that some third-party boards leave it out, which makes automatic reset unreliable, especially on Windows. The capacitor slows the rise of EN, so the chip stays in reset until the two lines have settled. Arduino-ESP32's troubleshooting page suggests 10 µF between EN (RST) and GND. If you have to hold BOOT for every upload, check the schematic or the area around the EN button first. Where there is no capacitor, adding one in that range often helps; with an electrolytic or tantalum part the negative side goes to GND. Espressif's hardware design guidelines also recommend an RC delay on EN for clean power-up, usually 10 kΩ and 1 µF as a starting point.
Other reasons boards and clones fail:
- A USB-UART adapter that brings out only TX, RX and GND has no DTR/RTS, so nothing can reset the chip; use the buttons or a jumper from GPIO0 to GND.
- Wrongly fitted transistors, a weak or missing pull-up on EN, or a bridge driver that switches DTR and RTS with uneven delays.
- Espressif notes that on Linux, serial ports assert RTS by default when nothing is attached, which can hold some boards in a reset loop. sudo stty -F /dev/ttyUSB0 -hupcl disables this.
ESP32-S2, S3, C3 and C6 with native USB
ESP32-S3, C3 and C6 include a USB-Serial/JTAG controller: a fixed hardware serial port and JTAG interface on the chip's USB pins (S3: GPIO19 D-, GPIO20 D+; C3: GPIO18 D-, GPIO19 D+; C6: GPIO12 D-, GPIO13 D+). It can put the chip into download mode by itself and appears as a COM port, /dev/ttyACM0 or /dev/cu.usbmodem.... The ESP32-S2 has only a USB-OTG controller, and the S3 has both. In Arduino, USB-OTG is driven by TinyUSB inside your sketch, so that port exists only while your code keeps the USB stack running.The Arduino IDE Tools menu entries that matter:
- USB CDC On Boot: Enabled sends Serial over the native USB port; Disabled sends it to UART0. Match it to the socket you use.
- USB Mode (S3): "Hardware CDC and JTAG" uses the fixed controller; "USB-OTG (TinyUSB)" uses the software stack.
- Upload Mode: on S3 "UART0 / Hardware CDC" or "USB-OTG CDC (TinyUSB)"; on S2 "UART0" or "Internal USB". In the TinyUSB upload mode the IDE first asks the running sketch to restart into the bootloader (the "1200 bps touch"), which a crashed sketch cannot do.
Many DevKits, Espressif's own included, have two sockets labelled UART and USB. While you experiment with TinyUSB, USB descriptors or sleep modes, upload through the UART socket; that path does not depend on your firmware.
Hardware causes: strapping pins, power and damaged boards
The chip samples its strapping pins at the moment it leaves reset, and anything wired to them takes part in that decision:| Chip | Download mode when | Watch at reset |
|---|---|---|
| ESP32 | GPIO0 low | GPIO2 floating or low; GPIO12 (MTDI) low, because high selects 1.8 V flash; GPIO15 (MTDO) low silences the ROM log; GPIO5 is also a strapping pin |
| ESP32-S2 | GPIO0 low | GPIO46 floating or low; GPIO45 is also a strapping pin |
| ESP32-S3 | GPIO0 low | GPIO46 floating or low; GPIO45 high selects 1.8 V VDD_SPI unless an eFuse fixes it; GPIO3 is also a strapping pin |
| ESP32-C3 | GPIO9 low | GPIO8 high (GPIO8 = 0 with GPIO9 = 0 is invalid); a pull-up on GPIO2 is recommended |
| ESP32-C6 | GPIO9 low | GPIO8 high; GPIO4, GPIO5 and GPIO15 are also strapping pins |
The table follows Espressif's esptool and hardware design documentation; for a production design, check the "Strapping Pins" or "Boot Configurations" chapter of your chip's datasheet. Relay modules, LEDs to GND, I2C pull-ups and sensor outputs are the usual culprits. The classic case is GPIO12 on the original ESP32: if it is high at reset, the flash supply (VDD_SDIO) switches to 1.8 V, and modules with 3.3 V flash, such as the ESP32-WROOM-32, can no longer read their flash reliably. Uploads fail or the board loops at boot; logs posted on forums often show boot:0x33 followed by "flash read err, 1000". Move that signal to another pin. As a last resort, and only on modules with 3.3 V flash, espefuse set-flash-voltage 3.3V (set_flash_voltage in v4) fixes the voltage permanently so that GPIO12 is ignored. eFuses cannot be undone, so read the module datasheet first.
Also check:
- UART0 pins: TX0/RX0 (GPIO1/GPIO3 on the classic ESP32) are shared with the bridge. A GPS module, RS-485 transceiver, display or second microcontroller on them competes with the upload.
- Power: esptool's documentation notes current peaks of 200-300 mA. A weak USB port, an unpowered hub or a long thin cable lets the voltage sag. During flashing it can show up as "Invalid head of packet" or a transfer that stops halfway; afterwards as "Brownout detector was triggered" in the serial monitor.
- Pin mix-ups: on DevKitC-style boards the CMD pin sits next to 5V, and Arduino-ESP32's documentation warns that it is easily confused with GND when the board is powered from its pins.
- Breadboards: esptool's documentation mentions breadboards shorting the flash pins. Test the board outside the breadboard.
- Damaged regulator or poor clone: with a multimeter, 3V3 should read close to 3.3 V, EN close to 3.3 V (0 V while RST is pressed) and GPIO0 close to 3.3 V (0 V while BOOT is pressed). A hot regulator or a 3V3 rail far from 3.3 V means the board needs repair or replacement.
Software causes: board settings, old tools, Linux and WSL
- Wrong board selected: "This chip is ESP32-S3, not ESP32. Wrong chip argument?" (esptool 5) or "This chip is ESP32 not ESP32-S2. Wrong --chip argument?" (esptool 4). Choose the board that matches the chip printed on the module.
- Flash mode and size: if the upload completes but nothing runs, try Flash Mode DIO, check Flash Size and enable Erase All Flash Before Sketch Upload once. esptool's documentation notes that some devices only support dio; a qio write can succeed while the chip cannot read the flash back.
- Outdated tools: newer chips and silicon revisions need a recent esptool and core. Update Arduino-ESP32 in Boards Manager, the espressif32 platform in PlatformIO, and a standalone esptool with pip inside a virtual environment.
- Security software on Windows: some antivirus products quarantine esptool.exe or block access to COM ports. If the upload fails before "Connecting..." with a missing-file error, check the quarantine list.
- brltty on Ubuntu: on some releases, notably 22.04, the braille display daemon brltty claims CH340/CH341 adapters (Launchpad bug 1990189). dmesg shows "usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1" followed by "ch341-uart converter now disconnected from ttyUSB0". If you do not use a braille display, sudo apt remove brltty fixes it. If you do, use the workaround from the bug comments instead: copy /lib/udev/rules.d/85-brltty.rules to /etc/udev/rules.d/, delete the 1a86/7523 line in the copy, run sudo udevadm control --reload and replug the adapter.
- ModemManager: esptool's documentation names it as a Linux service that may try to talk to new serial ports. If you do not use a mobile modem, stopping it (sudo systemctl stop ModemManager) rules it out.
- WSL 2: WSL does not see USB devices by default. Share the board with usbipd-win (the Microsoft guide walks through it), or run the upload on the Windows side with the COM port.
Code:
winget install usbipd
usbipd list
usbipd bind --busid 2-3
usbipd attach --wsl --busid 2-3 --auto-attach
Diagnosing from the command line with esptool
Running esptool directly shows whether the problem is the IDE or the hardware. Arduino and PlatformIO ship their own copy; for a standalone one, install it in a Python virtual environment:
Bash:
python3 -m venv ~/esptool-venv
source ~/esptool-venv/bin/activate
python3 -m pip install --upgrade esptool
esptool version
esptool --port /dev/ttyUSB0 chip-id
esptool --port /dev/ttyUSB0 flash-id
esptool --port /dev/ttyUSB0 read-mac
esptool --port /dev/ttyUSB0 --trace chip-id
esptool --port /dev/ttyUSB0 --connect-attempts 0 chip-id
esptool --port /dev/ttyUSB0 erase-flash
esptool --port /dev/ttyUSB0 --baud 460800 write-flash 0x0 MySketch.ino.merged.bin
- Spelling: esptool 5 uses hyphens (chip-id, flash-id, read-mac, erase-flash, write-flash, default-reset). esptool 4.x, older IDE logs and most tutorials use underscores (chip_id, write_flash, default_reset) and the esptool.py name. Version 5 still accepts the old names with a deprecation warning. If unsure, run esptool --help (or esptool.py --help) and use what it lists.
- chip-id connects and prints the chip type, features, crystal frequency and MAC, then the chip ID; on chips without one, such as the classic ESP32, it reads the MAC instead. If this works but the IDE fails, look at the IDE settings.
- flash-id reads the flash manufacturer, device ID and detected size. If chip-id works but flash-id fails, suspect the flash or its supply (remember GPIO12).
- --trace dumps every byte exchanged; if nothing ever comes back, look at the hardware side: port, wiring, reset or power. --connect-attempts 0 keeps retrying, which gives you time to work the buttons.
- erase-flash wipes everything, including saved Wi-Fi credentials and NVS data. It is the cure when a sketch keeps disabling USB at startup.
- write-flash 0x0 ...merged.bin: recent Arduino-ESP32 cores also write a .merged.bin to the build folder: bootloader, partition table and application in one image, padded with 0xFF up to the flash size, which goes to address 0x0. Because of the padding it rewrites the whole chip, including NVS and file-system data, and takes longer than flashing the parts. Separate files need their own offsets: bootloader at 0x1000 on ESP32 and ESP32-S2 or 0x0 on S3, C3 and C6, partition table at 0x8000, Arduino's boot_app0.bin at 0xe000 and the application at 0x10000.
In PlatformIO, set the port and speed in platformio.ini (on Windows, upload_port = COM5):
INI:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
upload_port = /dev/ttyUSB0
upload_speed = 115200
monitor_speed = 115200
In ESP-IDF, pass the port and a lower speed explicitly, because idf.py flashes at 460800 baud by default. The ESPPORT and ESPBAUD environment variables set defaults, and Ctrl+] exits the monitor:
Bash:
idf.py -p /dev/ttyUSB0 -b 115200 flash monitor
idf.py -p /dev/ttyUSB0 erase-flash
Symptom table
| Message or symptom | Most likely cause | Fix |
|---|---|---|
| Timed out waiting for packet header / No serial data received. | Not in download mode, wrong port, broken RX/TX, no power | BOOT + EN by hand, check port and cable, test with chip-id |
| Wrong boot mode detected (0x13)! | Auto-reset releases GPIO0 too early, or something pulls the boot pin high | Hold BOOT during Connecting..., add the EN capacitor, free GPIO0 and GPIO2 |
| Download mode successfully detected, but getting no sync reply | Computer-to-ESP line (ESP RX) broken | Check adapter TX to ESP RX, remove devices from RX0 |
| Invalid head of packet / Serial data stream stopped | Noise, poor cable, breadboard, brownout | Better cable, lower baud, stronger supply, test off the breadboard |
| Could not open port / Access is denied / Resource busy | Another program holds the port | Close monitors and port-scanning software |
| Permission denied: '/dev/ttyUSB0' | User not in the serial group | dialout or uucp group, then log in again |
| No port appears at all | Charge-only cable, missing driver, brltty, WSL without usbipd, native USB not running | Cable, vendor driver, remove brltty, usbipd, BOOT + RESET |
| This chip is ESP32-S3, not ESP32 | Wrong board selected | Select the matching board |
| Failed to write to target RAM (result was 01070000: Operation timed out) | Unstable driver or adapter | Vendor driver (CH9102 on macOS), lower baud, short cable, no hub |
| Upload succeeds but nothing runs; boot loop or flash read err, 1000 | Flash mode or size, GPIO12 high, brownout | DIO, correct size, free GPIO12, better power |
Prevention and design tips
- Label each board with its port and bridge type, and keep a tested data cable on the bench.
- Keep strapping pins and UART0 free on prototypes. If you must use a strapping pin, use it for a signal that nothing drives or pulls during reset, and check the default level in the datasheet.
- On custom PCBs, add BOOT and EN buttons, the two-transistor auto-reset from Espressif's DevKitC reference schematic (or route the native USB pins on S3/C3/C6), an RC delay on EN, and an external pull-up on GPIO0 (GPIO9 on C3/C6) with no large capacitor on that pin; the design guidelines warn that the chip may otherwise enter download mode. Add test pads for TX, RX, EN, BOOT, 3V3 and GND, and follow the guidelines' advice on bulk capacitance, including an extra 10 µF at the main power input.
- For devices in the field, plan OTA updates so that nobody needs a USB cable on site. Our IoT project patterns thread covers OTA and field debugging, and the ESP32 vs STM32 vs Raspberry Pi vs RP2040 comparison helps when you choose the board in the first place.
FAQ
Do I have to press BOOT for every upload?No. On a board with a working auto-reset circuit, esptool does it for you. If you need the button every time, the auto-reset is marginal (often a missing EN capacitor) or something on GPIO0 works against it. The button is a workaround, not a sign of a problem in your code.
Are "Timed out waiting for packet header" and "No serial data received" different errors?
No. They describe the same condition in older (3.1 and earlier) and newer (3.2 and later) esptool versions: the chip sent nothing back. Work through the same checklist.
Can a failed upload brick my ESP32?
Not through a normal upload. The serial bootloader lives in mask ROM, and a normal upload cannot overwrite it. As long as no security eFuses that disable or restrict download mode have been burned, you can return to download mode with BOOT and EN and flash again. eFuse commands are a different matter, because they are permanent.
Which upload speed should I use?
Arduino-ESP32 defaults to 921600 for most boards, which is usually fine with a good cable and bridge. If a transfer fails partway, drop to 460800 or 115200. Going from 921600 to 115200 does not help when there is no connection at all, because first contact already happens at 115200; esptool's documentation suggests -b 9600 as a test to rule out baud rate problems completely.
Why does my ESP32-S3 or C3 port disappear after an upload?
With native USB, the port belongs to the chip. If the new firmware switches to TinyUSB (S3), reconfigures the USB pins, enters deep sleep or, with USB-OTG, crashes before USB starts, the port goes away. Enter download mode with BOOT and RESET, select the port that appears and upload a fixed sketch. For everyday work, the "Hardware CDC and JTAG" mode or the UART socket is more forgiving.
Conclusion and next steps
"Failed to connect" nearly always comes down to a cable, a port, a button or a pin. Work from the outside in: cable and port first, then download mode, then drivers and permissions, and finally the board's reset circuit and strapping pins. Espressif's esptool troubleshooting page is the reference for each message.- Copy the exact error and the esptool version line from the upload output.
- Run the five-minute checklist, then esptool chip-id on its own.
- If chip-id only works with BOOT held, fix the auto-reset (EN capacitor) or keep using the button.
- On your own PCB, check every strapping pin against the datasheet and add BOOT/EN buttons and test pads to the next revision.