我使用pyserial从USB设备获取数据流。 当我使用他们的专有软件时,我会得到一个更新和滚动的情节,如下所示:
制造商提供此信息表非常有用:
所以我编写的代码对我来说似乎完全符合逻辑,并且它应该可以工作:
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范围。
但我得到完全的胡言乱语:
(5.502899069403557e-41,)
(-2.350988701644575e-38,)
(33.033477783203125,)
(1.408765983841204e-38,)
(0.0,)
(9.839021882302715e-36,)
(-1.1925119585221935e-23,)
(0.0,)
(1.9816933148201242e-21,)
(4.0218751556765575e+23,)
(0.0,)
(98320384.0,)
(-1.894110546575914e-13,)
外部循环的原因是我想看看我是否可以通过将其偏移最多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'
ADDENDUM:抱歉,我不清楚。它开始工作正常,但然后失败。例如,如果我使用上面的字节字符串,我们从良好的数据开始:
(26.5218505859375,)
但这很快就会进入:
(1.408765983841204e-38,)
(0.0,)
(-16140921856.0,)
(-1.1925119585221935e-23,)
(0.0,)
(-1.0772448149509728e-05,)
(4.021874795388587e+23,)
(0.0,)
ADDENDUM:下面标记的答案很好,但是在过渡期间我使用正则表达式提出了我自己的解决方案,这似乎完全正常:
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
答案 0 :(得分:1)
问题在于你依赖于永不丢失部分传输或遭受任何腐败,这两者都是有缺陷的假设。 你需要对头字节实现等待/检查,理想情况下对于页脚字节是相同的:
#!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
我创建了一个假的序列类,所以我可以写一个更接近你实际需要使用它的例子,所以你可以忽略那一点,但请注意我从你的示例代码的末尾删除了几个字节,因为它是数据框不完整。
这个输出是:
(26.5218505859375,)
(26.635705947875977,)
(26.05493927001953,)
(25.712480545043945,)
(24.589454650878906,)
(25.258407592773438,)
(25.894655227661133,)
(26.799833297729492,)
(26.695112228393555,)
(26.020360946655273,)
(25.64738655090332,)
(25.89031219482422,)
(26.84373664855957,)
(27.148889541625977,)
(27.67972755432129,)
(26.94598960876465,)
(26.517908096313477,)
(25.941728591918945,)
(25.957565307617188,)
(25.835195541381836,)
(25.56697654724121,)
(26.0041561126709,)
(26.60727882385254,)
(27.151063919067383,)
(26.898757934570312,)
(26.39227294921875,)
(25.70525550842285,)
(25.703269958496094,)
(25.737226486206055,)
(25.854454040527344,)
(25.65387535095215,)
答案 1 :(得分:0)
这些数据看起来是否合适?
by=b'\x41\xd4\x2c\xc0'
print(list(by))
print(struct.unpack('!f',by))
输出:
[65, 212, 44, 192]
(26.5218505859375,)
我查看了你的数据并根据你提供的格式信息,第一个数据包似乎编码了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,0x99,0x66])然后你可以将字节2..5传递给unpack()
。