WiFi¶
The flag wifiConnectAttemptNeeded indicates whether a new connect attempt is needed. This is set to true when:
- Security settings have been saved with AP mode enabled. FIXME TD-er, this may not be the best check.
- WiFi connect timeout reached & No client is connected to the AP mode of the node.
- Wifi is reset
- WiFi setup page has been loaded with SSID/pass values.
WiFi AP mode states¶
- AP on -> reset AP disable timer
- AP client connect/disconnect -> reset AP disable timer
- AP off -> AP disable timer = 0;
AP mode will be disabled when both apply:
AP mode will be enabled when at least one applies:
Start AP timer is set or cleared at:
- Set timerAPstart when “valid WiFi connection” state is observed.
- Disable timerAPstart when ESPEASY_WIFI_SERVICES_INITIALIZED wifi state is reached.
Quick reconnect (using BSSID/channel of last connection) when both apply:
Change of wifi settings when both apply:
Reset of wifi_connect_attempt to 0 when both apply:
WiFi disconnect reasons¶
Beacon timeout (200)¶
For more information on the Beacon frame, see Wikipedia.
In short, the access point sends periodically a packet containing information about the network. This interval is typically 100 TU (102.4 msec). The ESP module is trying to listen to this beacon every time, but for a number of reasons it may miss a beacon frame. The timeout is longer than 100 TU, so it must miss a number of these beacon frames to report a beacon timeout. Reasons to miss such a beacon frame are:
- ECO mode is enabled (see below)
- too busy processing other blocking tasks (very likely)
- access point not sending a beacon due to high traffic demands of others (depending on brand/model/settings)
- RF disturbances (not likely given how often this occurs)
- clock drift (not really likely)
So the “beacon timeout” is happening every now and then on the ESP nodes and ESPeasy will try to reconnect.
ECO mode¶
If the “ECO” mode is enabled, the ESP does turn off the radio for longer amounts of time.
Normally an access point does send out a beacon at every so called “beacon interval”. A typical beacon interval is ~100 msec (102.4 msec). When you try to send data to a connected WiFi station, your access point first tries to send directly to the node and if it doesn’t immediately reply, the access point includes a notification for this node in such a beacon package. Meaning, if you send a ping (or just any package) to a WiFi connected node, the first reply typically takes half this interval. (later ping replies may receive a response more quickly as the radio may be on continuously)
On ESP32, setting the ECO mode will also reduce the CPU clock to 80 MHz. (added: 2022/12/15)
If the ESP (or any other WiFi device in “power save mode”) is not listening to each beacon interval, it may take longer to reach the node. Such a “listen interval” is called a DTIM interval and is often set between 1 and 3 for almost all WiFi devices. I’m not entirely sure what the ESP uses when consuming ~80 mA, but I think it has the radio on all the time, effectively receiving packets before the next beacon interval.
Here a quick test performed on 2 ESPEasy nodes. One with “Eco mode” enabled and one disabled:
gijs@DESKTOP-QLB7N8I:~/GitHub/letscontrolit/ESPEasy$ ping 192.168.10.92 PING 192.168.10.92 (192.168.10.92) 56(84) bytes of data. 64 bytes from 192.168.10.92: icmp_seq=1 ttl=254 time=6.51 ms 64 bytes from 192.168.10.92: icmp_seq=2 ttl=254 time=4.24 ms 64 bytes from 192.168.10.92: icmp_seq=3 ttl=254 time=104 ms 64 bytes from 192.168.10.92: icmp_seq=4 ttl=254 time=3.01 ms ^C --- 192.168.10.92 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3005ms rtt min/avg/max/mdev = 3.007/29.329/103.562/42.876 ms gijs@DESKTOP-QLB7N8I:~/GitHub/letscontrolit/ESPEasy$ ping 192.168.10.211 PING 192.168.10.211 (192.168.10.211) 56(84) bytes of data. 64 bytes from 192.168.10.211: icmp_seq=2 ttl=254 time=885 ms 64 bytes from 192.168.10.211: icmp_seq=4 ttl=254 time=40.9 ms 64 bytes from 192.168.10.211: icmp_seq=5 ttl=254 time=34.8 ms 64 bytes from 192.168.10.211: icmp_seq=7 ttl=254 time=85.6 ms ^C --- 192.168.10.211 ping statistics --- 13 packets transmitted, 4 received, 69.2308% packet loss, time 12323ms rtt min/avg/max/mdev = 34.788/261.588/885.111/360.524 ms
As you can see, one of them did not reply on all ping packets and the first ping took quite some time to get a reply. N.B. both are connected to the same access point.
What happens if you try to reach any host on your network?
Case 1, your PC does not know the MAC address of the ESP:
- Your PC tries to find the MAC address belonging to an IP address using an ARP packet (question is like: “Who has 1.2.3.4?”)
- ARP packets gets broadcasted to the entire network
- If the ESP misses such an ARP request, you cannot route the IP packet to your ESP. -> fail
Case 2, your PR does know the MAC address of the ESP, but a switch or access point does not:
- Your PC sends out a packet for MAC belonging to your ESP
- Switch does not know how to rout and discards packet
- timeout on your PC.
Work around: Send Gratuitous ARP packets (answer to a question nobody asked)
- ESP sends “AA:BB:CC:DD:EE:FF has IP 1.2.3.4”
- All switches, access points and hosts on your network receiving this packet update their ARP table
- Roundtrip time of routing packet depends only on DTIM interval of the ESP.
TL;DR¶
If you only send data from your ESP to something like a broker, then using “ECO” mode does probably have little to no effect on WiFi performance. If you need a swift response (e.g. turning on a light), then you should not use “ECO” mode.
Support us by using one of these alternatives: Patreon Ko-Fi PayPal
© Copyright 2018-2023, ESP Easy.
Created using Sphinx 4.5.0.
Arduino.ru
Esp32 подключается, но WiFi.Status не становится WL_CONNECTED
for (i = 1; i < 3; i++) < Serial.println("Connecting to wifi " + String(ssid) + ": try " + String(i)); // delete old config WiFi.disconnect(true); delay(1000); // register wifi event callback WiFi.onEvent(WiFiEvent); WiFi.onEvent(WiFiGotIP, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP); // Connect to WiFi network WiFi.enableSTA(true); WiFi.begin(ssid, password); ssid_str=String(ssid); // Wait for connection j = 0; while ((WiFi.status() != WL_CONNECTED) & (j
к телефону, к роутеру микротик подключается. В нужном помещении дочка доступа не известная мне (вероятно убикьюти), доступа к настройкам нет, но айти прописал маки и ноутбука моего и esp32. ноутбук подключается к точке доступа нормально, а esp32 не подключается.
Вернее наступает событие Connected to access point (4), но WiFi.status() не равен WL_CONNECTED.
.Connecting to wifi XXX: try 1
[WiFi-event] event: 5 Disconnected from WiFi access point
[WiFi-event] event: 3 WiFi clients stopped
[WiFi-event] event: 0 WiFi interface ready
[WiFi-event] event: 2 WiFi client started
[WiFi-event] event: 0 WiFi interface ready
[WiFi-event] event: 4 Connected to access point
. Connecting to wifi XXX: try 2
[WiFi-event] event: 3 WiFi clients stopped
[WiFi-event] event: 0 WiFi interface ready
[WiFi-event] event: 2 WiFi client started
[WiFi-event] event: 0 WiFi interface ready
[WiFi-event] event: 4 Connected to access point
. Connecting to wifi M2021: try 3
[WiFi-event] event: 3 WiFi clients stopped
[WiFi-event] event: 0 WiFi interface ready
[WiFi-event] event: 2 WiFi client started
[WiFi-event] event: 0 WiFi interface ready
.
[WiFi-event] event: 5 Disconnected from WiFi access point
И так по кругу.
Как решить эту проблему?
Без логов ТД гадать можно бесконечно долго.
как их получить? как включить режим debug ?
Если это UAP от убика, то на UniFi Controller-е. Он вполне себе может отшивать устройства с низким уровнем передачи.
Ну и на ESP можно что-то типа Debug level включить, верно мыслите.
Функция обработчик событий говорит, что соединение с точной доступа произошло! :
[WiFi-event] event: 4 Connected to access point
Но на этом всё, ничего больше не происходит, никаких событий, нет выдачи адреса и т.д.
Ноутбук получает адрес динамический, т.е dhcp сервер там есть.
Почитал про дебаг, кроме jtag и прочих сложных отладчиков ничего не нашел, т.е. вариантов более глубокой отладки, чем события, нет.
Да может тупо ошибка в маке еспшки на стороне точки доступа. Без ее логов не понять.
Покажите нам две ваши функции:
WiFiEvent и WiFiGotIP , тогда посмотрим.
Вообще создается впечатление, что вы всего в кучу намешали. Сначала перегружаете калбэки, потом юзаете функции библиотеки которой для нормальной работы эти калбэки нужны, а они перегружены. Возьмите уже стандартный пример и попробуйте его.
Как включить отладочные сообщения для ESP32:
Спасибо за debug level, сегодня попробую
вот код:
//—обработчик событий wifi————————————————————————————- void WiFiEvent(WiFiEvent_t event) < Serial.printf("[WiFi-event] event: %d ", event); switch (event) < case SYSTEM_EVENT_WIFI_READY: Serial.println("WiFi interface ready"); break; case SYSTEM_EVENT_SCAN_DONE: Serial.println("Completed scan for access points"); break; case SYSTEM_EVENT_STA_START: Serial.println("WiFi client started"); break; case SYSTEM_EVENT_STA_STOP: Serial.println("WiFi clients stopped"); break; case SYSTEM_EVENT_STA_CONNECTED: Serial.println("Connected to access point"); break; case SYSTEM_EVENT_STA_DISCONNECTED: Serial.println("Disconnected from WiFi access point"); WiFi.begin(ssid, password); break; case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: Serial.println("Authentication mode of access point has changed"); break; case SYSTEM_EVENT_STA_GOT_IP: Serial.print("Obtained IP address: "); Serial.println(WiFi.localIP()); break; case SYSTEM_EVENT_STA_LOST_IP: Serial.println("Lost IP address and IP address is reset to 0"); break; case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: Serial.println("WiFi Protected Setup (WPS): succeeded in enrollee mode"); break; case SYSTEM_EVENT_STA_WPS_ER_FAILED: Serial.println("WiFi Protected Setup (WPS): failed in enrollee mode"); break; case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: Serial.println("WiFi Protected Setup (WPS): timeout in enrollee mode"); break; case SYSTEM_EVENT_STA_WPS_ER_PIN: Serial.println("WiFi Protected Setup (WPS): pin code in enrollee mode"); break; case SYSTEM_EVENT_AP_START: Serial.println("WiFi access point started"); break; case SYSTEM_EVENT_AP_STOP: Serial.println("WiFi access point stopped"); break; case SYSTEM_EVENT_AP_STACONNECTED: Serial.println("Client connected"); break; case SYSTEM_EVENT_AP_STADISCONNECTED: Serial.println("Client disconnected"); break; case SYSTEM_EVENT_AP_STAIPASSIGNED: Serial.println("Assigned IP address to client"); break; case SYSTEM_EVENT_AP_PROBEREQRECVED: Serial.println("Received probe request"); break; case SYSTEM_EVENT_GOT_IP6: Serial.println("IPv6 is preferred"); break; case SYSTEM_EVENT_ETH_START: Serial.println("Ethernet started"); break; case SYSTEM_EVENT_ETH_STOP: Serial.println("Ethernet stopped"); break; case SYSTEM_EVENT_ETH_CONNECTED: Serial.println("Ethernet connected"); break; case SYSTEM_EVENT_ETH_DISCONNECTED: Serial.println("Ethernet disconnected"); break; case SYSTEM_EVENT_ETH_GOT_IP: Serial.println("Obtained IP address"); break; default: break; >> //—обработчик событий wifi————————————————————————————- void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info)
Ну так повесте контроль на получение IP. В примере который вы курили есть :
WiFiEventId_t eventID = WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info)< Serial.print("WiFi lost connection. Reason: "); Serial.println(info.disconnected.reason); >, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED); Serial.print("WiFi Event ID: "); Serial.println(eventID);
Извиняюсь, оказалось проблема была на стороне роутера, айтишник неправильно прописал мак адрес (
поэтому точка доступа не выдавала адрес
столкнулся с похожей траблой
пытаюсь реализовать реконнект вафли после обрыва связи (Применительно к ЕСП32)
//————————————————————— Stop_wifi void stop_wifi() < if (web_cli) //Останавливаем клиента < DBG_OUT_PORT.println(F( "True stop the Client")); >if (web_ap) //Останавливаем АР < DBG_OUT_PORT.println(F( "True stop the AP")); >web_ap = false; web_cli = false; WiFi.mode(WIFI_OFF); WiFi.disconnect(); DBG_OUT_PORT.println(F(«WiFi stopped. «)); > //————————————————————— Start_wifi IPAddress start_wifi(const char* ssid, const char* ssipass, const char* apid, const char* appass) < IPAddress my_IP; DBG_OUT_PORT.print(F("Trying to connect a ")); DBG_OUT_PORT.println(ssid); #if defined(ESP8266) if (WiFi.getPersistent() == true) WiFi.persistent(false); //disable saving wifi config into SDK flash area #endif if (WiFi.getAutoConnect() != true) WiFi.setAutoConnect(true); //on power-on automatically connects to last used hwAP WiFi.setAutoReconnect(true); //automatically reconnects to hwAP in case it is disconnected WiFi.disconnect(true); WiFi.mode(WIFI_OFF); // May be necessary after deepSleep. Otherwise you may get "error: pll_cal exceeds 2ms. " when trying to connect delay(1); // --- // Here you can do whatever you need to do that doesn't need a WiFi connection. // --- #if defined(ESP8266) ESP.rtcUserMemoryRead(RTC_USER_DATA_SLOT_WIFI_STATE, reinterpret_cast(&state), sizeof(state)); #endif unsigned long start = millis(); delay(1000); // Examples of different ways to register wifi events WiFi.onEvent(WiFiEvent); WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP); WiFiEventId_t eventID = WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) < DBG_OUT_PORT.print("WiFi lost connection. Reason: "); DBG_OUT_PORT.println(info.wifi_sta_disconnected.reason); >, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED); // Remove WiFi event DBG_OUT_PORT.print(«WiFi Event ID: «); DBG_OUT_PORT.println(eventID); // WiFi.removeEvent(eventID); bool _resume = false; #if defined(ESP8266) _resume = (!WiFi.resumeFromShutdown(state) || (WiFi.waitForConnectResult(10000) != WL_CONNECTED)); #else _resume = (WiFi.waitForConnectResult(10000) != WL_CONNECTED); #endif if (_resume) < DBG_OUT_PORT.println(F("Cannot resume WiFi connection, connecting via begin. ")); if (!WiFi.mode(WIFI_STA) || !WiFi.begin(ssid, ssipass) || (WiFi.waitForConnectResult(10000) != WL_CONNECTED)) < DBG_OUT_PORT.print(F("Cannot connect to ")); DBG_OUT_PORT.println(ssid); DBG_OUT_PORT.print(F("Trying to start access point ")); DBG_OUT_PORT.println(apid); WiFi.mode(WIFI_AP); WiFi.softAP(apid, appass); my_IP = WiFi.softAPIP(); web_ap = true; DBG_OUT_PORT.print(F("AP IP address: ")); DBG_OUT_PORT.println(my_IP); return my_IP; >> DBG_OUT_PORT.print(ssid); DBG_OUT_PORT.println(F(» is connected!»)); unsigned long duration = millis() — start; DBG_OUT_PORT.printf(«Duration: %f\n», duration * 0.001); web_cli = true; my_IP = WiFi.localIP(); DBG_OUT_PORT.print(F(«Client IP address: «)); DBG_OUT_PORT.println(my_IP); return my_IP; > void WiFiEvent(WiFiEvent_t event) < DBG_OUT_PORT.printf(PSTR("[WiFi-event] event code: %d\n"), event); switch (event) < case ARDUINO_EVENT_WIFI_READY: DBG_OUT_PORT.println(F("WiFi interface ready")); break; case ARDUINO_EVENT_WIFI_SCAN_DONE: DBG_OUT_PORT.println(F("Completed scan for access points")); break; case ARDUINO_EVENT_WIFI_STA_START: DBG_OUT_PORT.println(F("WiFi client started")); break; case ARDUINO_EVENT_WIFI_STA_STOP: DBG_OUT_PORT.println(F("WiFi clients stopped")); break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: DBG_OUT_PORT.println(F("Connected to access point")); break; case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: DBG_OUT_PORT.println(F("Disconnected from WiFi access point")); break; case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: DBG_OUT_PORT.println(F("Authentication mode of access point has changed")); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: DBG_OUT_PORT.print(F("Obtained IP address: ")); DBG_OUT_PORT.println(WiFi.localIP()); break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: DBG_OUT_PORT.println(F("Lost IP address and IP address is reset to 0")); break; case ARDUINO_EVENT_WPS_ER_SUCCESS: DBG_OUT_PORT.println(F("WiFi Protected Setup (WPS): succeeded in enrollee mode")); break; case ARDUINO_EVENT_WPS_ER_FAILED: DBG_OUT_PORT.println(F("WiFi Protected Setup (WPS): failed in enrollee mode")); break; case ARDUINO_EVENT_WPS_ER_TIMEOUT: DBG_OUT_PORT.println(F("WiFi Protected Setup (WPS): timeout in enrollee mode")); break; case ARDUINO_EVENT_WPS_ER_PIN: DBG_OUT_PORT.println(F("WiFi Protected Setup (WPS): pin code in enrollee mode")); break; case ARDUINO_EVENT_WIFI_AP_START: DBG_OUT_PORT.println(F("WiFi access point started")); break; case ARDUINO_EVENT_WIFI_AP_STOP: DBG_OUT_PORT.println(F("WiFi access point stopped")); break; case ARDUINO_EVENT_WIFI_AP_STACONNECTED: DBG_OUT_PORT.println(F("Client connected")); break; case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: DBG_OUT_PORT.println(F("Client disconnected")); break; case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: DBG_OUT_PORT.println(F("Assigned IP address to client")); break; case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: DBG_OUT_PORT.println(F("Received probe request")); break; case ARDUINO_EVENT_WIFI_AP_GOT_IP6: DBG_OUT_PORT.println(F("AP IPv6 is preferred")); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: DBG_OUT_PORT.println(F("STA IPv6 is preferred")); break; case ARDUINO_EVENT_ETH_GOT_IP6: DBG_OUT_PORT.println(F("Ethernet IPv6 is preferred")); break; case ARDUINO_EVENT_ETH_START: DBG_OUT_PORT.println(F("Ethernet started")); break; case ARDUINO_EVENT_ETH_STOP: DBG_OUT_PORT.println(F("Ethernet stopped")); break; case ARDUINO_EVENT_ETH_CONNECTED: DBG_OUT_PORT.println(F("Ethernet connected")); break; case ARDUINO_EVENT_ETH_DISCONNECTED: DBG_OUT_PORT.println(F("Ethernet disconnected")); break; case ARDUINO_EVENT_ETH_GOT_IP: DBG_OUT_PORT.println(F("Obtained IP address")); break; default: break; >> void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) < DBG_OUT_PORT.println(F("WiFi connected")); DBG_OUT_PORT.println(F("IP address: ")); DBG_OUT_PORT.println(IPAddress(info.got_ip.ip_info.ip.addr)); >void setup() < DBG_OUT_PORT.begin(115200); fs_setup(); conf_data = loadConfig(conf_f); start_wifi(conf_data.sta_ssid, conf_data.sta_pass, conf_data.ap_ssid, conf_data.ap_pass); delay (2000); stop_wifi(); delay (2000); start_wifi(conf_data.sta_ssid, conf_data.sta_pass, conf_data.ap_ssid, conf_data.ap_pass); >void loop()
получаю следующее: (После холодного резета все замечательно — точка подключается и останавливается корректно)
09:13:20.456 -> Trying to connect a Home 09:13:21.492 -> WiFi Event ID: 3 09:13:21.492 -> Cannot resume WiFi connection, connecting via begin. 09:13:21.492 -> [WiFi-event] event code: 0 09:13:21.492 -> WiFi interface ready 09:13:21.541 -> [WiFi-event] event code: 2 09:13:21.541 -> WiFi client started 09:13:23.900 -> [WiFi-event] event code: 4 09:13:23.900 -> Connected to access point 09:13:24.467 -> [WiFi-event] event code: 7 09:13:24.467 -> Obtained IP address: 192.168.1.18 09:13:24.467 -> WiFi connected 09:13:24.467 -> IP address: 09:13:24.467 -> 192.168.1.18 09:13:24.515 -> Home is connected! 09:13:24.515 -> Duration: 4.049000 09:13:24.515 -> Client IP address: 192.168.1.18 09:13:26.544 -> True stop the Client 09:13:26.544 -> [WiFi-event] event code: 5 09:13:26.544 -> Disconnected from WiFi access point 09:13:26.544 -> WiFi lost connection. Reason: 8 09:13:26.544 -> [WiFi-event] event code: 3 09:13:26.544 -> WiFi clients stopped 09:13:26.544 -> WiFi stopped.
Но вот вторая попытка оказывается неудачной
09:13:28.571 -> Trying to connect a Home 09:13:29.566 -> WiFi Event ID: 6 09:13:29.566 -> Cannot resume WiFi connection, connecting via begin. 09:13:29.566 -> [WiFi-event] event code: 0 09:13:29.566 -> WiFi interface ready 09:13:29.566 -> [WiFi-event] event code: 0 09:13:29.566 -> WiFi interface ready 09:13:29.566 -> [WiFi-event] event code: 2 09:13:29.566 -> WiFi client started 09:13:29.566 -> [WiFi-event] event code: 2 09:13:29.566 -> WiFi client started 09:13:31.643 -> [WiFi-event] event code: 5 09:13:31.643 -> Disconnected from WiFi access point 09:13:31.643 -> WiFi lost connection. Reason: 201 09:13:31.643 -> [WiFi-event] event code: 5 09:13:31.643 -> Disconnected from WiFi access point 09:13:31.643 -> WiFi lost connection. Reason: 201 09:13:31.691 -> Cannot connect to Home 09:13:31.691 -> Trying to start access point C3_13
И как я разумею своим узким умишком все дело в этой строчке
09:13:29.566 -> WiFi Event ID: 6
При удачном коннекте она была равна 3
Видимо ид и пароль могут взяться откуда то из другого места?
if (WiFi.getPersistent() == true) WiFi.persistent(false); //disable saving wifi config into SDK flash area
В 32ке может есть что то похожее?