首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解码从arduino发送到用Python制作的TCP服务器的Byte数组

解码从arduino发送到用Python制作的TCP服务器的Byte数组
EN

Stack Overflow用户
提问于 2022-11-29 11:22:25
回答 2查看 35关注 0票数 0

我正在将传感器数据转换为字节,并将字节数组从arduino写入使用Python制作的TCP服务器,但不知何故,数组中的传感器数据在解码时触发UTF-8错误的变化。

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcf in position 1: invalid continuation byte

"0xcf“和"0xff”从一个错误变为另一个错误。

我怀疑这是因为传感器数据有时可能是负值。我知道一个字节不能容纳一个负数,而UTF-8可以容纳0-256.我想我必须在负值之前发送一个专用的"-“符号。然而,我不能预测什么时候出现负值。因此,必须有更好的办法来做到这一点。我可以发送字节数组而不对其进行解码,但我怀疑这里也存在一些问题,因为前两个位置的值应该与其余6个位置的值不同,如下所示:b'\xff\x00\x00\x00\x00\x00\x00\x00' b'\x02\x00\x00\x00\x00\x00\x00\x00'

我的问题是:如何以字节的形式发送负值并对其进行正确解码。

对于上下文,我将附加我的代码。Arduino客户:`

代码语言:javascript
复制
#include <Ethernet.h>
#include <SPI.h>
#include "AK09918.h"
#include "ICM20600.h"
#include <Wire.h>
//----------------------------------

//tiltsensor
AK09918_err_type_t err;
int32_t x, y, z;
AK09918 ak09918;
ICM20600 icm20600(true);
int16_t acc_x, acc_y, acc_z;
int32_t offset_x, offset_y, offset_z;
double roll, pitch;
//----------------------------------

//Ethernet
byte mac[] = { 0xBE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //not important if only one ethernet shield
byte ip[] = { 192, 168, X, X}; //IP of this arduino unit
byte server[] = { 192, 168, X, X}; //IP of server you want to contact
int tcp_port = 65432; // a nice port to send/acess the information on
EthernetClient client; 
//----------------------------------

//byte array
byte array[8] = {0, 0, 0, 0, 0, 0, 0, 0};
//----------------------------------

void setup()
{
  //tiltsensor
  Wire.begin();
  err = ak09918.initialize();
  icm20600.initialize();
  ak09918.switchMode(AK09918_POWER_DOWN);
  ak09918.switchMode(AK09918_CONTINUOUS_100HZ);
  Serial.begin(9600);
  err = ak09918.isDataReady();
  while (err != AK09918_ERR_OK) {
      Serial.println("Waiting Sensor");
      delay(100);
      err = ak09918.isDataReady();}
  Serial.println("Start figure-8 calibration after 2 seconds.");
  delay(2000);
  //calibrate(10000, &offset_x, &offset_y, &offset_z);
  Serial.println("");
  //----------------------------------

  //Ethernet
  Ethernet.begin(mac, ip);
  //Serial.begin(9600);
  delay(1000);
  Serial.println("Connecting...");
  if (client.connect(server, tcp_port)) { // Connection to server
    Serial.println("Connected to server.js");
    client.println();} 
  else {
    Serial.println("connection failed");}
  //----------------------------------
}

void loop()
{
  //tiltsensor
  acc_x = icm20600.getAccelerationX();
  acc_y = icm20600.getAccelerationY();
  acc_z = icm20600.getAccelerationZ();
  roll = atan2((float)acc_y, (float)acc_z) * 57.3;
  pitch = atan2(-(float)acc_x, sqrt((float)acc_y * acc_y + (float)acc_z * acc_z)) * 57.3;
  //----------------------------------

  //bytearray
  array[0] = byte(roll);
  array[1] = byte(pitch);
  //----------------------------------

  //test
  Serial.write(array, 8);
  Serial.println();
  delay(500); 
  //----------------------------------


  //Ethernet
  if (client.available()) {
      //client.print(array);
      //client.write(array[0]);
      client.write(array, 8);
      //client.write(array, 8);//((uint8_t*) array, sizeof(array));
      delay(3000); 
    }
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    for(;;)
      ;
  }
  //----------------------------------
}

`

TCP服务器(python):

`

代码语言:javascript
复制
# echo-server.py
import time
import socket

HOST = "192.168.X.X"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            #msg = s.recv(1024)
            #print(msg.decode("utf-8"))
            print(data.decode("utf-8"))
            #time.sleep(3)
            #conn.sendall(data)
            if not data:
                break
            conn.send(data)

`

我能够建立到服务器的连接,客户端可以给它写信。但是,我会得到UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa4 in position 0: invalid start byte类型错误。

EN

回答 2

Stack Overflow用户

发布于 2022-12-01 08:34:08

我取得了一些进展,

对于Arduino:

