ESP32 не подключается к Wi-Fi? Коды WiFi.status() и рабочие решения
ESP32 не подключается к Wi-Fi? Разбираем WiFi.status() и коды причин, решаем проблемы с 2,4 GHz и паролем, просадками питания, setTxPower, переподключением, статическим IP и eduroam.
ESP32 не подключается к Wi-Fi, а монитор порта всё печатает и печатает точки? Почти никогда дело не в сломанной плате. Обычные подозреваемые: попытка подключиться к сети 5 GHz, крошечная опечатка в имени сети или пароле, слабое питание, которое проседает в момент включения Wi-Fi, настройки безопасности и канала на роутере или корпоративная сеть в школе или на работе. Хорошая новость: ESP32 уже сообщает, что пошло не так. Нужно только уметь читать значение WiFi.status() и код причины (reason), который она выдаёт при обрыве соединения.
В этом руководстве сначала разберём, через какие шаги проходит ESP32 при подключении к сети и какой код статуса она выдаёт на каждом из них. Дальше идут диагностический скетч, который печатает коды статуса и причины, сканер, показывающий сети вокруг, требование 2,4 GHz и двухдиапазонные роутеры, просадки питания и решение через setTxPower, скетч переподключения, который восстанавливает связь без твоего участия, статический IP, подключение к школьным сетям WPA2-Enterprise и тест с точкой доступа на телефоне, который за несколько минут показывает, в чём проблема: в роутере или в плате. Скетчи работают с версиями 2.x и 3.x ядра ESP32 для Arduino IDE, а в конце есть ещё тестовый скрипт для Raspberry Pi Pico W и MicroPython.

