ESP32与Raspberry Pi Pico W Wi-Fi连接慢且丢包问题优化
ESP32与Raspberry Pi Pico W通信丢包及延迟过高问题解决
问题背景
需要通过ESP32和Raspberry Pi Pico W建立连接控制遥控船,要求数据传输延迟≤0.1秒,但当前连接传输缓慢,测试设置1秒延迟时Pico W接收数据存在丢失,测试输出如下:
Response from ESP32: 190, 300
Response from ESP32:Response from ESP32: 190, 300
Response from ESP32:Response from ESP32: 190, 300
Response from ESP32:
使用Arduino IDE编写ESP32程序,Thonny编写Pico W程序,代码如下:
ESP32代码
#include <WiFi.h> #include <WiFiClient.h> const char* ssid = "YourSSID"; const char* password = "YourPassword"; const int serverPort = 1234; WiFiServer server(serverPort); WiFiClient client; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); server.begin(); } void loop() { if (!client || !client.connected()) { client = server.available(); if (client) { Serial.println("Client connected"); } } if (client && client.connected()) { // Check if data is available from the Raspberry Pi Pico W if (client.available()) { String receivedData = client.readStringUntil('\n'); Serial.println("Received data: " + receivedData); // Send a response back to the Raspberry Pi Pico W client.println("190, 300"); } } }
Raspberry Pi Pico W代码
import usocket as socket import network import time def main(): ssid = "YourSSID" password = "YourPassword" esp32_ip = "YourESP32IP" # Replace with the IP address of the ESP32 esp32_port = 1234 wifi = network.WLAN(network.STA_IF) wifi.active(True) wifi.connect(ssid, password) while not wifi.isconnected(): time.sleep(1) print("Wi-Fi connected successfully") # Create a socket and connect to the ESP32 client_socket = socket.socket() addr = socket.getaddrinfo(esp32_ip, esp32_port)[0][-1] client_socket.connect(addr) try: while True: # Send data to the ESP32 data_to_send = "Hello from Raspberry Pi Pico W!" client_socket.send(data_to_send) # Receive the response from the ESP32 response = client_socket.recv(1024) print("Response from ESP32:", response.decode()) time.sleep(1) # Wait for 0.1 seconds before sending more data except: print("Connection lost. Reconnecting...") client_socket.close() time.sleep(5) if __name__ == "__main__": main()
问题原因及解决办法
1. 通信协议不匹配导致丢包
ESP32端用client.println()发送响应,会自动添加\r\n换行符;但Pico W发送数据时未添加换行符,导致ESP32的readStringUntil('\n')一直等待换行触发响应,最终造成丢包。
- 修复:Pico W发送数据时添加换行符并显式编码为字节流:
data_to_send = "Hello from Raspberry Pi Pico W!\n" client_socket.send(data_to_send.encode())
2. 无等待的接收逻辑导致空响应
Pico W的recv(1024)会一次性读取可用数据,但如果ESP32响应未到达就进入下一次循环,会出现空响应。
- 修复:在Pico W端添加短等待确保接收到完整数据:
# 等待数据可用 while client_socket.recv(0) == b'': time.sleep(0.001) response = client_socket.recv(1024).decode().strip() print("Response from ESP32:", response)
3. 优化延迟与连接稳定性
当前time.sleep(1)是1秒延迟,远高于0.1秒要求,同时TCP默认的Nagle算法会增加小数据包延迟。
- ESP32端修改:启用TCP_NODELAY并强制刷新缓冲区:
void loop() { if (!client || !client.connected()) { client = server.available(); if (client) { Serial.println("Client connected"); client.setNoDelay(true); // 禁用Nagle算法 } } if (client && client.connected()) { if (client.available()) { String receivedData = client.readStringUntil('\n'); Serial.println("Received data: " + receivedData); client.println("190, 300"); client.flush(); // 强制发送缓冲区数据 } } } - Pico W端修改:启用TCP_NODELAY并调整延迟:
client_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # ... 其他代码 time.sleep(0.1) # 修改为要求的0.1秒延迟
4. 避免ESP32动态内存分配导致性能下降
ESP32中String类的动态内存分配会增加延迟,改用字符数组处理接收数据:
char buffer[128]; int bytesRead = client.readBytesUntil('\n', buffer, sizeof(buffer)-1); if (bytesRead > 0) { buffer[bytesRead] = '\0'; Serial.print("Received data: "); Serial.println(buffer); client.println("190, 300"); client.flush(); }
内容的提问来源于stack exchange,提问作者PrismaHaken
相关产品推荐
相关产品推荐