代码语言:javascript
复制
#include <Ethernet.h>
#include <SPI.h>
#include "AK09918.h"
#include "ICM20600.h"
#include <Wire.h>
//----------------------------------

//tiltsensor
AK09918_err_type_t err;
int32_t x, y, z;
AK09918 ak09918;
ICM20600 icm20600(true);
int16_t acc_x, acc_y, acc_z;
int32_t offset_x, offset_y, offset_z;
double roll, pitch;
//----------------------------------

//Ethernet
byte mac[] = { 0xBE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //not important if only one ethernet shield
byte ip[] = { 192, 168, X, XX}; //IP of this arduino unit
byte server[] = { 192, 168, X, XX}; //IP of server you want to contact
int tcp_port = 65432; // a nice port to send/acess the information on
EthernetClient client; 
//----------------------------------


//byte array
union some_data{  //convert a float to 4 bytes
  float tobytes;
  byte bytearray[4];
};

byte array[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //intial array
//----------------------------------

void setup()
{
  //tiltsensor
  Wire.begin();
  err = ak09918.initialize();
  icm20600.initialize();
  ak09918.switchMode(AK09918_POWER_DOWN);
  ak09918.switchMode(AK09918_CONTINUOUS_100HZ);
  Serial.begin(9600);
  err = ak09918.isDataReady();
  while (err != AK09918_ERR_OK) {
      Serial.println("Waiting Sensor");
      delay(100);
      err = ak09918.isDataReady();}
  Serial.println("Start figure-8 calibration after 2 seconds.");
  delay(2000);
  //calibrate(10000, &offset_x, &offset_y, &offset_z);
  Serial.println("");
  //----------------------------------

  //Ethernet
  Ethernet.begin(mac, ip);
  //Serial.begin(9600);
  delay(1000);
  Serial.println("Connecting...");
  if (client.connect(server, tcp_port)) { // Connection to server
    Serial.println("Connected to server.js");
    client.println();} 
  else {
    Serial.println("connection failed");}
  //----------------------------------

  //byte array

  //----------------------------------
}

void loop()
{
  //tiltsensor
  acc_x = icm20600.getAccelerationX();
  acc_y = icm20600.getAccelerationY();
  acc_z = icm20600.getAccelerationZ();
  roll = atan2((float)acc_y, (float)acc_z) * 57.3;
  pitch = atan2(-(float)acc_x, sqrt((float)acc_y * acc_y + (float)acc_z * acc_z)) * 57.3;
  //----------------------------------


  //bytearray
   if (roll < 0) {array[0] = 0;}  //put identifier for positive or negative value in specific posision in byte array
  else {array[0] = 1;}

  if (pitch < 0) {array[5] = 0;} // same for second sensor value
  else {array[5] = 1;}

  union some_data sensor1;  //use the union function separately
  union some_data sensor2;

  sensor1.tobytes =abs(roll); //get byte array for sensor value
  sensor2.tobytes =abs(pitch); //get byte array for sensor value

  for (int i=0; i<sizeof sensor1.bytearray/sizeof sensor1.bytearray[0]; i++) {   //put sensor value byte array into main byte array
    array[1+i] =  sensor1.bytearray[i];
    array[6+i] =  sensor2.bytearray[i];
    }
  //----------------------------------

  //test
  Serial.write(array, sizeof array);
  Serial.println();
  delay(500); 
  //----------------------------------


  //Ethernet
  if (client.available()) {
      //client.print(array);
      //client.write(array[0]);
      client.write(array, sizeof array);
      //client.write(array, 8);//((uint8_t*) array, sizeof(array));
      delay(3000); 
    }
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    for(;;)
      ;
  }
  //----------------------------------
}

对于python。

代码语言:javascript
复制
# echo-server.py
import time
import socket

HOST = "192.168.XX.XX"  # Standard loopback interface address (localhost)
PORT = 65432  # Port to listen on (non-privileged ports are > 1023)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    conn, addr = s.accept()
    with conn:
        print(f"Connected by {addr}")
        while True:
            data = conn.recv(1024)
            #msg = s.recv(1024)
            #print(msg.decode("utf-8"))
            print(data)#.decode("utf-8"))
            #time.sleep(3)
            #conn.sendall(data)
            if not data:
                break
            conn.send(data)
票数 0
EN

Stack Overflow用户

发布于 2022-12-04 11:31:36

正如评论中提到的@hcheung,在Arduino方面,您可以简单地使用

代码语言:javascript
复制
Serial.write(&roll, 4);
Serial.wirte(&pitch,4);

符号已经以这些字节作为第一位进行编码。例如,请参见维基

在您的python方面,我建议您查看一下模块

对于您的具体情况,只需使用

代码语言:javascript
复制
roll, pitch = struct.unpack("dd", data)

其中"dd"描述了两种d的格式。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74613294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档