Как ESP32 подключается к сети Wi-Fi?
При вызове WiFi.begin() ESP32 в фоне выполняет четыре шага. Сначала она сканирует каналы в поисках сети с заданным именем (SSID). Если сеть нашлась, плата проходит аутентификацию и ассоциацию с роутером. В сетях WPA2 затем следует 4-этапное рукопожатие (4-way handshake): именно в этот момент становится ясно, верный ли пароль. Наконец, ESP32 запрашивает IP-адрес у DHCP-сервера роутера. WiFi.status() возвращает WL_CONNECTED только после того, как завершён и этот последний шаг. Если известно, на каком шаге всё застряло, причина по большей части тоже понятна:
| Шаг | Что происходит? | Статус и причина, если застряло |
|---|---|---|
| 1. Сканирование | ESP32 ищет имя сети на каналах 2,4 GHz | WL_NO_SSID_AVAIL (1), причина 201 |
| 2. Аутентификация и ассоциация | Роутер принимает или отклоняет ESP32 | WL_CONNECT_FAILED (4) или WL_DISCONNECTED (6), причина 202 или 203 |
| 3. 4-этапное рукопожатие | Сравниваются ключи, полученные из пароля | WL_DISCONNECTED (6) с причиной 15; WL_CONNECTION_LOST (5) с причиной 204 |
| 4. DHCP | Роутер выдаёт ESP32 IP-адрес | Зависает на WL_IDLE_STATUS (0) |
| После подключения | Роутер продолжает отправлять пакеты-маяки (beacon) | Если они пропадают: WL_CONNECTION_LOST (5), причина 200 |
Что означают коды WiFi.status()
WiFi.status() возвращает значение типа wl_status_t. Если вывести его прямо в монитор порта, видно только число. В таблице ниже показано, что означает каждое число в ядре ESP32 для Arduino. Внимание: значения от 0 до 6 называются так же, как в старой библиотеке Arduino WiFi, но на ESP32 появляются в немного других ситуациях. Например, сразу после WiFi.begin() статус равен 6, а не 0; он меняется на 0, когда плата подключилась к роутеру и ждёт IP, и на 3, когда IP получен.
| Код | Константа | Значение | Что проверить сначала |
|---|---|---|---|
| 0 | WL_IDLE_STATUS | Подключена к роутеру, но IP-адреса ещё нет | Несколько секунд это нормально; если затягивается, DHCP |
| 1 | WL_NO_SSID_AVAIL | Сеть с таким именем не найдена | Имя сети, диапазон 2,4 GHz, расстояние |
| 2 | WL_SCAN_COMPLETED | Сканирование сетей завершено | К подключению не относится |
| 3 | WL_CONNECTED | Подключена и имеет IP-адрес | Всё в порядке |
| 4 | WL_CONNECT_FAILED | Роутер отклонил подключение | Пароль, режим безопасности, MAC-фильтр |
| 5 | WL_CONNECTION_LOST | Установленное соединение оборвалось | Уровень сигнала, питание, антенна |
| 6 | WL_DISCONNECTED | Не подключена; попытка ещё идёт или не удалась | Код причины |
| 254 | WL_STOPPED | Станция Wi-Fi остановлена (ядро 3.x) | Вызови WiFi.mode(WIFI_STA) |
| 255 | WL_NO_SHIELD | Wi-Fi ещё не запущен (ядро 2.x) | Вызови WiFi.mode() или WiFi.begin() |
Диагностический скетч: вывод статуса и кода причины в монитор порта
Скетч ниже 20 секунд пытается подключиться, при каждом изменении статуса печатает его код с названием и при каждом обрыве соединения показывает код причины из ESP-IDF. Если подключение удалось, он выводит IP-адрес, шлюз, уровень сигнала (RSSI) и канал; в любом случае показывает и MAC-адрес платы. Замени имя сети и пароль на свои, загрузи скетч и открой монитор порта на скорости 115200 бод. Если скетч даже не загружается, сначала прочитай руководство об ошибках загрузки.
1#include <WiFi.h>
2
3const char* WIFI_ADI = "EvAgi_2G"; // Wi-Fi adı, büyük-küçük harfe duyarlı / network name, case-sensitive
4const char* WIFI_SIFRE = "sifre1234"; // Wi-Fi şifresi / Wi-Fi password
5
6// Durum kodunu adına çevir / turn the status code into its name
7const char* durumAdi(wl_status_t durum) {
8 switch (durum) {
9 case WL_IDLE_STATUS: return "WL_IDLE_STATUS";
10 case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL";
11 case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED";
12 case WL_CONNECTED: return "WL_CONNECTED";
13 case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED";
14 case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST";
15 case WL_DISCONNECTED: return "WL_DISCONNECTED";
16 default: return "WL_NO_SHIELD / WL_STOPPED";
17 }
18}
19
20// Bağlantı her koptuğunda sebep kodunu yaz / print the reason code on every disconnect
21void koptugunda(arduino_event_id_t olay, arduino_event_info_t bilgi) {
22 Serial.printf("Koptu / Disconnected, reason: %d\n", (int)bilgi.wifi_sta_disconnected.reason);
23}
24
25void setup() {
26 Serial.begin(115200);
27 delay(1000);
28 WiFi.onEvent(koptugunda, ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
29 WiFi.mode(WIFI_STA); // istasyon modu / station mode
30 WiFi.begin(WIFI_ADI, WIFI_SIFRE); // begin() yalnızca bir kez / call begin() only once
31
32 wl_status_t onceki = WL_NO_SHIELD;
33 unsigned long baslangic = millis();
34 while (WiFi.status() != WL_CONNECTED && millis() - baslangic < 20000) {
35 wl_status_t simdi = WiFi.status();
36 if (simdi != onceki) { // yalnızca değişince yaz / print only when it changes
37 Serial.printf("Durum / Status: %d %s\n", (int)simdi, durumAdi(simdi));
38 onceki = simdi;
39 }
40 delay(500);
41 }
42
43 if (WiFi.status() == WL_CONNECTED) {
44 Serial.print("Bagli / Connected, IP: ");
45 Serial.println(WiFi.localIP());
46 Serial.print("Ag gecidi / Gateway: ");
47 Serial.println(WiFi.gatewayIP());
48 Serial.printf("RSSI: %d dBm, kanal / channel: %d\n", (int)WiFi.RSSI(), (int)WiFi.channel());
49 } else {
50 wl_status_t son = WiFi.status();
51 Serial.printf("Baglanamadi / Failed, son durum / last status: %d %s\n", (int)son, durumAdi(son));
52 }
53 Serial.print("MAC: ");
54 Serial.println(WiFi.macAddress()); // MAC filtresi için / for MAC filtering
55}
56
57void loop() {}Сначала увидеть Durum / Status: 6 WL_DISCONNECTED нормально. Если подключение удаётся, статус ненадолго меняется на 0, а затем на 3. Если он остаётся равным 1, сеть так и не найдена; если одна за другой идут строки вроде Koptu / Disconnected, reason: 15, скорее всего, неверный пароль. Чтобы получить ещё больше подробностей, выбери в Arduino IDE Инструменты › Core Debug Level (Tools › Core Debug Level) значение Warn или Info: тогда ядро при каждом обрыве печатает и название причины, например Reason: 201 - NO_AP_FOUND. Вот коды причин, которые встречаются чаще всего:
| Причина | Название | Что это значит? | Решение |
|---|---|---|---|
| 2 | AUTH_EXPIRE | Истекло время аутентификации | Слабый сигнал или перегруженный роутер; подойди ближе, перезагрузи роутер |
| 5 | ASSOC_TOOMANY | Достигнут лимит клиентов роутера | Отключи ненужные устройства или увеличь лимит |
| 8 | ASSOC_LEAVE | ESP32 сама покинула сеть | Код вызывает WiFi.disconnect(); это нормально |
| 15 | 4WAY_HANDSHAKE_TIMEOUT | Не удалось завершить рукопожатие с паролем | Чаще всего неверный пароль; проверь его и режим безопасности |
| 200 | BEACON_TIMEOUT | Маяки от роутера перестали приходить | Слабый сигнал или просадка напряжения; антенна, питание, setTxPower |
| 201 | NO_AP_FOUND | Сеть с этим именем не найдена | Написание SSID, сеть 5 GHz, расстояние, скрытая сеть, каналы 12 и 13 |
| 202 | AUTH_FAIL | Аутентификация отклонена | Пароль или несовместимый режим безопасности, например Enterprise |
| 203 | ASSOC_FAIL | Роутер отклонил ассоциацию | MAC-фильтр или беспроводной режим вроде «только 802.11ax» |
| 204 | HANDSHAKE_TIMEOUT | Истекло время рукопожатия | Неверный пароль или очень слабый сигнал |
| 210, 211 | NO_AP_FOUND_W_COMPATIBLE_SECURITY, NO_AP_FOUND_IN_AUTHMODE_THRESHOLD | Сеть найдена, но её режим безопасности несовместим или ниже допустимого минимума (ядро 3.x) | Переключи роутер на WPA2-Personal (AES) или понизь минимум через WiFi.setMinSecurity() |
Требование 2,4 GHz: ESP32 не видит сети 5 GHz
Классическая ESP32, ESP32-S2, ESP32-S3, ESP32-C3 и ESP32-C6 работают только в диапазоне 2,4 GHz. Сеть, вещающую на 5 GHz, они при сканировании не видят никогда, и результат всегда WL_NO_SSID_AVAIL. Большинство домашних роутеров вещают в обоих диапазонах. Если у роутера для каждого диапазона своё имя (например, MyWiFi и MyWiFi_5G), всегда указывай ESP32 имя сети 2,4 GHz. Если у обоих диапазонов одно и то же имя (Smart Connect, band steering или mesh-системы), ESP32 обычно без проблем подключается к стороне 2,4 GHz, ведь сигнал 5 GHz она всё равно не видит. Проблемы начинаются, когда диапазон 2,4 GHz выключен или роутер пытается перевести клиентов на 5 GHz: ESP32 подключается, через несколько секунд отваливается, и всё повторяется по кругу. В таком случае раздели диапазоны в настройках роутера или создай гостевую сеть, которая вещает только на 2,4 GHz.
| Плата | Диапазон Wi-Fi | Примечание |
|---|---|---|
| ESP32 (WROOM-32, DevKit), ESP32-S2, ESP32-S3 | Только 2,4 GHz | 802.11 b/g/n |
| ESP32-C3 | Только 2,4 GHz | Дешёвым платам Super Mini может понадобиться пониженная мощность передатчика |
| ESP32-C6 | Только 2,4 GHz | Поддерживает Wi-Fi 6 (802.11ax), но всё равно только на 2,4 GHz |
| ESP32-C5 | 2,4 GHz и 5 GHz | Первый двухдиапазонный чип Espressif |
| ESP8266 (NodeMCU, Wemos D1 mini, ESP-01) | Только 2,4 GHz | 802.11 b/g/n |
| Raspberry Pi Pico W и Pico 2 W | Только 2,4 GHz | Беспроводной чип CYW43439 |
| Arduino Uno R4 WiFi | Только 2,4 GHz | За Wi-Fi отвечает встроенная ESP32-S3 |
Если диапазон верный, а сеть всё равно не находится, проверь настройки канала и режима на роутере. С региональной настройкой ESP32 по умолчанию каналы с 1 по 11 сканируются активно, а каналы 12 и 13 только прослушиваются пассивно. Видимые сети на этих каналах обычно всё же находятся, но скрытую сеть (вещание SSID выключено) на канале 12 или 13 ESP32 не найдёт. Самый надёжный вариант: переключить канал с автоматического на фиксированный 1, 6 или 11. Классическая ESP32, S2, S3 и C3 не могут подключиться к роутеру, настроенному только на 802.11ax (Wi-Fi 6); переключи режим на b/g/n или смешанный b/g/n/ax. По безопасности самые совместимые варианты: WPA2-Personal (AES) или смешанный режим WPA2/WPA3. По умолчанию ядро Arduino отклоняет всё, что слабее WPA2 (WEP и старый WPA-TKIP); если действительно нужно подключиться к очень старой сети, добавь WiFi.setMinSecurity(WIFI_AUTH_WEP) перед begin(). Прежде чем менять настройки, посмотри с помощью этого сканера, что на самом деле видит ESP32:
1#include <WiFi.h>
2
3// Güvenlik türünü yazıya çevir / turn the security type into text
4const char* guvenlikAdi(wifi_auth_mode_t tur) {
5 switch (tur) {
6 case WIFI_AUTH_OPEN: return "Acik / Open";
7 case WIFI_AUTH_WEP: return "WEP";
8 case WIFI_AUTH_WPA_PSK: return "WPA";
9 case WIFI_AUTH_WPA2_PSK: return "WPA2";
10 case WIFI_AUTH_WPA_WPA2_PSK: return "WPA/WPA2";
11 case WIFI_AUTH_WPA3_PSK: return "WPA3";
12 case WIFI_AUTH_WPA2_WPA3_PSK: return "WPA2/WPA3";
13 default: return "Diger / Other (Enterprise)";
14 }
15}
16
17void setup() {
18 Serial.begin(115200);
19 WiFi.mode(WIFI_STA);
20 WiFi.disconnect(); // temiz tarama için bağlantıyı kes / disconnect for a clean scan
21 delay(100);
22}
23
24void loop() {
25 Serial.println("Taraniyor / Scanning...");
26 int adet = WiFi.scanNetworks(); // engelleyen tarama, 2-4 sn / blocking scan, 2-4 s
27 if (adet <= 0) {
28 Serial.println("Ag bulunamadi / No networks found");
29 }
30 for (int i = 0; i < adet; i++) {
31 Serial.printf("%2d | %-32s | %4d dBm | kanal/ch %2d | %s\n",
32 i + 1, WiFi.SSID(i).c_str(), (int)WiFi.RSSI(i),
33 (int)WiFi.channel(i), guvenlikAdi(WiFi.encryptionType(i)));
34 }
35 WiFi.scanDelete(); // sonuçları bellekten sil / free the results
36 Serial.println();
37 delay(10000); // 10 sn sonra yeniden tara / scan again in 10 s
38}Если имени твоей сети вообще нет в списке, проблема возникает ещё до кода: сеть на 5 GHz, скрытая или ESP32 слишком далеко. Если имя есть, посмотри на его RSSI: от -30 до -60 dBm отлично, от -60 до -70 dBm хорошо; между -70 и -80 dBm плата подключается, но может терять связь, а ниже -80 dBm надёжного соединения не жди. Если одно и то же имя встречается несколько раз, у роутера или mesh-системы больше одной точки доступа. При быстром сканировании по умолчанию ESP32 подключается к первому найденному совпадению; если нужно, чтобы она выбирала самый сильный сигнал, добавь WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN) перед begin(). Скопируй имя ровно так, как оно показано в результатах сканирования, и вставь в скетч: это раз и навсегда исключает опечатки.
Ошибки в имени сети (SSID) и пароле
Если диагностический скетч сообщает причину 201 или 15, проблема обычно в двух строках кода. SSID может занимать до 32 байт, пароль WPA2 должен содержать от 8 до 63 символов, и оба чувствительны к регистру. Вот ошибки, которые чаще всего остаются незамеченными:
- Заглавные и строчные буквы: к сети, которая в роутере называется MyWiFi, не подключиться, если написать mywifi. То же правило действует для пароля.
- Невидимые пробелы: пробел в конце имени сети или пароля либо скрытый символ, попавший при копировании откуда-то, ломает совпадение.
- Специальные символы: буквы с диакритикой, кириллицу или символы в имени сети роутер может хранить в другой кодировке. Самое надёжное решение: переименовать сеть, используя только латинские буквы и цифры.
- Типографский апостроф: на iPhone имя точки доступа совпадает с именем телефона, и в нём часто стоит изогнутый ’ вместо прямого ' с клавиатуры, поэтому имя в коде не совпадает.
- Обратная косая черта и кавычки: если в пароле есть \ или ", в строке C++ их нужно записать как \\ и \"; иначе компилятор изменит пароль или скетч не скомпилируется.
- Открытая сеть: для подключения к сети без пароля пароль не указывается вовсе; достаточно WiFi.begin(имя). Если передать пароль для открытой сети, ядро ищет WPA2 и не находит сеть.
- Скрытая сеть: к сетям с выключенным вещанием SSID можно подключиться, указав точное имя, но при сканировании они не видны; если возникают трудности, на время тестов включи вещание.
Питание и просадка напряжения (brownout): почему плата перезагружается при запуске Wi-Fi?
Модуль ESP32 в среднем потребляет около 80 mA, но пока работает передатчик Wi-Fi, ток кратковременно подскакивает до 250–400 mA. Самые большие пики обычно бывают во время калибровки радио при старте и при первом подключении. Поэтому Espressif рекомендует источник питания, способный выдать не меньше 500 mA. Если источник не справляется с этими пиками, шина 3,3 V на мгновение проседает, срабатывает детектор просадки питания (brownout) в чипе, и плата перезагружается с сообщением Brownout detector was triggered в мониторе порта. Симптом очень знакомый: код нормально работает до строки с Wi-Fi, на WiFi.begin() плата сбрасывается, и всё превращается в бесконечный цикл. Эту ошибку мы подробно разбираем в статье об ошибках brownout и Guru Meditation на ESP32.

