我正在将传感器数据转换为字节,并将字节数组从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客户:`
#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):
`
# 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类型错误。
发布于 2022-12-01 08:34:08
我取得了一些进展,
对于Arduino:
#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。
# 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)https://stackoverflow.com/questions/74613294
复制相似问题