首页 > 解决方案 > 如果字符串太长,则无法从功率计获得响应

问题描述

我正在使用此代码与功率计进行通信:

def Hello() :
    answer = SendMessage("\x10\x49\x01\x00\x4A\x16","100b01000c16")
    if answer == 1:
        answer = SendMessage("\x10\x40\x01\x00\x41\x16","100001000116")
    if answer == 1:
        answer = SendMessage("\x10\x49\x01\x00\x4A\x16","100b01000c16")
    if answer == 1:
        answer = SendMessage("\x68\x0D\x0D\x68\x73\x01\x00\xB7\x01\x06\x01\x00\x00\x01\x00\x00\x00\x34\x16","100001000116")   
    if answer ==  1:
        input3 = input ("progress")

def SendMessage(message, expected):
    out = ''
    while out == '':
        # send the character to the device
        print (message)
        ser.write(message.encode())
        #Let's wait one second before reading output (let's give device time to answer)
        time.sleep(0.02)
        while ser.inWaiting() > 0:
            out += ser.readline().hex()
            if out != '':
                print (">>>>" + out)
                if out == expected:
                    print("Correct response")
                    out = ''
                    answer = 1
                    return answer
                else:
                    print("Incorrect response")
                    answer = 0
                    return answer

OpenComm = Hello()

代码远非理想。它现在只是一个概念证明。

根据我从同一个功率计获得的日志,当我发送

68 0D 0D 68 73 01 00 B7 01 06 01 00 00 01 00 00 00 34 16

它应该回复

10 00 01 00 01 16

但是现在,当我发送该特定消息时,它什么也没做(尽管它确实响应了以前的消息)。会不会是十六进制太长了?如果是这样,关于如何解决这个问题的任何想法?

这就是我配置串行端口的方式:

ser = serial.Serial(
    port = "COM3",
    baudrate=9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_TWO,
    bytesize=serial.EIGHTBITS,
    timeout=1
)

标签: pythonpython-3.xpyserial

解决方案


您的代码中有一个很小但很重要的问题。

您将原始字节用作字符串的表示法"\x10\x49\x01\x00\x4A\x16"实际上应该是b"\x10\x49\x01\x00\x4A\x16".

当您发送短命令时这没有问题,因为这些命令没有任何非 ASCII 字符。但是根据您的长期命令,您拥有\xB7. 如果您尝试以下操作:

>>> b"\xb7"=="\xb7".encode()

在你的 Python 解释器上,你会得到:False.

如果你这样做:

>>> "\x68\x0D\x0D\x68\x73\x01\x00\xB7\x01\x06\x01\x00\x00\x01\x00\x00\x00\x34\x16".encode()

你会得到:

b'h\r\rhs\x01\x00\xc2\xb7\x01\x06\x01\x00\x00\x01\x00\x00\x004\x16'

所以你在编码时会看到"\xB7

>>> "\xb7".encode()

你得到b'\xc2\xb7'的意思是你正在发送一个虚假字节。

要修复它,只需更正添加到命令的符号并在写入端口时b"...删除。.encode()

在意识到问题之前,我认为您的命令的语法可能有问题。但是检查这个文档,一切似乎都井井有条(除了设备地址和校验和,您的命令与第 83 页上的完全相同)。我不能 100% 确定修复符号会解决您的问题,但我非常乐观。

编辑:正如下面评论中所讨论的,还有一个事实是serial.write()作为非阻塞工作的,所以它会立即返回。由于将一定数量的字节写入总线(以波特率指示的速度)需要一些时间。针对您的情况进行粗略计算,如果您等待 20 毫秒(使用time.sleep(0.02)),缓冲区将写入大约 9600 bps*(20ms/1000ms)*0.1bytes/1bit=19 字节。

这对于您的短命令可能已经足够了,但考虑到您应该留出一小段时间让仪表有时间对命令做出反应并发送回它的答案,对于长命令,您可能需要将延迟增加到大约 50- 100 毫秒。


推荐阅读