当强制转换为浮点时,很难用pyserial解释字节流

2024-04-25 13:31:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我用pyserial从USB设备获取数据流。 当我使用他们的专有软件时,我得到一个绘图更新和滚动,看起来像:

enter image description here

制造商提供了以下信息表,非常有帮助:

enter image description here

所以我写了一些在我看来完全合乎逻辑的代码,好像它应该起作用:

import serial
import struct

device = '/dev/cu.usbserial-DM003616' #osx
ser = serial.Serial(device, 115200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE, rtscts=False, dsrdtr=False)

bytes = ser.read(500)

splitby = 11
for i in range(splitby):
    offset = i
    for i in range(len(bytes)//splitby):
        datum = bytes[i*splitby+offset:(i+1)*splitby+offset]
        float = datum[2:6]
        float = struct.unpack('!f',float)
        print(float)

给出上面的曲线图,以及数据文件中的例子,我期望一个浮点值,范围可能是-100到+100。在

但我只是胡言乱语:

^{pr2}$

外循环的原因是我想知道是否可以通过最多偏移11个字节来理解数据(因为我想知道我是否开始在11字节段的中间轮询设备),但是不管数据是什么都是无稽之谈。在

有人对我如何理解这些数据有什么建议吗?在

500长度的字节串示例如下:

b'\xaaUA\xd4,\xc0\xbbL\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd5\x15\xed\xbbM\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd0p\x84\xbbN\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xb3)\xbbO\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xc4\xb74\xbbP\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xca\x118\xbbQ\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf(A\xbbR\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd6f\x0f\xbbS\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd5\x8f\x97\xbbT\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd0)\xb3\xbbU\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd-\xd9\xbbV\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf\x1f\\\xbbW\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd6\xbf\xf9\xbbX\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd90\xed\xbbY\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xddp\x15\xbbZ\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd7\x91c\xbb[\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd4$\xad\xbb\\\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf\x88\xa9\xbb]\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf\xa9\x18\xbb^\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xce\xae{\xbb_\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcc\x89+\xbb`\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd0\x08\x83\xbba\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd4\xdb\xb5\xbbb\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd95a\xbbc\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd70\xa8\xbbd\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd3#`\xbbe\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xa4]\xbbf\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xa0L\xbbg\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xe5\xd7\xbbh\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xce\xd5\xec\xbbi\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd;#\xbbj\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd'

附录:对不起,我不清楚。它开始工作正常,但后来失败了。例如,如果我使用上面的字节字符串,我们从良好的数据开始:

(26.5218505859375,)

但这很快就归结为:

(1.408765983841204e-38,)
(0.0,)
(-16140921856.0,)
(-1.1925119585221935e-23,)
(0.0,)
(-1.0772448149509728e-05,)
(4.021874795388587e+23,)
(0.0,)

附录:下面的答案很好,但在此期间,我使用regex提出了我自己的解决方案,它似乎工作得非常好:

class PLD():
    def __init__(self, device='COM5'):

        self.device = device        # self.device = '/dev/cu.usbserial-DM003616' #osx
        self.sample_rate = 1/0.0256
        self.ser = serial.Serial(device, 115200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE, rtscts=False, dsrdtr=False)

    def get_data(self,n=500):
        regexp = '\\xaa.+?\\xbb'
        floats = []
        serial_data = self.ser.read(n)
        for match in re.findall(regexp, serial_data):
            serial_data = match[2:6]
            try:
                datum = struct.unpack('!f', serial_data)[0]
                floats.append(datum)
            except struct.error:
                floats.append(0)
        return floats

Tags: selffalsedatadeviceserialfloatstructser
2条回答

问题是,你所依赖的是永远不会失去一部分传输或得到任何腐败,这两种假设都是有缺陷的。 您需要对页眉字节执行等待/检查,理想情况下对页脚字节执行相同的等待/检查:

#!python3
import struct

class FakeSerial():
    def __init__(self):
        self.data = b'\xaaUA\xd4,\xc0\xbbL\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd5\x15\xed\xbbM\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd0p\x84\xbbN\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xb3)\xbbO\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xc4\xb74\xbbP\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xca\x118\xbbQ\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf(A\xbbR\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd6f\x0f\xbbS\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd5\x8f\x97\xbbT\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd0)\xb3\xbbU\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd-\xd9\xbbV\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf\x1f\\\xbbW\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd6\xbf\xf9\xbbX\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd90\xed\xbbY\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xddp\x15\xbbZ\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd7\x91c\xbb[\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd4$\xad\xbb\\\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf\x88\xa9\xbb]\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcf\xa9\x18\xbb^\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xce\xae{\xbb_\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcc\x89+\xbb`\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd0\x08\x83\xbba\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd4\xdb\xb5\xbbb\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd95a\xbbc\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd70\xa8\xbbd\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xd3#`\xbbe\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xa4]\xbbf\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xa0L\xbbg\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd\xe5\xd7\xbbh\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xce\xd5\xec\xbbi\x00\x00\x00\x00\x00\x00\x99f\xaaUA\xcd;#\xbbj\x00\x00\x00\x00\x00\x00\x99f'
        self.index = 0

    def read(self, num=1):
        data = self.data[self.index : self.index+num]
        self.index += num
        if self.index > len(self.data):
            self.index = 0
        return data

s = FakeSerial()

while True:
    if s.read() == b'\xaa': # wait for header 1 because of loop
        if s.read() == b'\x55': # check  header 1 followed immediately by header 2
            data = s.read(4) # get the data
            print(struct.unpack('!f',data)) # unpack it

            # choose one of these methods, not both
            # 1
            padding = s.read(10) # this should read the tag, count, reserved and footer bytes

            # 2
            # this instead loops waiting for footer bytes
#           while True: 
#               if s.read() == b'\x99': # footer 1
#                   if s.read() == b'\x66': # footer 2
#                       break

我做了一个假的串行类,这样我就可以写一个更接近你实际使用它的例子,所以你可以忽略这一点,但是请注意,我从你的示例代码末尾删除了一些字节,因为它是一个不完整的数据帧。在

其结果是:

^{pr2}$

这个数据看起来对吗?在

by=b'\x41\xd4\x2c\xc0'
print(list(by))
print(struct.unpack('!f',by))

输出:

^{pr2}$

我看过你的数据,根据你提供的格式信息,第一个数据包似乎编码了一个26.521的浮动。。。在

此外,他们提供的样本数据似乎可以正确解码:

by=b'\xc0\x59\x99\x99'
print(list(by))
print(struct.unpack('!f',by))

输出:

[192, 89, 153, 153]
(-3.3999998569488525,)

一般来说,你需要编写一些软件来依次读取每个字节,当你找到一个0xaa字节时,也要读取接下来的15个字节,并检查所有常量字节是否都在正确的位置:([0xaa,0x55]…[0xbb].[0,0,0,0,0,0,0,0,0,0,0x99,0x66]),然后可以将字节2..5传递到unpack()。在

相关问题 更多 >