You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:52:47