2013-03-22 95 views
1

这个周末我打算做一个小项目。有一个太阳能电池逆变器(丹佛斯ULX 3600i),我将尝试连接到我的Linux机器,看我是否可以从中获取数据,创建多少能量,例如统计数据。有一个用于RJ45连接的输入,但带有RS485。用python发送十六进制串行

我在电脑和逆变器之间通过一个RS485转换器将电缆连接到PC的USB端口。

然后我写一个小的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() 

所述逆变器被使用丹佛斯ComLynx协议(上page 26是我想发送数据):

编辑: 我现在可以发送一个请求为对亚当4520 RS485的LED光转换器闪烁一次,但是没有数据返回,但是当我在终端做了CTRL + C得到此错误:

[email protected]:~/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 

回答

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并发送它。这只会在文档中的各个ID与设备上的ID匹配时才起作用

您需要弄清楚python “struct”的工作方式,如何编码二进制以及如何将两个4位值放入一个8位字节:线索,请参阅>>和< <运营商和结构包“B”格式

0

声明:我很新的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() 

这基本上可以帮助你在退出程序一个相当“干净的方式”。希望有所帮助。

1

我试过了一些方案来将我的十六进制字符串命令转换为在远端UART上被识别为十六进制的字节,然后才能建立下面的方案。我选择一次发送一个字节的字符串,因为远端一次不能处理超过四个字节,所以我无法发送整个字符串。个人hex_byte的格式是C.

类似于sprintf的
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窗口中显示。

cmd_name:HEART_BEAT_CMD

cmd_string:a5a50a00010000003e1b

响应:b'a5a51a002a0054373031763200000c08201e0a040000e389f86b”

我很少抽时间去分析其输出为字节,但是这将是一个很好的补充。