ESP32 STA mode latency problems
Posted: Mon Nov 27, 2023 3:50 pm
Hi,
I have made a program so that the ESP32 module connects in STA mode to form a wireless “lan cable”.
I see that the device that is connected to the module via Ethernet responds to the ping when the PC is connected to the same Wi-Fi network as said module. But although the connection is stable, the latency is very poor (900ms +-).
I have read that the latency improved considerably if the esp_wifi_set_ps (WIFI_PS_NONE) power saving mode was eliminated, but the result is still disastrous.
Any idea what could be happening?
I have made a program so that the ESP32 module connects in STA mode to form a wireless “lan cable”.
I see that the device that is connected to the module via Ethernet responds to the ping when the PC is connected to the same Wi-Fi network as said module. But although the connection is stable, the latency is very poor (900ms +-).
I have read that the latency improved considerably if the esp_wifi_set_ps (WIFI_PS_NONE) power saving mode was eliminated, but the result is still disastrous.
Any idea what could be happening?
- #include <string.h>
- #include <stdlib.h>
- #include "sdkconfig.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "esp_event.h"
- #include "esp_log.h"
- #include "esp_eth_driver.h"
- #include "esp_wifi.h"
- #include "nvs_flash.h"
- #include "esp_private/wifi.h"
- #include "ethernet_init.h"
- #include "esp_netif_br_glue.h"
- #include "esp_eth.h"
- #include "esp_mac.h"
- #include "esp_system.h"
- #include "esp_netif.h"
- #include "lwip/ip4_addr.h"
- #include "lwip/netif.h"
- #include "freertos/event_groups.h"
- #include "lwip/err.h"
- #include "lwip/sys.h"
- //
- #define STA_MODE 1
- //
- static const char *TAG = "eth2ap_example";
- static esp_eth_handle_t s_eth_handle[2] = {NULL};
- static QueueHandle_t flow_control_queue = NULL;
- static bool s_sta_is_connected = false;
- static bool s_ethernet_is_connected = false;
- #if STA_MODE
- static int s_retry_num = 0;
- /* FreeRTOS event group to signal when we are connected*/
- static EventGroupHandle_t s_wifi_event_group;
- /* The event group allows multiple bits for each event, but we only care about two events:
- * - we are connected to the AP with an IP
- * - we failed to connect after the maximum amount of retries */
- #define WIFI_CONNECTED_BIT BIT0
- #define WIFI_FAIL_BIT BIT1
- #endif
- #define FLOW_CONTROL_QUEUE_TIMEOUT_MS (100) //100
- #define FLOW_CONTROL_QUEUE_LENGTH (60) //60
- #define FLOW_CONTROL_WIFI_SEND_TIMEOUT_MS (100) //100
- #if STA_MODE
- #define EXAMPLE_ESP_WIFI_SSID "Serie500"
- #define EXAMPLE_ESP_WIFI_PASS "BalanzaUniversal0"
- #define EXAMPLE_ESP_MAXIMUM_RETRY 5
- #if STA_MODE
- #define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
- #define EXAMPLE_H2E_IDENTIFIER ""
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
- #endif
- #if CONFIG_ESP_WPA3_SAE_PWE_HUNT_AND_PECK
- #define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
- #define EXAMPLE_H2E_IDENTIFIER ""
- #elif CONFIG_ESP_WPA3_SAE_PWE_HASH_TO_ELEMENT
- #define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
- #define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
- #elif CONFIG_ESP_WPA3_SAE_PWE_BOTH
- #define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
- #define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
- #endif
- #if CONFIG_ESP_WIFI_AUTH_OPEN
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
- #elif CONFIG_ESP_WIFI_AUTH_WEP
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
- #elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
- #elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
- #elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
- #elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
- #elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
- #elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
- #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
- #endif
- #endif
- typedef struct {
- void *packet;
- uint16_t length;
- esp_eth_handle_t eth_handle;
- } flow_control_msg_t;
- #if STA_MODE
- // Forward packets from Wi-Fi to Ethernet
- static esp_err_t tcpip_adapter_sta_input_eth_output(void *buffer, uint16_t len, void *eb)
- {
- if (s_ethernet_is_connected) {
- if (esp_eth_transmit(s_eth_handle[0], buffer, len) != ESP_OK) {
- ESP_LOGE(TAG, "Ethernet send packet 1 failed");
- }
- else{
- ESP_LOGI(TAG, "Envío paquete internamente wifi STA/ethernet OK");
- }
- }
- esp_wifi_internal_free_rx_buffer(eb);
- return ESP_OK;
- }
- #endif
- // Forward packets from Wi-Fi to Ethernet
- static esp_err_t tcpip_adapter_ap_input_eth_output(void *buffer, uint16_t len, void *eb)
- {
- if (s_ethernet_is_connected) {
- //if (s_eth_handle[0] == eth_handle){
- if (esp_eth_transmit(s_eth_handle[0], buffer, len) != ESP_OK) {
- ESP_LOGE(TAG, "Ethernet send packet 1 failed");
- }else{
- ESP_LOGI(TAG, "Envío paquete internamente wifi AP/ethernet OK");
- }
- } //else {
- //if (esp_eth_transmit(s_eth_handle[1], buffer, len) != ESP_OK) {
- // ESP_LOGE(TAG, "Ethernet send packet 2 failedbbb");
- // }
- //}
- esp_wifi_internal_free_rx_buffer(eb);
- return ESP_OK;
- }
- // Forward packets from Ethernet to Wi-Fi
- // Note that, Ethernet works faster than Wi-Fi on ESP32,
- // so we need to add an extra queue to balance their speed difference.
- static esp_err_t pkt_eth2wifi(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t len, void *priv)
- {
- esp_err_t ret = ESP_OK;
- flow_control_msg_t msg = {
- .packet = buffer,
- .length = len,
- .eth_handle = eth_handle
- };
- if (xQueueSend(flow_control_queue, &msg, pdMS_TO_TICKS(FLOW_CONTROL_QUEUE_TIMEOUT_MS)) != pdTRUE) {
- ESP_LOGI(TAG, "Envio de mensaje Flow control fallido o timeout");
- ESP_LOGE(TAG, "send flow control message failed or timeout");
- free(buffer);
- ret = ESP_FAIL;
- }
- else{
- ESP_LOGI(TAG, "Envio de mensaje al flow control OK");
- }
- return ret;
- }
- // This task will fetch the packet from the queue, and then send out through Wi-Fi.
- // Wi-Fi handles packets slower than Ethernet, we might add some delay between each transmitting.
- static void eth2wifi_flow_control_task(void *args)
- {
- flow_control_msg_t msg;
- int res = 0;
- uint32_t timeout = 0;
- while (1) {
- if (xQueueReceive(flow_control_queue, &msg, pdMS_TO_TICKS(FLOW_CONTROL_QUEUE_TIMEOUT_MS)) == pdTRUE) {
- timeout = 0;
- if (s_sta_is_connected && msg.length) {
- do {
- vTaskDelay(pdMS_TO_TICKS(timeout));
- timeout += 2;
- #if STA_MODE
- res = esp_wifi_internal_tx(WIFI_IF_STA, msg.packet, msg.length);
- #else
- res = esp_wifi_internal_tx(WIFI_IF_AP, msg.packet, msg.length);
- #endif
- } while (res && timeout < FLOW_CONTROL_WIFI_SEND_TIMEOUT_MS);
- if (res != ESP_OK) {
- ESP_LOGE(TAG, "WiFi send packet failed: %d", res);
- }
- else{
- ESP_LOGI(TAG, "Envio de mensaje wifi OK");
- }
- }
- free(msg.packet);
- }
- }
- vTaskDelete(NULL);
- }
- // Event handler for Ethernet
- static void eth_event_handler(void *arg, esp_event_base_t event_base,
- int32_t event_id, void *event_data)
- {
- uint8_t mac_addr[6] = {0};
- // Set your new MAC Address
- uint8_t wifiMACAddress[6] = {0x00, 0x08, 0xEF, 0x00, 0x01, 0x37}; //MAC
- /* we can get the ethernet driver handle from event data */
- esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
- switch (event_id) {
- case ETHERNET_EVENT_CONNECTED:
- // if (eth_handle == s_eth_handle[0]){
- s_ethernet_is_connected = true;
- esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
- #if STA_MODE
- esp_wifi_set_mac(WIFI_IF_STA, wifiMACAddress);
- esp_wifi_set_ps (WIFI_PS_NONE);
- #else
- esp_wifi_set_mac(WIFI_IF_AP, mac_addr);
- esp_wifi_set_mac(WIFI_IF_STA, mac_addr);
- #endif
- //esp_wifi_connect();
- ESP_ERROR_CHECK(esp_wifi_start());
- // }
- ESP_LOGI(TAG, "Ethernet (%p) Link Up", eth_handle);
- ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
- mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
- ESP_LOGI(TAG, "WIFI MAC Addr %02x:%02x:%02x:%02x:%02x:%02x",
- wifiMACAddress[0], wifiMACAddress[1], wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]);
- break;
- //
- case ETHERNET_EVENT_DISCONNECTED:
- // s_ethernet_is_connected = false;
- // ESP_ERROR_CHECK(esp_wifi_stop());
- ESP_LOGI(TAG, "Ethernet (%p) Link Down", eth_handle);
- break;
- //
- case ETHERNET_EVENT_START:
- ESP_LOGI(TAG, "Ethernet (%p) Started", eth_handle);
- break;
- //
- case ETHERNET_EVENT_STOP:
- ESP_LOGI(TAG, "Ethernet (%p) Stopped", eth_handle);
- break;
- //
- default:
- break;
- }
- }
- // Event handler for Wi-Fi
- static void wifi_event_handler(void *arg, esp_event_base_t event_base,
- int32_t event_id, void *event_data)
- {
- static uint8_t s_con_cnt = 0;
- switch (event_id) {
- case WIFI_EVENT_AP_STACONNECTED:
- ESP_LOGI(TAG, "Wi-Fi AP got a station connected");
- if (!s_con_cnt) {
- s_sta_is_connected = true;
- esp_wifi_internal_reg_rxcb(WIFI_IF_AP, tcpip_adapter_ap_input_eth_output);
- }
- s_con_cnt++;
- break;
- case WIFI_EVENT_AP_STADISCONNECTED:
- ESP_LOGI(TAG, "Wi-Fi AP got a station disconnected");
- s_con_cnt--;
- if (!s_con_cnt) {
- s_sta_is_connected = false;
- esp_wifi_internal_reg_rxcb(WIFI_IF_AP, NULL);
- }
- break;
- #if STA_MODE
- case WIFI_EVENT_STA_START:
- esp_wifi_connect();
- break;
- case WIFI_EVENT_STA_DISCONNECTED:
- s_sta_is_connected = false;
- esp_wifi_internal_reg_rxcb(WIFI_IF_STA, NULL);
- if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
- esp_wifi_connect();
- s_retry_num++;
- ESP_LOGI(TAG, "retry to connect to the AP");
- }
- //if (s_retry_num == EXAMPLE_ESP_MAXIMUM_RETRY)
- // esp_wifi_disconnect();
- ESP_LOGI(TAG,"connect to the AP fail");
- break;
- case IP_EVENT_STA_GOT_IP:
- ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
- ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
- s_retry_num = 0;
- break;
- case WIFI_EVENT_STA_CONNECTED:
- s_retry_num = 0;
- s_sta_is_connected = true;
- esp_wifi_internal_reg_rxcb(WIFI_IF_STA, tcpip_adapter_sta_input_eth_output);
- //esp_wifi_internal_reg_rxcb(WIFI_IF_STA, (wifi_rxcb_t)tcpip_adapter_sta_input_eth_output);
- xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
- break;
- #endif
- default:
- break;
- }
- }
- static void initialize_ethernet(void)
- {
- uint8_t eth_port_cnt = 0;
- esp_eth_handle_t *eth_handles;
- ESP_ERROR_CHECK(example_eth_init(ð_handles, ð_port_cnt));
- for (uint8_t i = 0; i < eth_port_cnt; i++)
- {
- s_eth_handle[i] = eth_handles[i];
- ESP_ERROR_CHECK(esp_eth_update_input_path(eth_handles[i], pkt_eth2wifi, NULL));
- bool eth_promiscuous = true;
- ESP_ERROR_CHECK(esp_eth_ioctl(eth_handles[i], ETH_CMD_S_PROMISCUOUS, ð_promiscuous));
- ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler, NULL));
- ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
- }
- free(eth_handles);
- }
- static void initialize_wifi(void)
- {
- ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL));
- wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
- ESP_ERROR_CHECK(esp_wifi_init(&cfg));
- ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
- #if STA_MODE
- s_wifi_event_group = xEventGroupCreate();
- ESP_ERROR_CHECK(esp_netif_init());
- esp_netif_create_default_wifi_sta();
- #endif
- #if STA_MODE
- esp_event_handler_instance_t instance_any_id;
- esp_event_handler_instance_t instance_got_ip;
- ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
- ESP_EVENT_ANY_ID,
- &wifi_event_handler,
- NULL,
- &instance_any_id));
- ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
- IP_EVENT_STA_GOT_IP,
- &wifi_event_handler,
- NULL,
- &instance_got_ip));
- #endif
- #if STA_MODE
- wifi_config_t wifi_config = {
- .sta = {
- .ssid = EXAMPLE_ESP_WIFI_SSID,
- .password = EXAMPLE_ESP_WIFI_PASS,
- /* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
- * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
- * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
- * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
- */
- .channel = 1,
- .threshold.authmode = WIFI_AUTH_WPA2_PSK,
- .sae_pwe_h2e = ESP_WIFI_SAE_MODE,
- .sae_h2e_identifier = EXAMPLE_H2E_IDENTIFIER,
- },
- };
- ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
- esp_wifi_set_ps (WIFI_PS_NONE);
- ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
- ESP_ERROR_CHECK(esp_wifi_start() );
- ESP_LOGI(TAG, "wifi_init_sta finished.");
- /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
- * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
- EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
- WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
- pdFALSE,
- pdFALSE,
- portMAX_DELAY);
- /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
- * happened. */
- if (bits & WIFI_CONNECTED_BIT) {
- ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
- EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
- } else if (bits & WIFI_FAIL_BIT) {
- ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
- EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
- } else {
- ESP_LOGE(TAG, "UNEXPECTED EVENT");
- }
- #else
- wifi_config_t wifi_config = {
- .ap = {
- .ssid = CONFIG_EXAMPLE_WIFI_SSID,
- .ssid_len = strlen(CONFIG_EXAMPLE_WIFI_SSID),
- .password = CONFIG_EXAMPLE_WIFI_PASSWORD,
- .max_connection = CONFIG_EXAMPLE_MAX_STA_CONN,
- .authmode = WIFI_AUTH_WPA_WPA2_PSK,
- .channel = CONFIG_EXAMPLE_WIFI_CHANNEL // default: channel 1
- },
- };
- if (strlen(CONFIG_EXAMPLE_WIFI_PASSWORD) == 0) {
- wifi_config.ap.authmode = WIFI_AUTH_OPEN;
- }
- ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
- ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
- #endif
- }
- static esp_err_t initialize_flow_control(void)
- {
- flow_control_queue = xQueueCreate(FLOW_CONTROL_QUEUE_LENGTH, sizeof(flow_control_msg_t));
- if (!flow_control_queue) {
- ESP_LOGE(TAG, "create flow control queue failed");
- return ESP_FAIL;
- }
- BaseType_t ret = xTaskCreate(eth2wifi_flow_control_task, "flow_ctl", 2048, NULL, (tskIDLE_PRIORITY + 2), NULL);
- if (ret != pdTRUE) {
- ESP_LOGE(TAG, "create flow control task failed");
- return ESP_FAIL;
- }
- ESP_LOGI(TAG, "Flow control bien");
- return ESP_OK;
- }
- void app_main(void)
- {
- esp_err_t ret = nvs_flash_init();
- if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
- ESP_ERROR_CHECK(nvs_flash_erase());
- ret = nvs_flash_init();
- }
- ESP_ERROR_CHECK(ret);
- ESP_ERROR_CHECK(esp_event_loop_create_default());
- ESP_ERROR_CHECK(initialize_flow_control());
- initialize_wifi();
- initialize_ethernet();
- }