Отправка шестнадцатеричного по серийному номеру с помощью python

В эти выходные я собираюсь сделать небольшой проект. У меня есть инвертор на солнечных батареях (Danfoss ULX 3600i), который я попытаюсь подключить к своей машине с Linux, чтобы посмотреть, смогу ли я получить от него данные, сколько энергии было создано, например, для статистики. На нем есть вход для подключения RJ45, но с RS485.

Я получил кабели для подключения его через USB-порт в ПК с преобразователем RS485 между ПК и инвертором.

Затем я пишу небольшой код на Python, чтобы сделать запрос. Однако я не могу понять, как правильно отправить данные.

import serial
import struct

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

print(ser.isOpen())
thestring = "7E FF 03 00 01 00 02 0A 01 C8 04 D0 01 02 80 00 00 00 00 8E E7 7E"
data = struct.pack(hex(thestring))
#data = struct.pack(hex, 0x7E, 0xFF, 0x03, 0x00, 0x01, 0x00, 0x02, 0x0A, 0x01, 0xC8,      0x04, 0xD0, 0x01, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xE7, 0x7E)

ser.write(data)
s = ser.read(1)
print(s)
ser.close()

Инвертор использует протокол Danfoss ComLynx (на страница 26 — это данные, которые я пытаюсь отправить):

РЕДАКТИРОВАТЬ: теперь я могу отправить запрос, так как светодиодный индикатор на преобразователе Adam 4520 RS485 мигает один раз, однако данные не возвращаются, но я получаю эту ошибку, когда я нажимаю CTRL + C в терминале:

dontommy@dtbeast:~/workspace/python_scripting/src$ ./sollar.py 
True
^CTraceback (most recent call last):
  File "./sollar.py", line 30, in <module>
    s = ser.readline().decode('utf-8')
  File "/usr/local/lib/python3.2/dist-packages/serial/serialposix.py", line 446, in read
    ready,_,_ = select.select([self.fd],[],[], self._timeout)
KeyboardInterrupt

person user2199192    schedule 22.03.2013    source источник


Ответы (4)


Перепишите «thestring» как

thestring = "\x7E\xFF\x03\x00\x01\x00\x02\x0A\x01\xC8\x04\xD0\x01\x02\x80\x00\x00\x00\x00\x8E\xE7\z7E"

Вам не нужно его упаковывать, вы можете сказать data=thestring и отправить его. Это будет работать только в том случае, если различные идентификаторы в документе точно совпадают с идентификаторами на вашем оборудовании.

Вам нужно понять, как работает "struct" в python, как кодировать двоичный код и как поместить два 4-битных значения в один 8-битный байт: подсказка, см. >> и ‹‹ операторы и формат struct pack "B"

person Vorsprung    schedule 26.03.2013

Я попробовал несколько схем для преобразования моей командной строки из шестнадцатеричных символов в байты, которые распознавались как шестнадцатеричные на дальнем конце UART, прежде чем остановился на схеме ниже. Я решил отправлять строку по одному байту за раз, потому что дальний конец не мог обрабатывать более четырех байтов за раз, поэтому я не мог отправить всю строку. Форматирование отдельного hex_byte похоже на sprintf в C.

import time
import serial
import sys
import binascii
import inspect


# This function takes a command string and sends individual bytes.
# It also reports the response.
def send_command(cmd_name, cmd_string):
    print ("\ncmd_name:", cmd_name)
    print ("cmd_string:", cmd_string)
    cmd_bytes = bytearray.fromhex(cmd_string)
    for cmd_byte in cmd_bytes:
        hex_byte = ("{0:02x}".format(cmd_byte))
        #print (hex_byte)
        ser.write(bytearray.fromhex(hex_byte))
        time.sleep(.100)

    # wait an extra 3 seconds for DISP_ON_CMD
    if cmd_name == "DISP_ON_CMD":
        time.sleep(5.0)
    response = ser.read(32)
    print ("response:", binascii.hexlify(bytearray(response)))
    return

# Code to put processor into factory mode.
comm_init='c4c4'
# Here's the list of command strings, captured as tuples.
# The 16-bit Data and Msg CRCs are calculated via gen_crc.exe.
heart_beat_cmd=      ("HEART_BEAT_CMD",      'a5a50a00010000003e1b')

Вот что я вижу в окне Python 3.4.5.

имя_команды: HEART_BEAT_CMD

cmd_string: a5a50a00010000003e1b

ответ: b'a5a51a002a0054373031763200000c08201e0a040000e389f86b'

Мне так и не удалось разобрать вывод на байты, но это было бы хорошим дополнением.

person cwilde    schedule 22.11.2017

Отказ от ответственности: я очень новичок в программировании как на python, так и на последовательном порту. Я знаю, что это очень старый вопрос и, возможно, уже был решен, но я хотел бы внести свой вклад (я думаю) и, возможно, научиться в процессе! Я знаю ответ на вторую часть вопроса о KeyboardInterrupt (или, по крайней мере, я думаю, что знаю). Итак, начнем.

KeyboardInterrupt в основном происходит, когда пользователь нажимает «Control + C», пока программа все еще работает. Это заставляет программу останавливаться прямо в той строке, которая выполнялась в данный момент. Следовательно

File "./sollar.py", line 30, in <module>
    s = ser.readline().decode('utf-8')
File "/usr/local/lib/python3.2/dist-packages/serial/serialposix.py", line 446, in read
    ready,_,_ = select.select([self.fd],[],[], self._timeout)

Потому что на этом он остановился (надеюсь, я прав). Чтобы избежать этого, вы можете использовать «попробовать.. кроме»

while True:
    try:
        # your main code here
        break
    except KeyboardInterrupt:
        print("User interrupt encountered. Exiting...")
        time.sleep(3)
        exit()
    except:
        # for all other kinds of error, but not specifying which one
        print("Unknown error...")
        time.sleep(3)
        exit()

Это в основном помогает вам выйти из вашей программы довольно "чистым способом". Надеюсь, это поможет.

person Shrinivas Iyengar    schedule 12.03.2017

ser.write(b'\x1A') #### esto es = control + z

person David Betancourt    schedule 29.07.2021