问题
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