Sending hex over serial with python

守給你的承諾、 提交于 2020-01-01 00:23:12

问题


This weekend I am going to make a little project. Got a solarcell inverter (Danfoss ULX 3600i) which I will try to connect to my linux machine, to see if I can grab the data from it, how much energy created eg for stats. There is an input for RJ45 connection on it, but with RS485.

I got the cables to connect it through my usb port in the pc with an RS485 converter in between the pc and the inverter.

I am then writing a small python code to make request. However I cant figure out how to send the data correctly.

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()

The inverter is using the Danfoss ComLynx protocol (on page 26 is the data I am trying to send):

EDIT: I now can send a request as the LED light on the Adam 4520 RS485 converter is blinking once, however no data back, but get this error when I do a CTRL+C in terminal:

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

回答1:


Rewrite "thestring" as

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

You won't need to pack it, you can say data=thestring and send it. This will only work if the various ids in the document match exactly what is on your equipment

You need to figure out how the python "struct" works, how to encode binary and how to put two 4 bit values into one 8 bit byte: clue, see the >> and << operators and the struct pack "B" format




回答2:


I tried a number of schemes to convert my command string of hex characters into bytes which were recognized as hex on the far end of the UART, before settling on the scheme below. I chose to send the string one byte at a time, because the far end could not process more than four bytes at a time, so I could not send the entire string. The formatting of the individual hex_byte is similar to an sprintf in 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')

Here is what I see displayed in my Python 3.4.5 window.

cmd_name: HEART_BEAT_CMD

cmd_string: a5a50a00010000003e1b

response: b'a5a51a002a0054373031763200000c08201e0a040000e389f86b'

I never got around to parsing the output into bytes, but that would be a nice addition.




回答3:


Disclaimer: I am very new to both python and serial port programming. I know this is a very old question and might have been solved already, but I'd like to do my part(I guess) and maybe learn in the process! I know the answer to the second part of the question about the KeyboardInterrupt(or at least I think I do.) So here goes

KeyboardInterrupt is basically when the user hits "Control+C" while the program is still running. This makes the program stop at right whichever line it was executing at then moment. Hence the

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)

Because that's where it stopped(hopefully I'm right.) To avoid this, you could use "try.. except"

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()

This basically helps you exit your program in a rather "clean way." Hope that helps.



来源:https://stackoverflow.com/questions/15570526/sending-hex-over-serial-with-python

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!