如何在 esp8266 中接收来自 python 通过 UDP 发送的结构

How to receive the struct sent over UDP from python , in esp8266

我正在从我的电脑发送 UDP 数据包到 esp8266,但是在收到数据包之后,它在 Arduino 串行监视器中看起来像这样:

我发送的原始数据:

这里是接收端的代码块(esp8266):

void udp_rcv()
{
  int packetSize = UDP.parsePacket();
  if (packetSize) {
    Serial.print("Received packet! Size: ");
    Serial.println(packetSize); 
    int len = UDP.read(packet, 255);
    if (len > 0)
    {
      packet[len] = '[=11=]';
    }
    Serial.print("Packet received: ");
    Serial.println(packet[0]);
}

这是使用 python 从我的电脑发送 UDP 数据包的代码:

pygame.event.pump()
roll     = mapping(joystick.get_axis(0),-1,1,1000,2000)
pitch    = mapping(joystick.get_axis(1),1,-1,1000,2000)
yaw      = mapping(joystick.get_axis(2),-1,1,1000,2000)
throttle = mapping(joystick.get_axis(3),1,-1,1000,2000)
mode     = joystick.get_button(6)

# Be sure to always send the data as floats
# The extra zeros on the message are there in order for the other scripts to do not complain about missing information
message = [roll, pitch, yaw, throttle, mode, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
buf = struct.pack('>' + 'd' * len(message), *message)
sock.sendto(buf, (UDP_IP, UDP_PORT))
print( message)

我想做的就是使用我的操纵杆游戏手柄输入通过 UDP 协议将其发送到 esp8266

要跨平台发送和接收数据,您需要了解发送的数据类型和数据结构,以及发送方和接收方的Endianness

关于您的 Python 代码

我不确定你为什么用 > 明确指定大端来打包数据,大多数现代计算机都使用小端而不是大端(除非你有摩托罗拉 68000 或 PowerPC 机器),而且Uno和ESP8266等所有MCU都是小端MCU。因此,使用 < 指定小端来打包数据会更有意义。

其次,您假设您的数据在 double 中,但如果您查看 message 上的屏幕截图,mode 绝对不是 double,而是 int(在大多数现代 PC 上,int 是 32 位长)。

所以不要用以下方式打包数据:

buf = struct.pack('>' + 'd' * len(message), *message)

你真正应该做的是:

buf = struct.pack('<ddddiddddddddd', *message)

关于您的 Arduino 代码

从 Python 代码发送的数据是一系列字节,可以用 C++ 表示为:

struct __attribute__((packed)) JoyStick {
  double roll;
  double pitch;
  double yaw;
  double throttle;
  int32_t mode;
  double array[9]; 
};

由于数据包数据是uint8_t的数组(或者你可能声明的char),将数据复制到JoyStick_t类型的变量中会更容易,这样您就可以以 struct.

的形式访问数据
  int packetSize = UDP.parsePacket();
  if (packetSize) {
    Serial.printf("Received %d bytes\n", packetSize);
    if (UDP.read(packet, packetSize) > 0)) {
      JoyStick myJoystick;                      //create a struct
      memcpy(&myJoystick, packet, packetSize);  //copy packet array to the a struct
      Serial.printf("%f %f %f %f %d\n", 
                    myJoystick.roll, 
                    myJoystick.pitch, 
                    myJoystick.yaw, 
                    myJoystick.throttle, 
                    myJoystick.mode);           // access the data in the struct
    }
  }