Протокол последовательной связи в двоичном формате - получение неожиданного ответа - PullRequest
0 голосов
/ 06 января 2020

Я пытаюсь использовать Python3 на Raspberry для связи с последовательным устройством. Протокол выглядит следующим образом:

  1. Хост отправляет байт команды (содержит адрес и тип данных)
  2. Байт команды echos устройства
  3. Хост отправляет байт операнда (больше типа данных) info)
  4. Байт эхо-операнда устройства, а также первый байт данных
  5. Хост-эхо первого байта данных. Устройство отправляет второй байт данных. Повторяйте до 5 байтов данных

Устройство должно получать и отправлять только в двоичном формате (в соответствии с устаревшим руководством, на которое я ссылаюсь), но когда я запрашиваю второй байт данных, я получаю "\ т "или какой-то другой странный символ. Кажется, что команда, операнд и первый байт данных работают должным образом. Но после этого у меня появляются неожиданные персонажи.

На самом ли деле устройство взаимодействует не в двоичном формате?

Мои таланты в коде все еще находятся на ранней стадии развития, поэтому игнорируйте чрезмерное использование команд печати. Не стесняйтесь придираться, когда я новичок ..

import serial
import time
import binascii

ser = serial.Serial(
    port='/dev/ttyUSB0',\
    baudrate=9600,\
    parity=serial.PARITY_NONE,\
    stopbits=serial.STOPBITS_ONE,\
    bytesize=serial.EIGHTBITS,\
    timeout = 2)

command=b"\x92"
operand =b"\x02"
sleepy = 0.2
data = bytearray()



while True:
    ser.write(command) #send command byte
    time.sleep(sleepy)
    print(ser.read(1)) #recieve command byte
    time.sleep(sleepy)


    ser.write(operand) #send operand byte
    time.sleep(sleepy)
    echo = ser.read(2)#recieve operand byte & first data byte
    print(echo)        
    time.sleep(sleepy)
    data.append(echo[1])

    ser.write(bytearray([echo[-1]])) #send first data byte echo
    time.sleep(sleepy)
    echo = ser.read(10) #recieve second data byte
    print(echo)
    time.sleep(sleepy)
    data.append(echo[-1])
    print(echo[-1])

    ser.write(bytearray([echo[-1]]))    #send second data byte echo
    time.sleep(sleepy)
    echo = ser.read(10) #recieve third data byte
    print(echo)
    time.sleep(sleepy)
    data.append(echo[-1])
    print(echo[-1])

    ser.write(bytearray([echo[-1]]))    #send third data byte echo
    time.sleep(sleepy)
    echo = ser.read(10) #recieve fourth data byte
    print(echo)
    time.sleep(sleepy)
    data.append(echo[-1])
    print(echo[-1])

    ser.write(bytearray([echo[-1]]))    #send fourth data byte echo
    time.sleep(sleepy)
    echo = ser.read(10) #recieve 5th data byte
    print(echo)
    time.sleep(sleepy)
    data.append(echo[-1])
    print(echo[-1])
    print(data)




ser.close()

Например, когда я запускаю это, я получаю массив данных "(b '\ x04 \ x08hT ^')". Я всегда получаю первый \ x04, но символы после него случайные.

1 Ответ

0 голосов
/ 24 февраля 2020

Я с тех пор заставил эту программу работать. Я все еще получаю данные с некоторыми неожиданными символами, но использую binascii.hexlify , а затем "{: 08b}". Format (int (c [1], base = 16)) для преобразовать его в 8-битный двоичный файл, который мне нужен. Вот посмотрите на то, что, кажется, работает. Для контекста, эта программа собирает данные из анализатора влажности. Таким образом, математика внизу состоит в том, чтобы преобразовать 40-битный двоичный код в значение с плавающей точкой.

def get_h20():
data = bytearray()
echo = bytearray()
command=bytearray([146])
operand =bytearray([1])
sleepy = 0.02

ser = serial.Serial(
port='/dev/ttyUSB1',\
baudrate=9600,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout = 0)

data = bytearray()
ser.write(command) #send command byte
time.sleep(sleepy)
echo = ser.read(1) #recieve command byte
data = data + echo


ser.write(operand)
time.sleep(sleepy)
echo = ser.read(2)
data = data + echo

ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo

ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo

ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo


ser.write(bytearray([echo[-1]]))
time.sleep(sleepy)
echo = ser.read(1)
data = data + echo
return(data)

ser.close()

преобразует необработанные данные h2o в ppb

def raw_to_ppb (data):

raw_hex = str(binascii.hexlify(data[2:]))
c = [raw_hex[i:i+2] for i in range (0, len(raw_hex), 2)]
try:
    byte1 = "{:08b}".format(int(c[1], base=16))
    byte2 = "{:08b}".format(int(c[2], base=16))
    byte3 = "{:08b}".format(int(c[3], base=16))
    byte4 = "{:08b}".format(int(c[4], base=16))
    byte5 = "{:08b}".format(int(c[5], base=16))

    h20_bin = byte1+byte2+byte3+byte4+byte5

    m1 = h20_bin[14:16]
    m2 = h20_bin[17:24]
    m3 = h20_bin[25:32]
    m4 = h20_bin[33:40]
    m = m1+m2+m3+m4

    mantissa =      (int(m[0])*2**22+int(m[1])*2**21+int(m[2])*2**20+int(m[3])*\
                2**19+int(m[4])*2**18+int(m[5])*2**17+int(m[6])*2**16+int(m[7])*\
                2**15+int(m[8])*2**14+int(m[9])*2**13+int(m[10])*2**12+int(m[11])*\
                2**11+int(m[12])*2**10+int(m[13])*2**9+int(m[14])*2**8+int(m[15])*\
                 2**7+int(m[16])*2**6+int(m[17])*2**5+int(m[18])*2**4+int(m[19])*\
                 2**3+int(m[20])*2**2+int(m[21])*2**1+int(m[22])*2**0)/8388608

    e1 = h20_bin[5:8]
    e2 = h20_bin[9:14]
    e = e1+e2
    exponent = int(e,2)
    sign = (-1)**(int(h20_bin[4],2))

    h20_ppb = sign*(2**(exponent-127))*(1+mantissa)

    return(str(h20_ppb))
except:
    pass

Я все еще хотел бы узнать больше о формате данных, которые получают от анализатора. Если я печатаю переменную данных из функции get_h2o, то я все равно получаю странные ответы "b '\ x04 \ x08hT ^" ... но, похоже, python знает, что с ней делать.

...