[英]decoding a Byte Array sent from arduino to TCP Server made with Python
我正在将传感器数据转换为字节,并将字节数组从 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 服务器(蟒蛇):
`
# 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
type 错误。
我能够取得一些进步,
对于 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 TCP 服务器。
# 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.