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]





2013年11月13日 星期三

製作執行檔 -> 把python轉為.exe檔

之前看到網路上很多人都介紹 py2exe來製作執行檔
讓沒有安裝Python的電腦也能使我們開發的程式

以上就試使用py2exe來製作執行檔

  1. 先到 http://sourceforge.net/projects/py2exe/files/ 下載所需要的安裝檔
    這是有版本對應關系的,我是python2.7所以下載:
    py2exe-0.6.9.win32-py2.7.exe
    然後安裝之
  2. 假設我們的程式叫 Test1.py
    我們就在同一個資料夾建立一個 my_setup.py 的檔案,內容為:
    #!/usr/bin/python
    from distutils.core import setup
    import py2exe
    setup(console=["Test1.py"])
  3. 然後,在console模式下,移到my_setup.py的目錄下
    執行python my_setup.py py2exe 即可自動生成安裝檔
  4. 在資料夾「dist」中的所有檔案就是你給別人所需要的資料

不過生成的檔案是一堆檔案真的不是很好看
最近還有看到另一個叫 PyInstaller 的,也可以生成執行檔
能夠支援windows和Linux,又可以把執行檔變成一個檔案就好
感覺方便很多
但…測試時顯示缺 pywin32,暫時還沒有安裝起來
晚點有空再試試看囉
未來應該也是會在Linux下製作Python的程式
所以還是需要這樣的功能


2013年11月8日 星期五

開始~

1. 先安裝python,目前使用的是python 2.7,因為大多的資料工具聽說還沒移到3.0去
http://www.python.org/

2. 要在指命模式下執行python,就要先在
"控制台" -> "系統" -> "進階" -> "環境變數" 設定PATH,選取 'PATH' 變數名稱後,再點 '編輯' 按鈕
比如,我是在最後的地方加入 : ";C:\Python27",其中";" 用來把二個路徑分隔開
3. 建立方便的「安裝模組」的工具

https://pypi.python.org/pypi/setuptools/1.1.6#installation-instructions
下載 ez_setup.py
然後下指令:
python ez_setup.py
就可以安裝好 easy_install 工具啦

但這樣還不能馬上使用,還要建立path:
";C:\Python27\Scripts"

4. 接著就開始來使用 "easy_install"來安裝我們需要的工具了
  因為工作的原因,最近需要 Modbus 的library,所以選了 pymodbus 這個工具
 參考 pymodbus 的解說, 下指令:
easy_install -U pymodbus
就可以安裝好了,看過程,它好像也一併安裝了 pyserial
應該是 Modbus RTU要用的吧

到這邊就可以開始用Python寫Modbus的程式啦!! RTU , TCP都可以!!