2013年11月21日 星期四

pymodbus 試寫 Modbus TCP 程式

不知為何 pyModbus的文件實在不容易看
不知道是我對Python的了解不夠還是怎麼回事,真的不太了解要怎麼查一個function到底要怎麼用,或是 function回傳值的結構長什麼樣子…

所以還是寫個記錄,方便自己以後回憶,不然真的每次寫Modbus程式時就只能狂查他的 source code...
若有人知道什麼pymodbus資源可以方便查詢,再請告訴我一下:)

簡單說明一下:
(1) ModbusClient('192.168.27.44', 502) 用來設定建立連線之目標
(2) read_input_registers(start_addr, count, unit=sid)
  三個欄位為:(起始Address, 要讀入的AI數量, Modbus slave ID)
(3) read_holding_registers(start_addr, count, unit=sid)
  同上
(4) write_registers(start_addr, value_array, unit=sid)
  欄位說明: (起始address, 寫入值的array, Modbus ID)
(5) read_discrete_inputs(start_addr, bit count, unit=sid)
  欄位說明: (起始address, 要讀入幾個DI, Modbus ID)
  要注意到!! 回應值是以byte為單位,所以讀4 bit或8 bit,都是回一個byte --> 8 bit
(6) 其它的以此類推…

下面是我的範例程式:

from pymodbus.client.sync import ModbusTcpClient as ModbusClient

client = ModbusClient('192.168.27.44', 502)
client.connect()

print '==== AI ===='
#-- FC04: read multi-input registers (3xxxx), for AI
#read_input_registers(start_addr, count, unit=sid)
rr = client.read_input_registers(0,1, unit=1) #read AI
print rr, "value=", rr.registers
rr = client.read_input_registers(0,2, unit=1) #read AI
print rr, "value=", rr.registers

print '==== AO ===='
#-- FC03: read multi-registers (4xxxx) for AO
#read_holding_registers(start_addr, count, unit=sid)
rr = client.read_holding_registers(0,1, unit=1) #read AO
print rr, "value=", rr.registers
rr = client.read_holding_registers(0,2, unit=1) #read AO
print rr, "value=", rr.registers

#-- FC16: write multi-registers for AO
# write_registers(start_addr, value_array, unit=sid)
rq = client.write_registers(0, [10, 20], unit=1)
assert(rq.function_code < 0x80)#if FC>0x80 --> Error
# read back, to check value
rr = client.read_holding_registers(0,4, unit=1) #read AO
print rr, "AO value=", rr.registers

print '==== DI ===='
#-- FC2  Read multi-input discrete ( 1xxxx ) for DI
#   01 02 00 01 00 08 28 0C
#   01 82 01 81 60
# read_discrete_inputs(start_addr, bit count, unit=sid)
rr = client.read_discrete_inputs(0, 4, unit=1) #will reply 1 byte --> 8 bits
print rr, "DI value=", rr.bits
rr = client.read_discrete_inputs(0, 10, unit=1)#will reply 2 byte --> 16 bits
print rr, "DI value=", rr.bits

print '==== DO ===='
#-- FC01: Read multi-coils status (0xxxx) for DO
# read_coils(start_addr, bit count, unit=sid)
rr = client.read_coils(0, 1, unit=1)
print rr, "DO value=", rr.bits[1]
#if error : Exception Response(129, 1, IllegalFunction)
#   01 01 00 00 00 01 FD CA
#   01 81 01 81 90

#-- FC05: Write single-coil (0xxxx) for DO
# read_coils(start_addr, bit count, unit=sid)
print '-- write single DO --'
rq = client.write_coil(0, True, unit=1)
print rq
rr = client.read_coils(0, 4, unit=1)
print rr, "DO value=", rr.bits
#if error: Exception Response(129, 1, IllegalFunction)
#   01 05 00 01 FF 00 DD FA
#   01 85 01 83 50

#-- FC15: Write multi-coils ( 0xxxx ) for DO
# write_coils(start_addr, value_array, unit=sid)
print '-- write multi DO --'
rq = client.write_coils(0, [False]*8, unit=1)
rq = client.write_coils(0, [True]*4, unit=1)
print rq
rr = client.read_coils(0, 8, unit=1)
print rr, "DO value=", rr.bits

client.close()


===========================================
下面是輸出的結果
===========================================

==== AI ====
ReadRegisterResponse (1) value= [0]
ReadRegisterResponse (2) value= [0, 0]
==== AO ====
ReadRegisterResponse (1) value= [10]
ReadRegisterResponse (2) value= [10, 20]
ReadRegisterResponse (4) AO value= [10, 20, 0, 0]
==== DI ====
ReadBitResponse(8) DI value= [False, False, False, False, False, False, False, False]
ReadBitResponse(16) DI value= [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
==== DO ====
ReadBitResponse(8) DO value= False
-- write single DO --
WriteCoilResponse(0) => 1
ReadBitResponse(8) DO value= [True, True, True, True, False, False, False, False]
-- write multi DO --
WriteNCoilResponse(0, 4)
ReadBitResponse(8) DO value= [True, True, True, True, False, False, False, False]





沒有留言:

張貼留言