| Источник питания | Подходит? | Почему? |
|---|---|---|
| USB-порт на задней панели компьютера, короткий толстый кабель | Обычно да | Порт USB 2.0 выдаёт 500 mA; короткий кабель уменьшает потери напряжения |
| USB на передней панели, USB-хаб или длинный тонкий кабель | Может вызывать проблемы | Сопротивление кабеля и контактов роняет напряжение во время пиков тока |
| Зарядка для телефона на 5 V, не меньше 1 A | Да | Оставляет хороший запас для пиков тока |
| Пин 3.3V на Arduino Uno | Нет | Этот пин выдаёт всего около 50 mA |
| Li-ion аккумулятор 3,7 V напрямую на пин 5V платы | Нет | Из-за падения напряжения на AMS1117 выход опускается ниже 3 V |
| Li-ion аккумулятор с повышающим преобразователем на 5 V или стабилизатором 3,3 V с малым падением напряжения (LDO) | Да | Даёт стабильные 3,3 V даже по мере разряда аккумулятора |
| Выход 3,3 V модуля питания для макетной платы MB102 | Чаще всего да | Питай его от адаптера с достаточным током и добавь конденсатор |
Решение через setTxPower: снижение мощности передатчика
На некоторых платах даже при хорошем питании ESP32 видит сеть, но не может подключиться, или соединение постоянно рвётся. Особенно на дешёвых платах ESP32-C3 Super Mini и некоторых клонах ESP32 антенная цепь и стабилизатор не справляются с максимальной мощностью передатчика. По умолчанию ESP32 передаёт примерно на 19,5–20 dBm. Снижение мощности через WiFi.setTxPower() уменьшает пики тока и на таких платах часто сразу исправляет подключение. Вызывай её сразу после WiFi.begin(): до запуска Wi-Fi, то есть до WiFi.mode() или begin(), она не работает.
| Константа | Мощность | Когда использовать |
|---|---|---|
| WIFI_POWER_19_5dBm | 19,5 dBm | Близко к значению по умолчанию; максимальная дальность |
| WIFI_POWER_15dBm | 15 dBm | Первая попытка при небольших проблемах |
| WIFI_POWER_11dBm | 11 dBm | Обычно хватает, если роутер в той же комнате |
| WIFI_POWER_8_5dBm | 8,5 dBm | Значение, которое чаще всего советуют для ESP32-C3 Super Mini |
| WIFI_POWER_5dBm | 5 dBm | Для тестов прямо рядом с роутером |
Каждое снижение на 3 dB вдвое уменьшает мощность передатчика, так что дальность тоже сокращается. Начни с 15 dBm; если проблема остаётся, спустись до 11, а затем до 8,5 dBm. Если снижение мощности исправляет подключение, настоящая причина обычно в питании или конструкции антенны, поэтому в долгосрочной перспективе добавь ещё и более качественный источник питания с конденсатором. Текущую настройку платы можно прочитать через WiFi.getTxPower(); значение выражено в единицах 0,25 dBm, так что 78 означает 19,5 dBm.
Скетч автоматического переподключения
ESP32 теряет соединение, когда роутер перезагружается, когда после отключения возвращается электричество или когда сигнал на время пропадает. В ядре ESP32 WiFi.setAutoReconnect(true) включён по умолчанию, и после большинства обрывов плата подключается снова без посторонней помощи. Но при некоторых причинах, например 202 AUTH_FAIL, ядро сдаётся после одной повторной попытки, и плата остаётся без сети до сброса. Поэтому в проекте, который должен работать месяцами, стоит добавить собственную проверку. Скетч ниже обходится без delay() и с помощью millis() каждые 15 секунд проверяет соединение, переподключается, если оно оборвалось, и перезагружает плату, если подключиться не удаётся 5 минут:
1#include <WiFi.h>
2
3const char* WIFI_ADI = "EvAgi_2G"; // Wi-Fi adı / network name
4const char* WIFI_SIFRE = "sifre1234"; // Wi-Fi şifresi / Wi-Fi password
5
6const unsigned long KONTROL_ARALIGI = 15000; // 15 sn'de bir kontrol / check every 15 s
7const int EN_FAZLA_DENEME = 20; // 20 x 15 sn = 5 dk / 20 x 15 s = 5 min
8unsigned long sonKontrol = 0;
9int basarisizSayac = 0; // üst üste başarısız kontrol / consecutive failed checks
10
11void wifiBaslat() {
12 WiFi.mode(WIFI_STA);
13 WiFi.setAutoReconnect(true); // çekirdeğin kendi yeniden bağlanması / core auto-reconnect
14 WiFi.begin(WIFI_ADI, WIFI_SIFRE);
15 WiFi.setTxPower(WIFI_POWER_15dBm); // gerekirse 8_5dBm'e kadar düşür / lower to 8_5dBm if needed
16 WiFi.setSleep(false); // modem uykusunu kapat / disable modem sleep
17}
18
19void setup() {
20 Serial.begin(115200);
21 wifiBaslat();
22}
23
24void loop() {
25 if (millis() - sonKontrol >= KONTROL_ARALIGI) {
26 sonKontrol = millis();
27 if (WiFi.status() == WL_CONNECTED) {
28 basarisizSayac = 0;
29 Serial.printf("Bagli / Connected, IP: %s, RSSI: %d dBm\n",
30 WiFi.localIP().toString().c_str(), (int)WiFi.RSSI());
31 } else {
32 basarisizSayac++;
33 Serial.printf("Bagli degil / Not connected (%d/%d), yeniden baglaniyor / reconnecting\n",
34 basarisizSayac, EN_FAZLA_DENEME);
35 WiFi.disconnect();
36 WiFi.reconnect();
37 if (basarisizSayac >= EN_FAZLA_DENEME) {
38 Serial.println("Yeniden baslatiliyor / Restarting");
39 delay(100);
40 ESP.restart(); // son çare: kartı yeniden başlat / last resort: restart the board
41 }
42 }
43 }
44
45 // Projenin kodu buraya; uzun delay() kullanma / your project code here; avoid long delay()
46}Строка WiFi.setSleep(false) выключает modem sleep: режим, в котором ESP32 во время подключения периодически ненадолго выключает радио. С некоторыми роутерами это уменьшает обрывы, а на веб-сервере снижает задержку; взамен плата потребляет на несколько десятков mA больше. В проектах на батарейках эту строку можно убрать и рассчитать, сколько проработает батарея, в калькуляторе времени работы от батареи. Строку setTxPower оставляй, только если есть проблемы из предыдущего раздела. Добавляя код проекта в loop(), избегай долгих вызовов delay(), потому что проверка соединения выполняется только пока loop() крутится. Если удобнее вводить данные Wi-Fi с телефона, а не прописывать их в коде, посмотри библиотеку WiFiManager.
Настройка статического IP на ESP32
Обычно роутер выдаёт ESP32 адрес по DHCP, и он может каждый раз меняться. Если ты делаешь веб-сервер, который всегда будешь открывать с телефона по одному и тому же адресу, или DHCP роутера работает с ошибками (статус застревает на 0), жизнь упрощает статический IP. Запомни три правила: WiFi.config() нужно вызывать до WiFi.begin(); выбранный адрес должен быть в сети роутера, но вне его пула DHCP (если роутер раздаёт 192.168.1.2–100, бери что-то вроде 192.168.1.200); шлюз — это собственный адрес роутера. Чтобы узнать адрес роутера, один раз запусти диагностический скетч с DHCP: он печатает и шлюз.
1#include <WiFi.h>
2
3const char* WIFI_ADI = "EvAgi_2G"; // Wi-Fi adı / network name
4const char* WIFI_SIFRE = "sifre1234"; // Wi-Fi şifresi / Wi-Fi password
5
6IPAddress sabitIP(192, 168, 1, 200); // DHCP havuzunun dışında bir adres / an address outside the DHCP pool
7IPAddress agGecidi(192, 168, 1, 1); // modemin adresi / router address
8IPAddress altAgMaskesi(255, 255, 255, 0); // alt ağ maskesi / subnet mask
9IPAddress dns1(1, 1, 1, 1); // birinci DNS / primary DNS
10IPAddress dns2(8, 8, 8, 8); // ikinci DNS / secondary DNS
11
12void setup() {
13 Serial.begin(115200);
14 WiFi.mode(WIFI_STA);
15 // config() mutlaka begin()'den önce / config() must come before begin()
16 if (!WiFi.config(sabitIP, agGecidi, altAgMaskesi, dns1, dns2)) {
17 Serial.println("Statik IP ayarlanamadi / Static IP config failed");
18 }
19 WiFi.begin(WIFI_ADI, WIFI_SIFRE);
20
21 unsigned long baslangic = millis();
22 while (WiFi.status() != WL_CONNECTED && millis() - baslangic < 15000) {
23 delay(500);
24 Serial.print('.');
25 }
26 Serial.println();
27 Serial.print("IP: ");
28 Serial.println(WiFi.localIP()); // 192.168.1.200 olmalı / should be 192.168.1.200
29}
30
31void loop() {}Школьные и корпоративные сети: подключение к WPA2-Enterprise (eduroam)
eduroam в университетах, сети компаний и некоторые школьные сети используют WPA2-Enterprise (802.1X): вместо одного общего пароля у каждого пользователя свои логин и пароль. Обычный WiFi.begin(имя, пароль) в таких сетях всегда завершается неудачей, а в сканере их тип безопасности отображается как Diger / Other (Enterprise). Версии 2.x и 3.x ядра ESP32 для Arduino предлагают готовую форму begin() для PEAP, самого распространённого метода:
1#include <WiFi.h>
2
3const char* AG_ADI = "eduroam"; // kurum ağının adı / enterprise network name
4const char* EAP_KIMLIK = "[email protected]"; // kimlik, çoğu zaman kullanıcı adıyla aynı / identity, usually same as username
5const char* EAP_KULLANICI = "[email protected]"; // kullanıcı adı / username
6const char* EAP_SIFRE = "kurum_sifren"; // kurum şifresi / enterprise password
7
8void setup() {
9 Serial.begin(115200);
10 WiFi.disconnect(true); // önceki bağlantıyı kapat / close any previous connection
11 WiFi.mode(WIFI_STA);
12 // PEAP (MSCHAPv2) ile bağlan, CA doğrulaması yok / connect with PEAP (MSCHAPv2), no CA check
13 WiFi.begin(AG_ADI, WPA2_AUTH_PEAP, EAP_KIMLIK, EAP_KULLANICI, EAP_SIFRE);
14
15 unsigned long baslangic = millis();
16 while (WiFi.status() != WL_CONNECTED && millis() - baslangic < 30000) {
17 delay(500);
18 Serial.print('.');
19 }
20 Serial.println();
21 if (WiFi.status() == WL_CONNECTED) {
22 Serial.print("Bagli / Connected, IP: ");
23 Serial.println(WiFi.localIP());
24 } else {
25 Serial.printf("Baglanamadi / Failed, durum / status: %d\n", (int)WiFi.status());
26 }
27}
28
29void loop() {}В большинстве организаций identity (идентификатор) совпадает с именем пользователя; некоторые требуют анонимный внешний идентификатор вроде [email protected]. Этот скетч не проверяет сертификат сервера (CA): соединение работает, но поддельная точка доступа может перехватить пароль. Поэтому, прежде чем записывать личный пароль в ESP32, посоветуйся с ИТ-отделом и по возможности попроси учётную запись или сеть для устройств. Если организация требует сертификат, CA-файл можно передать шестым параметром begin(). Сети, которые открывают страницу входа в браузере (captive portal), как в отелях, общежитиях и кафе, — отдельная проблема: ESP32 не умеет заполнять такую страницу. Некоторые школы также требуют заранее регистрировать MAC-адреса устройств; отправь в ИТ-отдел MAC-адрес, который печатает диагностический скетч. В таких сетях самое практичное решение: точка доступа на телефоне или маленький карманный роутер.
Тест с точкой доступа на телефоне: виноват роутер или ESP32?
Быстрее всего сузить круг причин, подключив ESP32 к сети, настройки которой полностью под твоим контролем. Точка доступа на телефоне идеально для этого подходит:
- Дай точке доступа короткое имя только из латинских букв и цифр (например, esptest) и задай простой пароль не короче 8 символов (например, test12345).
- На Android в настройках точки доступа выбери диапазон (на некоторых телефонах пункт называется «Диапазон точки доступа» или «Скорость и совместимость») 2,4 GHz, а в качестве типа защиты WPA2-Personal.
- На iPhone открой Настройки › Режим модема (Settings › Personal Hotspot) и включи Разрешать другим (Allow Others to Join). На новых моделях включи ещё Максимальная совместимость (Maximize Compatibility): это переводит точку доступа на 2,4 GHz. Имя точки доступа совпадает с именем телефона, поэтому упрости его в Настройки › Основные › Об этом устройстве › Имя и держи экран «Режим модема» открытым, пока ESP32 не подключится.
- Замени имя сети и пароль в диагностическом скетче на данные точки доступа, положи телефон в 1–2 м от ESP32 и загрузи скетч.
- Прочитай коды статуса и причины в мониторе порта, а затем попробуй тот же скетч с данными домашнего роутера.
Результат толкуй так: если ESP32 подключается к точке доступа, но не к домашнему роутеру, с кодом, платой и питанием всё в порядке; проблема в настройках роутера: диапазоне, канале, безопасности, MAC-фильтре или лимите клиентов. Если к точке доступа подключиться тоже не удаётся, проблема на стороне ESP32: смени источник питания и кабель, снизь мощность через setTxPower, убедись, что перед антенной нет металла, и ещё раз проверь код. Тест с точкой доступа также самый быстрый способ доказать, что проект, который не подключается в школе, на самом деле работает.
Тест Wi-Fi на Raspberry Pi Pico W и MicroPython
Raspberry Pi Pico W и Pico 2 W тоже поддерживают только 2,4 GHz; все советы этой статьи про диапазон, пароль, питание и точку доступа относятся и к этим платам. В MicroPython коды статуса читаются через константы модуля network. Скрипт ниже без изменений работает в Thonny и на ESP32, и на Pico W. На Pico W он сразу прекращает ожидание, если сеть не найдена или пароль неверный; на ESP32 MicroPython после некоторых ошибок продолжает попытки, поэтому через 20 секунд скрипт печатает последний статус:
1import network, time
2
3AG_ADI = "EvAgi_2G" # Wi-Fi adı / network name
4SIFRE = "sifre1234" # Wi-Fi şifresi / Wi-Fi password
5
6wlan = network.WLAN(network.STA_IF)
7wlan.active(True)
8if wlan.isconnected():
9 wlan.disconnect() # eski bağlantıyı kapat / close the previous connection
10 time.sleep(1)
11wlan.connect(AG_ADI, SIFRE)
12
13durum = wlan.status()
14for saniye in range(20): # en fazla 20 sn bekle / wait up to 20 s
15 durum = wlan.status()
16 print(saniye, "durum / status:", durum)
17 if durum in (network.STAT_GOT_IP, network.STAT_NO_AP_FOUND, network.STAT_WRONG_PASSWORD):
18 break # sonuç belli, beklemeyi bırak / result is known, stop waiting
19 time.sleep(1)
20
21if durum == network.STAT_GOT_IP:
22 print("Bagli / Connected, IP:", wlan.ifconfig()[0])
23 print("RSSI:", wlan.status("rssi"), "dBm")
24elif durum == network.STAT_NO_AP_FOUND:
25 print("Ag bulunamadi / Network not found (SSID, 2.4 GHz)")
26elif durum == network.STAT_WRONG_PASSWORD:
27 print("Sifre yanlis / Wrong password")
28else:
29 print("Baglanamadi / Failed, durum / status:", durum)На Pico W числовые значения статуса другие: 3 означает «подключено, IP получен», 2 — «подключено, ждёт IP», -1 — общая ошибка, -2 — сеть не найдена, а -3 — неверный пароль. На ESP32 вместо этого во время подключения будет 1001, после получения IP 1010, а при проблемах коды причин ESP-IDF вроде 201 и 202. Чтобы на Pico W не было проблем с каналами 12 и 13, перед подключением укажи код страны (rp2.country('GB') или на новых прошивках network.country('GB'), подставив свою страну); если соединение время от времени рвётся, энергосбережение можно выключить через wlan.config(pm=0xa11140). Как сделать веб-сервер на Pico W, смотри в статье Веб-сервер Wi-Fi на Pico W, а если MicroPython для тебя в новинку, загляни в руководство Основы MicroPython.
Частые проблемы и решения
| Симптом | Вероятная причина | Решение |
|---|---|---|
| Мусорные символы в мониторе порта | Не совпадает скорость (бод) | Выставь в мониторе порта 115200 бод |
| Статус 1, причина 201 | Неверное имя сети, сеть 5 GHz или слишком далеко | Запусти сканер и точно скопируй имя сети 2,4 GHz |
| Статус 6, причина 15 снова и снова | Неверный пароль | Введи пароль заново, следя за регистром и специальными символами |
| Статус 4 или 6; причина 202, 210 или 211 | Несовместимый режим безопасности | Переключи роутер на WPA2-Personal (AES) или смешанный WPA2/WPA3 |
| Застревает на статусе 0 | Подключена к роутеру, но не получает IP по DHCP | Перезагрузи роутер, расширь пул DHCP или используй статический IP |
| Сброс на WiFi.begin() с сообщением Brownout detector was triggered | Источник питания не справляется с пиками тока | Короткий кабель, адаптер не меньше 1 A, 470 µF между 3V3 и GND |
| Подключается, а через несколько минут отваливается (причина 200) | Слабый сигнал, modem sleep или проблема с питанием | setSleep(false), setTxPower, скетч переподключения, ближе к роутеру |
| На столе работает, в корпусе не подключается | Металлический корпус или аккумулятор перед антенной | Размести антенну у края корпуса, наружу, используй пластиковый корпус |
| Подключено, но веб-страница не открывается на телефоне | Телефон в другой сети или в гостевой сети включена изоляция клиентов | Подключи оба устройства к одной сети и возьми IP из монитора порта |
| Значения analogRead() портятся при включённом Wi-Fi | Датчик на пине ADC2, а Wi-Fi использует ADC2 | Перенеси датчик на пины ADC1, GPIO 32–39 |
| Дальность в несколько сантиметров на ESP32-CAM или плате с внешней антенной | Выбрана внешняя антенна, но она не подключена | Подключи антенну к разъёму IPEX или проверь резистор 0 Ω выбора антенны на плате |
Подключение есть: что теперь можно собрать?
- Веб-сервер и живая панель: сделай веб-сервер на ESP32 с WebSocket, который в реальном времени показывает значения датчиков на телефоне.
- Интернет-часы: получай время с NTP-сервера и выводи его на дисплей.
- Погодный дисплей: получай температуру и влажность в своём городе через погодный API.
- Уведомления на телефон: отправляй сообщение через Telegram-бота, когда открывается дверь.
- Умный дом: подключи ESP32 к Home Assistant через MQTT.
- Связь без роутера: пусть две платы ESP32 общаются по ESP-NOW, не подключаясь ни к какой сети.
- Беспроводная загрузка: когда плата уже запечатана в корпусе, отправляй новый код по Wi-Fi с помощью обновления OTA.
ESP32, которая не подключается к Wi-Fi, поначалу сбивает с толку, но коды статуса и причины всегда подсказывают, на каком шаге проблема: 1 и 201 означают, что сеть не найдена, 15 и 202 указывают на пароль или режим безопасности, 0 на DHCP, а 200 или внезапные перезагрузки на сигнал или питание. Если ESP32 для тебя в новинку, основы найдёшь в статье Что такое ESP32?. В приложении BlueGrays есть и проекты вроде подключения ESP32 к Wi-Fi, веб-сервера, mDNS, часов с NTP, метеостанции, обновления OTA и сигнализации в Telegram, каждый с пошаговыми схемами подключения и готовым кодом.
Частые вопросы
Почему ESP32 не подключается к Wi-Fi?
Самые частые причины: попытка подключиться к сети 5 GHz, опечатка в имени сети или пароле, слабое питание, напряжение которого проседает при запуске Wi-Fi, и настройки безопасности роутера. Выведи значение WiFi.status() и код причины, который приходит при обрыве, и сразу станет видно, что именно. Если сеть не найдена, будут 1 и 201; при неверном пароле обычно 6 и 15.
Может ли ESP32 подключиться к Wi-Fi 5 GHz?
Классическая ESP32, ESP32-S2, S3, C3 и C6 поддерживают только 2,4 GHz и при сканировании никогда не видят сети 5 GHz. Двухдиапазонная модель — ESP32-C5. Если роутер вещает два диапазона под разными именами, укажи ESP32 имя сети 2,4 GHz.
Что означает WiFi.status() 6 на ESP32?
6 означает WL_DISCONNECTED: плата не подключена, а попытка подключения либо ещё идёт, либо не удалась. На ESP32 неверный пароль часто даёт это значение вместо 4 (WL_CONNECT_FAILED). Чтобы увидеть настоящую причину, проверь код причины в событии ARDUINO_EVENT_WIFI_STA_DISCONNECTED.
Почему ESP32 постоянно отключается от Wi-Fi?
Основные причины повторяющихся обрывов: слабый сигнал, питание, которое не справляется с пиками тока Wi-Fi, металл или аккумулятор перед антенной и настройки band steering на роутере. Поставь плату ближе к роутеру, добавь конденсатор 100–470 µF между 3V3 и GND и выключи modem sleep через WiFi.setSleep(false). И напиши код так, чтобы он восстанавливался после обрыва соединения без посторонней помощи.
Может ли ESP32 подключиться к точке доступа на телефоне?
Да, если точка доступа вещает на 2,4 GHz. На Android выбери для точки доступа диапазон 2,4 GHz, на iPhone включи «Максимальная совместимость» и оставь имя точки доступа простым. Тест с точкой доступа быстрее всего показывает, в чём проблема: в домашнем роутере или в ESP32.
Может ли ESP32 подключиться к eduroam или школьной сети?
ESP32 может подключаться к сетям WPA2-Enterprise вроде eduroam с помощью формы WiFi.begin(name, WPA2_AUTH_PEAP, identity, username, password) из ядра ESP32 для Arduino. Но в сетях, которые открывают страницу входа в браузере (captive portal), ESP32 не может заполнить эту страницу. Перед использованием сети организации лучше посоветоваться с ИТ-отделом и по возможности попросить отдельную учётную запись для устройств.
Что собрать после прочтения
Все проекты
Подключение ESP32 к Wi-Fi в режиме STA (с экраном LCD)
В этом проекте ESP32 надёжно и устойчиво к сбоям подключается к домашней сети Wi-Fi в режиме станции (STA). SSID и пароль хранятся в отдельном файле secrets.h, чтобы не утекли в Git; настроено автоматическое переподключение, а уровень сигнала RSSI и IP-адрес выводятся на I2C LCD-экран. Встроенный светодиод служит индикатором состояния. Это менеджер подключения уровня реальных устройств.

