2016-09-18 4 views
1

Солнечный инвертор (Delta RPI M6A) имеет магистральную шину RS485. Мастер запрашивает инвертор несколько раз в секунду для отправки набора данных ответа, который затем делает инвертор. Общий набор связи составляет 176 байт. Raspberry Pi 3B подключается к этой шине с использованием конвертера ICI FT-232 (USB-последовательный) (FT-32).Отсутствие байтов при чтении данных RS485 с использованием pySerial (инвертор солнечной батареи Delta)

Программа Python используется для чтения данных, передаваемых по шине. Это прекрасно работает, только если нет байтов, которые интерпретируются как специальные символы (по крайней мере, это то, что я думаю). Я сначала прочитал ввод 1 байт за раз. После того, как была найдена правильная последовательность «начала передачи» (STX, за которой следует ACK, за которым следует инверторID = 1), тогда ожидается набор данных из 160 байтов плюс конечная последовательность. Последнее байтовое чтение должно быть ETX (= ascii 3).

Ожидаемый результат: Screenshot of expected output

Я думаю, что проблема в том, что если некоторые из байтов являются эквивалентом специальных символов, таких как побег или перевод строки, то эти байты не «видели» в ser.read(). Затем я получу байт ETX на несколько байт раньше, указав, что некоторые байты где-то посередине не были захвачены.

Соответствующая часть кода:

if bytes_to_read == 1: 
    raw_data = ser.read() 
    pos = pos + 1; 
    # print pos; 
    if ord(raw_data) == 2:         # 2 = start of text character 
     pos = 1; 
     print str(pos) + ' ' + str(ord(raw_data)) 
    elif pos == 2 and ord(raw_data) == 6:     # 6 = acknowledge character 
     ack = True; 
     print str(pos) + ' ' + str(ord(raw_data)) 
    elif pos == 2 and ord(raw_data) != 6:     # 6 = acknowledge character 
     ack = False; 
     print str(pos) + ' ' + str(ord(raw_data)) + ' ack reset to False' 
    elif pos == 3 and ack and ord(raw_data) == 1: 
     bytes_to_read = 164; 
     print str(pos) + ' ' + str(ord(raw_data)) 
elif bytes_to_read == 164: 
    raw_data_byte = ser.read(164) 
    print len(raw_data_byte); 
    bytes_to_read = 1; 
    ack = False; 
    print 'got to read 164 bytes, first byte is ' + str(ord(raw_data_byte[0])) + ', last byte: ' + str(ord(raw_data_byte[163])); 
    if ord(raw_data_byte[0]) == 160 and ord(raw_data_byte[163]) == 3:      # 160 = data bytes specified by sender 
     print ('ready to process ' + str(len(raw_data_byte)) + ' bytes') 
     supplied_power_byte1 = bin(ord(raw_data_byte[101]))[2:].zfill(8) 
     supplied_power_byte2 = bin(ord(raw_data_byte[102]))[2:].zfill(8) 

Захваченные байты позже обработаны, чтобы разрешить запись в базу данных.

Я пробовал ser.read() и ser.readline() с тем же результатом.

Я был бы признателен за любые намеки, которые укажут мне в правильном направлении.

Спасибо, Bram

ответ

0

Решение было установить все специальные символы последовательного интерфейса к 'неопределенным', с помощью командной строки:

[email protected]:~ $ stty -F /dev/RS-485 intr ^- 

где '/ DEV/RS-485' является символической ссылкой на настоящий USB-порт, а «intr» - это пример имени специального символа. Когда это будет сделано для каждого специального символа (все они могут быть добавлены к вышеуказанной командной строке), параметры порта выглядеть следующим образом:

[email protected]:~ $ stty -F /dev/RS-485 -g 
1400:4:cbe:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0 

Чтобы увидеть настройки в более удобочитаемом формате, используйте команду

[email protected]:~ $ stty -F /dev/RS-485 -a 

Все байты теперь входят в ожидании.