PySerial read () пропускает начало данных кадра - PullRequest
0 голосов
/ 08 января 2019

Я хочу написать программу, которая взаимодействует с интеллектуальными счетчиками (электричество, тепло и т. Д.) По протоколу Метр-шина . У меня есть M-Bus <-> RS232 конвертер и RS232 <-> USB.

Когда я тестирую свой скрипт Python с помощью теплосчетчика, отправляя ему команду, он отвечает мне длинным, но правильным кадром, а затем, если я запрашиваю его снова вскоре после того, как получаю только частичный ответ кадра. Ожидание около 30 секунд помогает правильно получить весь кадр. Этот частичный ответ всегда один и тот же. Кадры учета теплосчетчиков

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

Также есть команда, которая инициализирует ведомое устройство - ведомое устройство отвечает '\ xE5', хотя я вижу мигание диода Rx, я не могу поймать этот единственный байт.

Что я пробовал:

  1. Я пытался прочитать определенно больше байтов, чем могло быть в моем буфере, как ser.read(500)

  2. Пробовал с использованием ser.inwaiting, но он вернул бы 0, пока я не использовал time.sleep(1) до этого

  3. Загрузка кусков байтов из pySerial inWaiting возвращает неверное количество байтов

  4. Управление xonxoff параметром и timeout.

Все без эффекта.

import serial
import time

def ser_to_mbus():
    ser = serial.Serial(
        port='COM4', 
        baudrate=2400, 
        bytesize=serial.EIGHTBITS,
        parity=serial.PARITY_EVEN,
        stopbits=serial.STOPBITS_ONE,
        timeout=2,
        #write_timeout=1,
        xonxoff=False,
        rtscts=False,
        dsrdtr=False,
        #inter_byte_timeout=0.01,
        )
    # Should receive a hex response '\xE5' with command below.
    #to_send = b'\x68\x0B\x0B\x68\x73\xFD\x52\x84\x11\x10\x00\xFF\xFF\xFF\xFF\x63\x16'
    #to_send = b'\x10\x7B\x01\x7C\x16' # heat meter request frame
    to_send = b'\x10\x7B\xFD\x78\x16' # electricity meter request frame
    ser.write(to_send)
    ser.close()

def mbus_to_ser():
    ser = serial.Serial(
        port='COM4', 
        baudrate=2400, 
        bytesize=serial.EIGHTBITS,
        parity=serial.PARITY_EVEN,
        stopbits=serial.STOPBITS_ONE,
        timeout=1,
        #write_timeout=1,
        xonxoff=1,
        rtscts=False,
        dsrdtr=False,
        #inter_byte_timeout=0.2,
        )
    time.sleep(1) # Otherwise ser.in_waiting is empty. 
    buffer_size = ser.in_waiting
    frame = ser.read(buffer_size)
    return frame

ser_to_mbus()
frame = mbus_to_ser()
print(frame)

Я отслеживал кадры M-Bus с EMU и мой последовательный порт с Serial Port Monitor . Кадры, отправленные и полученные EMU, всегда правильные, как и в Serial Monitor. Если я использую свой код для отправки и получения фреймов, Serial Monitor получает те же результаты, что и в моем терминале - он видит неправильные, «нарезанные» фреймы.

Устройства отвечают только после получения правильных запросов (я вижу, мигает диод Rx).

Я не знаю, есть ли проблема с многопоточностью, или с буфером, или, может быть, сценарий Python недостаточно быстр, чтобы перехватить все байты из буфера?

...