Асинхронный веб-сервер на ESP32 (с выводом IP на LCD)
В этом проекте ESP32 превращается в асинхронный веб-сервер, которым можно управлять с телефона или компьютера в той же сети Wi-Fi. Благодаря библиотеке ESPAsyncWebServer сервер может обрабатывать несколько запросов одновременно (в отличие от классического WebServer.h, который блокируется на одном запросе). Открыв IP-адрес ESP32 в браузере, ты нажимаешь кнопки ON/OFF (маршруты /on и /off) и включаешь и выключаешь светодиод на GPIO 5.

mDNS на ESP32: доступ к устройству через bluegrays-esp.local (с экраном LCD)
В этом проекте к ESP32 добавляется служба mDNS (Multicast DNS), и к устройству можно обращаться по понятному имени вроде bluegrays-esp.local вместо IP-адреса. Даже если IP, выданный DHCP, меняется, устройство всегда доступно по одному имени. На устройстве также работает маленький веб-сервер, через который по адресу http://bluegrays-esp.local/ из браузера отправляются команды светодиоду. I2C LCD показывает имя хоста, IP-адрес и состояние светодиода.

Точное время из интернета через NTP на ESP32
ESP32 подключается к Wi-Fi и получает точное время с точностью до миллисекунд от серверов NTP (Network Time Protocol). Благодаря функции configTzTime() автоматически применяется часовой пояс Турции (TRT, UTC+3), а в странах с летним временем переходы обрабатываются автоматически по строке POSIX TZ. Время выводится в монитор порта и на необязательный I2C LCD. configTzTime() запускает службу SNTP, которая периодически пересинхронизирует часы.

