[英]Raspberry Pi RS485/Uart Modbus
我試圖在UART上連接一個RS485適配器,通過Raspberry Pi上的modbus進行通信。 我的最終目標是讓所有這些都與Node應用程序一起工作,但到目前為止,我的開發人員一直使用Python。
我的硬件連接如下:
[Modbus-Device] <===> [RS485芯片<==> Raspberry PI GPIO]引腳。 RS485有三條線(發送,接收,方向),它們按如下方式連接
RaspiPi <=> 適配器
GPIO 14(8) - Tx <=>數據+
GPIO 15(10) - Rx <=> - 數據 -
GPIO 18(12) - 方向
RS485不是典型的9針適配器。 我有三根電線在芯片上運行。 雙絞線,用作差動裝置和地線。
通過手動翻轉GPIO18進行發送/接收,我能夠在此adpater和USB-RS485適配器之間發送串行通信。 (以下代碼)[1]。 此代碼純粹用於證明適配器的工作原理
我堅持讓modbus在GPIO適配器上工作。 我嘗試過使用minimalmodbus,它可以很好地與USB-RS485適配器配合使用,但是在GPIO適配器上失敗了。 我懷疑這是因為沒有設置方向引腳。
理想的解決方案是在pi上為GPIO找到一個RS485驅動程序,但我沒看到三個選項
1 - 制作我自己的驅動程序(我完全不熟悉的東西)2 - 以某種方式獲得一個modbus庫來翻轉內核空間中的GPIO引腳3 - 手動通過串行發送modbus消息並調整用戶空間中的GPIO引腳。 在速度和可靠性方面,這似乎是最簡單但也是最差的。 我的代碼嘗試低於[2]
關於這個主題的任何建議都將非常感激。 如果有人之前做過類似的事情並且可以權衡我的選擇,這會有所幫助。 我從來沒有在這個級別的軟件上工作,所以如果有一些明顯的答案我完全忽略了,我就不會感到驚訝。
[1]此代碼與連接USB的樹莓派上的另一個RS485適配器通信。 這是為了證明GPIO適配器正在工作,我可以用Raspberry pi上的Pin 12控制方向
import time
import serial
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT);
ser = serial.Serial(
port= '/dev/ttyS0',
baudrate= 57600,
parity= serial.PARITY_NONE,
stopbits= serial.STOPBITS_ONE,
bytesize= serial.EIGHTBITS,
timeout=1
)
def write_add():
counter = 0;
message = 0
while (True):
print "writing",
GPIO.output(12,1) #set high/transmit
ser.write('%d \n'%(message))
time.sleep(0.005) #baud for 57600
#time.sleep(0.5) #baud for 9600
GPIO.output(12, 0) #pin set to low/receive
loop_count = 0
res =""
while (res == ""):
res =ser.readline();
if(res != ""):
print ""
print "Read Cycles: "+str(loop_count)+" Total: "+str(counter)
print res
message = int(res) + 1
counter = counter + 1
elif(loop_count > 10):
res = "start over"
else:
print ".",
loop_count = loop_count + 1
write_add()
[2]此代碼試圖與另一個modbus設備通信。 我的消息正在發送,但響應是嘎嘎嘎嘎。 我的假設是GPIO方向引腳要么過早翻轉並切斷消息或者太遲而且缺少一些響應。
import serial
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
ser = serial.Serial(
port='/dev/ttyS0',
baudrate = 57600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
GPIO.output(12,1) #set high/transmit
ByteStringToSend = "\x00\x03\x01\xb8\x00\x01\x04\x02"
ser.write(ByteStringToSend)
time.sleep(0.005) #baud for 57600
GPIO.output(12, 0) #pin set to low/receive
ReceivedData = ""
while (ReceivedData == ""):
RecievedData = ser.readline();
print RecievedData
[3]工作USB-RS-485代碼。 Pi上的USB適配器連接到Modbus設備此代碼每秒讀取寄存器440。
#1/usr/bin/env python
import minimalmodbus
import time
print minimalmodbus._getDiagnosticString()
minimalmodbus.BAUDRATE=57600
minimalmodbus.PARITY='N'
minimalmodbus.BYTESIZE=8
minimalmodbus.STOPBITS=1
minimalmodbus.TIMEOUT=0.1
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 0) #port and slave
#instrument.debug = True
while True:
batterVolt = instrument.read_register(440, 2) #register number, number decimals
print batterVolt
time.sleep(1)
編輯:澄清計划。 Edit2:進一步闡明了方案和添加/編輯的代碼
示例-2中的代碼實際上可以正常工作。 我只需要格式化響應。
print RecievedData.encode('hex')
這將以modbus響應格式給出十六進制字符串。 正如Andrej Debenjak所提到的,time.sleep (x)將取決於波特率和消息大小。
旁注:我發現這個頁面有助於破譯modbus傳輸。
http://www.modbustools.com/modbus.html
編輯:我發送的ByteString不適用於正確的modbus設置。 第一個字節x00是廣播字節,不應該請求響應。 看起來我正在使用的硬件有一些時髦的東西。 在典型的modbus設置中,您需要解決您嘗試與之通信的設備。 感謝Marker指出這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.