使用 esp32 接入点流式传输 UDP 数据包会导致大量数据包丢失

Posted

技术标签:

【中文标题】使用 esp32 接入点流式传输 UDP 数据包会导致大量数据包丢失【英文标题】:streaming UDP packets with esp32 access point cause massive packet loss 【发布时间】:2021-10-18 13:40:20 【问题描述】:

我目前正在运行我的 esp32 wroom 作为接入点,以将 UDP 数据包(每秒约 100 个数据包,每个数据包 1Ko)流式传输到不同的智能手机。 在近距离,我以稳定的速度丢失了大约 30% 的数据包。 使用 UDP 协议丢失数据包并不罕见,但此问题仅发生在某些特定且最近的智能手机上。 在对 Wifi 消息进行了一些 Wireshark 调查后,我观察到这种数据包丢失仅发生在使用 IEEE 802.11 省电机制的智能手机上。 ESP 32 配置中有很多关于省电模式的选项,我怀疑我可能错误配置了 ESP32。

您知道导致问题的原因吗?

谢谢

我正在与您分享 ESP32 配置:

#
# Wi-Fi
#

CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=y
# CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER is not set
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=32
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=32
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set
CONFIG_ESP32_WIFI_IRAM_OPT=y
CONFIG_ESP32_WIFI_RX_IRAM_OPT=y
CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y
# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set
# CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is not set
# end of Wi-Fi

查看接入点初始化代码:

esp_err_t COM_wifi_access_point_start(void) 
        
    esp_err_t esp_err;
    
    do  
        
        // Initialization of the physical WiFi port
        tcpip_adapter_init();

        // Shutdown of the DHCP server before reprogramming the IP address of the probe
        BREAK_ON_ERR( esp_err = tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP) );

        // Initialization of the structure containing the IP address of the probe
        tcpip_adapter_ip_info_t ip_info;
        IP4_ADDR(&ip_info.ip,EPF_IPV4_IP_ADDR_1,EPF_IPV4_IP_ADDR_2,EPF_IPV4_IP_ADDR_3,EPF_IPV4_IP_ADDR_4);
        IP4_ADDR(&ip_info.gw,EPF_IPV4_GW_ADDR_1,EPF_IPV4_GW_ADDR_2,EPF_IPV4_GW_ADDR_3,EPF_IPV4_GW_ADDR_4);
        IP4_ADDR(&ip_info.netmask,EPF_IPV4_NM_ADDR_1,EPF_IPV4_NM_ADDR_2,EPF_IPV4_NM_ADDR_3,EPF_IPV4_NM_ADDR_4);

        // The new IP address is applied
        BREAK_ON_ERR( esp_err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info) );

        // Restarting the DHCP server
        BREAK_ON_ERR( esp_err = tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP) );

        // Connecting the IT WiFi handler
        BREAK_ON_ERR( esp_err = esp_event_loop_init(wifi_event_handler, NULL) );

        // Initialization of the WiFi driver to the default configuration
        wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT();
        BREAK_ON_ERR( esp_err = esp_wifi_init(&wifi_init_config) );

        // The driver is told to store all WiFi configuration in RAM
        // => We don't always write the configuration in flash each time
        BREAK_ON_ERR( esp_err = esp_wifi_set_storage(WIFI_STORAGE_RAM) );

        // Switching from the default connection mode to Access Point mode
        BREAK_ON_ERR( esp_err = esp_wifi_set_mode(WIFI_MODE_AP) );

        // The desired configuration is applied to the WiFi driver
        wifi_config_t ap_config =
            
            .ap =
                
                .ssid           = "",
                .channel        = EPF_WIFI_CHANNEL_NUMBER,
                .password       = EPF_WIFI_PASSWORD,
                .authmode       = WIFI_AUTH_WPA_WPA2_PSK,
                .ssid_hidden    = COM_WIFI_BROADCAST,                               // SSID in broadcast mode => Non-hidden network
                .max_connection = EPF_WIFI_NB_CONNECTION,                           // Only one connection allowed simultaneously
                .beacon_interval= COM_WIFI_BEACON_INT
                
            ;
        sprintf((char*)ap_config.ap.ssid, EPF_WIFI_SSID_TMPL, PAR_get_live_raw_fast(EPF_MAI_PROBE_SERIAL_NB) );
        
        BREAK_ON_ERR( esp_err = esp_wifi_set_config(WIFI_IF_AP, &ap_config) );

        // Starting WiFi
        // After calling this function, the access point is visible from remote WiFi devices
        BREAK_ON_ERR( esp_err = esp_wifi_start() );

        // Renaming the hostname
        BREAK_ON_ERR( esp_err = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, COM_LOCALHOSTNAME) );
        
        esp_err = ESP_OK;
        
         while(0);

    return esp_err;
    

【问题讨论】:

【参考方案1】:

ESP32-s WiFi 省电默认开启。你可以通过调用esp_wifi_set_ps(WIFI_PS_NONE); 来禁用它——看看它是否适合你。在我看到负载下的大量 ICMP 数据包丢失后,我不得不将其关闭。

【讨论】:

我尝试使用esp_wifi_set_ps(WIFI_PS_NONE),但它似乎不起作用。当我使用 Wireshark 查看 Wifi 框架时,我仍在查看来自智能手机的电源管理请求。

以上是关于使用 esp32 接入点流式传输 UDP 数据包会导致大量数据包丢失的主要内容,如果未能解决你的问题,请参考以下文章

将 esp-32 摄像头流式传输到 YouTube 等 RTMP 服务器 [关闭]

WIFI无线传输模块使用 ESP8266芯片方案接入云平台的方法

esp32tcpclient最大传输的数据长度

esp32无协议通讯

ESP8266, NodeMCU, soft AP - UDP server-like soft AP, 独立接入点

ESP8266 WebServer如何流式传输无符号字符