ESP32 HTTPClient + API погоды (с экраном LCD)
В этом проекте ESP32 через HTTPClient.h делает вызов REST API к сервису погоды (wttr.in) через интернет. Полученный ответ в JSON разбирается с помощью ArduinoJson v7, а город, температура, влажность, погода и ветер выводятся на I2C LCD на турецком и английском. wttr.in бесплатен и не требует ключа API — достаточно указать любое название города, чтобы получить текущую погоду. Данные автоматически обновляются каждые 30 минут.

Обновление ESP32 по воздуху (OTA): беспроводная установка прошивки (с экраном LCD)
В этом проекте ты узнаешь, как загружать новую прошивку в ESP32 по Wi-Fi без USB-кабеля. С библиотекой ArduinoOTA ESP32 становится видна в сети и автоматически появляется как bluegrays-ota на вкладке «Сетевой порт» в Arduino IDE. Первая загрузка выполняется по USB, а все следующие обновления — без проводов: это важно для устройств в эксплуатации. I2C LCD показывает состояние Wi-Fi, IP-адрес, имя хоста, процент загрузки OTA и сообщения об ошибках.

Счётчик на WebSocket с ESP32 (2 кнопки + LCD + веб в реальном времени)
В этом проекте две кнопки, подключённые к ESP32 (GPIO 5 увеличивает, GPIO 4 уменьшает), меняют счётчик. Значение сразу обновляется и на I2C LCD 16x2, и — через поддержку WebSocket в ESPAsyncWebServer — во всех подключённых браузерах без перезагрузки страницы. Вместо опроса по HTTP используется одно постоянное соединение, и ESP32 отправляет новое значение всем через ws.textAll().

Сигнализация движения на ESP32 (PIR + зуммер + светодиод + Telegram)
Умная охранная сигнализация, которая при обнаружении движения PIR-датчиком включает зуммер и светодиод и одновременно сразу отправляет владельцу уведомление в Telegram. В ней есть 30-секундная пауза, ограничивающая частоту повторных тревог; этот механизм не проверяет срабатывания PIR и не устраняет ложные тревоги. Подходит для дома, гаража, склада или мастерской. С ESP32-CAM можно добавить уведомления с фото, а с обычной ESP32 DevKit V1 приходят текстовые.
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

