python2 到 python3 与字节添加和发送到串口的区别

python2 to python3 differences with byte additions and sending to serial port

目前,我们正在构建一个带有 raspberry pi 和 AX-12 动力舵机的机器人。我们找到了一个 python2 库,我们目前正在移植到 python3,我们在特定方法中查明了问题,该方法在 python3.

中给出了错误

Python 2 版本确实很有魅力

AX_GOAL_LENGTH = 5
AX_WRITE_DATA = 3
AX_GOAL_POSITION_L = 30
AX_START = 255
AX_REG_WRITE = 4

def move(self, id, position):
    self.direction(Ax12.RPI_DIRECTION_TX)
    Ax12.port.flushInput()
    p = [position&0xff, position>>8]
    checksum = (~(id + Ax12.AX_GOAL_LENGTH + Ax12.AX_WRITE_DATA + Ax12.AX_GOAL_POSITION_L + p[0] + p[1]))&0xff
    outData = chr(Ax12.AX_START)
    outData += chr(Ax12.AX_START)
    outData += chr(id)
    outData += chr(Ax12.AX_GOAL_LENGTH)
    outData += chr(Ax12.AX_WRITE_DATA)
    outData += chr(Ax12.AX_GOAL_POSITION_L)
    outData += chr(p[0])
    outData += chr(p[1])
    outData += chr(checksum)
    Ax12.port.write(outData)

我们试过调整这个变量:

Ax12.port.write(bytes(outData,'utf-8'))

现在脚本 运行s,遗憾的是 Servo 将不再工作。

我们还尝试将字节放在字节数组中

result = bytes([Ax12.AX_START, Ax12.AX_START, 
                Ax12.AX_GOAL_LENGTH,Ax12.AX_REG_WRITE,
                Ax12.AX_GOAL_POSITION_L, p[0], p[1], checksum
])
Ax12.port.write(result)

脚本 运行s 但伺服不会 运行。

我认为 python3 和 python2 中对 outData 的操作不同。我找不到应该调整或不同的地方。

有人看到我现在做错了什么吗?

你的字节是不是UTF-8数据;对于您在 0 - 127 范围之外创建的任何 chr() 值,编码为 UTF-8 会产生 两个 字节。

您正在从整数值创建 Unicode 代码点;如果您将这些代码点限制为 0 到 255 之间的整数,则它们会创建 Latin-1 代码点;原则上,您可以编码为 'latin1' 以再次获取字节,但首先创建字节要容易得多。

在 Python 3 中,使用 bytes 类型,从整数列表创建:

def move(self, id, position):
    self.direction(Ax12.RPI_DIRECTION_TX)
    Ax12.port.flushInput()
    p = [, position>>8]
    checksum = (~(id + Ax12.AX_GOAL_LENGTH + Ax12.AX_WRITE_DATA + Ax12.AX_GOAL_POSITION_L + p[0] + p[1]))&0xff
    outData = bytes([
        Ax12.AX_START, Ax12.AX_START, id,
        Ax12.AX_GOAL_LENGTH, Ax12.AX_WRITE_DATA,
        Ax12.AX_GOAL_POSITION_L, p[0], p[1], checksum])
    Ax12.port.write(outData)

您自己的尝试未包含 id 值,您使用的是 AX_REG_WRITE 而不是 AX_WRITE_DATA

您也可以使用 bytearray() object,这样您就可以附加额外的字节;您可以使用它通过引用到目前为止生成的字节来计算校验和,避免重复自己(错误的常见来源):

def move(self, id, position):
    self.direction(Ax12.RPI_DIRECTION_TX)
    Ax12.port.flushInput()
    outData = bytearray([
        Ax12.AX_START, Ax12.AX_START, id,
        Ax12.AX_GOAL_LENGTH, Ax12.AX_WRITE_DATA,
        Ax12.AX_GOAL_POSITION_L, position & 0xff, position >> 8])
    checksum = ~sum(outData[2:]) & 0xff
    outData.append(checksum)
    Ax12.port.write(outData)

当然你也可以使用串联(outData = bytes([...])outData += bytes([checksum]))但是bytearray在Python 2中也可用,所以上面的版本与两者兼容主要 Python 版本。