【问题标题】:Problem with Serial.read() and Struct.pack / serial communication between Arduino and Python (3.x)Arduino 和 Python (3.x) 之间的 Serial.read() 和 Struct.pack / 串行通信问题
【发布时间】:2019-09-04 09:31:42
【问题描述】:

我在尝试使用 串行通信 将一些值从 Python 3.x 发送到 Arduino 时遇到问题。
小于 255 时正常,大于 255 时会报错。

我在 Python 中使用 Struct.pack,在 Arduino 中使用 Serial.read()


Python 代码:

import cv2
import numpy as np
from serial import Serial
import struct

arduinoData = Serial('com6', 9600)

cap = cv2.VideoCapture(0)
hand_cascade = cv2.CascadeClassifier('hand.xml')

while(True):
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    handdetect = hand_cascade.detectMultiScale(gray, 1.6, 3)

    for (x, y, w, h) in handdetect:   
        cv2.rectangle(frame, (x, y), (x + w, y + h), (127, 127, 0), 2)

        xcenter = int(x + w/2)
        ycenter = int(y + h/2)

        #This is where i send values to serial port
        arduinoData.write(struct.pack('>II',xcenter,ycenter))

    cv2.imshow('Webcam', frame)
    k = cv2.waitKey(25) & 0xff
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

Arduino 代码:

int SerialData[8];
const int led = 7;
int xcenter;
int ycenter;

void setup(){
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}

void loop(){
  if (Serial.available() >= 8){
    for (int i = 0; i < 8; i++){
      SerialData[i] = Serial.read();
    }
    xcenter = (SerialData[0]*1000) + (SerialData[1]*100) + (SerialData[2]*10) + SerialData[3];
    ycenter = (SerialData[4]*1000) + (SerialData[5]*100) + (SerialData[6]*10) + SerialData[7];

    if (xcenter <= 200){
      digitalWrite(led, LOW);
    }
    else if(xcenter > 200){
      digitalWrite(led, HIGH);
    }
   //Serial.flush();
  }
}

就像我在本主题开头所说的那样,当xcenter &gt; 200 &amp;&amp; xcenter &lt;= 255 时,LED 亮起(这意味着代码工作正常)。
但是当xcenter &gt; 255 时,LED 熄灭(这里有问题)。
我想我已经读取了 Arduino 代码中的所有 8 个字节,并在 struct.pack 中使用了 unsigned int &gt;II,那么我的错误是什么以及在哪里?
我很感激所有的帮助!谢谢!


编辑和修复。
“它不会将 int 打包成数字 (0-9),而是将它们打包成字节 (0-255)”_

所以这是错误的:

xcenter = (SerialData[0]*1000) + (SerialData[1]*100) + (SerialData[2]*10) + SerialData[3];  
ycenter = (SerialData[4]*1000) + (SerialData[5]*100) + (SerialData[6]*10) + SerialData[7];  

改成这个(对于大值):

long result = long((unsigned long(unsigned char(SerialData[0])) << 24) | (unsigned long(unsigned char(SerialData[1])) << 16)
            | (unsigned long(unsigned char(SerialData[2])) << 8) | unsigned char(SerialData[3])); 

或者改成这个(对于小值):

xcenter = (SerialData[2]*256) + SerialData[3];
ycenter = (SerialData[6]*256) + SerialData[7]; 

或者这个(也适用于小值):

int result = int((unsigned int(unsigned char(SerialData[2])) << 8) | unsigned char(SerialData[3]));

代码会完美运行!

【问题讨论】:

  • 它不会将 int 打包成数字 (0-9),而是将它们打包成字节 (0-255)。 256 被打包到 00 00 01 00 中,您将其解压缩为 10x1,而 255 是 00 00 00 ff,在您的情况下为 1x255。将 10 的幂更改为 256 (2^8) 的幂。或者不要打包它们,只需将它们转换为字符串,例如 "{:04d}{:04d}".format(intA, intB)
  • 感谢@IcedLance 向我展示了我的错误。我是代码新手,请问第一个字节代表什么?。
  • 您可以查看 this link 以了解其工作原理,但简而言之:十进制(以 10 为底)从 0 变为 9,因此 356 = 3*10*10 + 5*10 + 6 而字节从 0 到 255,这意味着 03 05 06 = 3*256*256 + 5*256 + 6。我用 2 个字母写它们,因为通常用成对的十六进制数字表示字节值(基数 16 , 256=16*16)。在您的情况下,第一个字节基本上代表`xcenter /(256 * 256 * 256)。在 xcenter 大于 256^3 之前,它将为 0。
  • 亲爱的@IcedLand,谢谢你的帮助,我已经解决了我所有的问题!你拯救了我的一天,再次感谢,祝你有美好的一天!最好的尊重。
  • @IcedLance 请将解决方案作为答案发布并接受!

标签: python-3.x arduino serial-port pyserial serial-communication


【解决方案1】:

对于较大的值,此代码将无法正常工作...

int xcenter = (SerialData[0]*256*256*256) + (SerialData[1]*256*256) + (SerialData[2]*256) + SerialData[3];

问题是输入是4字节宽,是一个长整数,而arduino上的整数大小只有2字节宽,也就是说256 * 256 = 0x10000 & 0xFFFF = 0!

为确保您不会遇到超过 2 个字节的值的问题,必须使用移位操作。

这给出了:

long result = long((unsigned long(unsigned char(SerialData[0])) << 24) | (unsigned long(unsigned char(SerialData[1])) << 16)
            | (unsigned long(unsigned char(SerialData[2])) << 8) | unsigned char(SerialData[3]));

或者,如果您不期望较大的值,则仅使用输入中的两个字节。确保使用无符号值进行微积分,否则您可能会遇到问题!!!

int result = int((unsigned int(unsigned char(SerialData[2])) << 8) | unsigned char(SerialData[3]));

这非常冗长,但对所有输入类型都是安全的。例如,如果 SerialData[] 是一个 char 数组,则 OP 提出的解决方案将不起作用,它应该是,以避免浪费内存。

【讨论】:

  • 谢谢你带给我的知识,真的对我帮助很大!
  • 不客气。我知道这些小细节会浪费多少时间。
  • 我已修复并将您的知识添加到我的主题中,供其他需要的人使用!再次感谢@Michael Roy
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多