Почему ESP32 со статическим IP не выходит в интернет?
Обновлено Редакция GAW
У устройства в сети IPv4 есть адрес, маска и шлюз, а для работы с именами — ещё адрес DNS-сервера. Пока работает DHCP, всё это выдаёт роутер. При статической настройке каждую величину задаёт программа, и ошибка в любой даёт характерный симптом.
Как устройство решает, куда отправить пакет
Узел накладывает маску на свой адрес и на адрес назначения: если результаты совпадают, получатель в той же сети и пакет уходит напрямую, иначе — через шлюз (RFC 1122, разд. 3.3.1.1). Интернет всегда «не в своей сети», поэтому без правильного шлюза до него не дойти.
| Симптом | Причина |
|---|---|
| Не видит и локальную сеть | адрес не из подсети роутера или конфликт адресов |
| Локальная сеть есть, внешних адресов нет | шлюз не задан, 0.0.0.0 или не из своей подсети |
| Внешние IP-адреса доступны, имена — нет | не задан DNS-сервер |
| Часть локальных адресов недоступна | маска шире или уже, чем у роутера |
Наш пример: ESP32 с адресом 192.168.1.50/24 и шлюзом 192.168.0.1. Сеть ESP32 — 192.168.1.0, а шлюз лежит в 192.168.0.0: устройство не может отправить ему пакет напрямую, и выхода в интернет нет. Проверить, в одной ли подсети адрес и шлюз, можно в калькуляторе подсетей.
Как задать адрес в ESP-IDF
- Остановить клиент DHCP:
esp_netif_dhcpc_stop(). - Заполнить адрес, маску и шлюз и вызвать
esp_netif_set_ip_info(). - Задать DNS-сервер:
esp_netif_set_dns_info()с типомESP_NETIF_DNS_MAIN— например, адрес роутера, если он работает DNS-сервером.
Для Ethernet через W5500 или LAN8720 порядок тот же: интерфейс работает через ESP-NETIF — о выборе контроллера ответ «W5500 или LAN8720 для ESP32», а варианты Ethernet для микроконтроллеров — в статье «Ethernet для микроконтроллера».
Похожие вопросы
Как узнать правильный шлюз и маску?
Посмотреть их у компьютера или телефона, подключённого к той же сети и получившего адрес по DHCP: шлюз — адрес роутера, маска — та же. ESP32 со статическим адресом должен получить такие же маску и шлюз и свободный адрес из той же подсети вне пула DHCP роутера.
Почему с DHCP всё работало, а со статическим адресом нет?
При DHCP роутер сам выдаёт адрес, маску, шлюз и DNS-серверы. Остановив DHCP, вы берёте всё это на себя: забытый шлюз отрезает внешние адреса, забытый DNS — имена. По документации ESP-IDF при выключенном клиенте DHCP основной и резервный DNS можно задать только функцией esp_netif_set_dns_info().
esp_netif_set_ip_info() возвращает ошибку. Почему?
Скорее всего, клиент DHCP ещё работает: ESP-IDF требует сначала его остановить функцией esp_netif_dhcpc_stop(), иначе вызов вернёт ESP_ERR_ESP_NETIF_DHCP_NOT_STOPPED. Порядок действий показан в примере protocols/static_ip.
Источники
- Espressif. ESP-IDF Programming Guide v6.1: ESP-NETIF — для статического адреса и DNS-серверов нужно остановить клиент DHCP, включённый по умолчанию у интерфейса Ethernet и станции Wi-Fi (пример protocols/static_ip); esp_netif_set_ip_info() — адрес, маска и шлюз; esp_netif_set_dns_info(): при включённом DHCP основной и резервный DNS приходят из аренды DHCP, при выключенном — задаются только этой функцией; LWIP хранит DNS глобально, а не для интерфейса
- IETF. RFC 1122: Requirements for Internet Hosts — Communication Layers, 1989 — разд. 3.3.1.1: если адрес назначения после наложения маски совпадает с адресом узла, пакет отправляется напрямую, иначе — через шлюз (разд. 3.3.1.2)
- Modbus Organization. MODBUS Messaging on TCP/IP Implementation Guide V1.0b, 2006 — разд. 4.3.3.1: адрес шлюза по умолчанию должен быть в подсети локального адреса, 0.0.0.0 запрещён
Нашли ошибку?
Смотрите также
- Калькулятор подсетей IPv4Маска и CIDR, сеть, broadcast, узлы, частные диапазоны, деление на подсети
- Ethernet для микроконтроллераW5500, ENC28J60, MAC + PHY по RMII, LAN8720, DP83848, трансформатор и разводка
- Что выбрать для ESP32: W5500 или LAN8720?LAN8720 — только классический ESP32 и P4; W5500 — любой ESP32
- ESP32ESP32, S2, S3, C2, C3, C5, C6, H2, P4: ядра, радио, USB, GPIO — сравнение и выбор
- Почему ESP32 перезагружается при включении Wi-Fi?Пики тока передатчика и просадка питания модуля