2013-03-22 94 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」

我很少抽時間去分析其輸出爲字節,但是這將是一個很好的補充。