2009年2月17日火曜日

ctypes(その2) MBT.dll を Python から

問題は、ポインタやハンドラ渡しの変数をどう扱うかです。

いろいろ試してみて、なんとかこれでいいのではないか?と思われる方法です。MBT.dll の公開されている API (Google検索)を見てください 。
  1. ctypes のインポート
  2. PLC との通信に必要な変数の設定
  3. ハンドラ、ポインタの型 を c_long() に  < この辺が大事みたいです。
  4. def connect() 関数 < socket が ハンドラ です
  5. def disconnect()関数
  6. def read()関数 < ReadData が ポインタ です
  7. def write()関数 < WriteData が ポインタ です
  8. 各関数を順番に実行します
  9. ## は VBA で使う時のサンプル

  • 変数をあらかじめ c_long() 等宣言する
  • 関数では byref()で渡す
  • 中身は、 ***.value で扱う
ソフトウェア用語を使ったうまい説明はできません、用語を知りませんので。
 <<16、>>16 は 16 bit のデータを Python 32 bit、 で受けた(?)ので、ずらしてます。
SwapDWord() は、インテル系 CPU の変なバイトオーダーに合わせる為の関数です。 

16 bit の 整数型、だけしかうまく動いてません。また時間があったらがんばります。


# $Id$
# Win32
# Python 2.5 (ctypes)
# MBT.dll by Wago (Modbus over TCP)
# copy MBT.dll to c:\windws\system32
# SYSTEM 750-841 Wago PLC
#
# data = int (16 bit) only
#

from ctypes import *

PLCAddress = '192.168.1.2' # PLC adress or name
Port = 502 # Modbus TCP port, need to be enabled
BaseAddress = 0x3000 # PLC, IEC 61131-3 Addresses %MW0..
length = 1 # data length

socket = c_long() # handler
ReadData = c_long() # pointer
WriteData = c_long() # pointer

def connect():
state_a = windll.MBT.MBTInit()
state_b = windll.MBT.MBTConnect(PLCAddress, Port, 1, 3000, byref(socket))

print ('PLC address = ',PLCAddress)
print ('Socket = ',socket.value)
print ('MBT Init state = ',state_a)
print ('MBT Connect state = ',state_b)


def disconnect():
state_a = windll.MBT.MBTDisconnect(socket)
state_b = windll.MBT.MBTExit()

print ('MBT Disconnect state = ',state_a)
print ('MBT Exit state = ',state_b)


def read(OffsetAddress, c=None):
ReadAddress = BaseAddress + OffsetAddress
state_a = windll.MBT.MBTReadRegisters(socket,4,ReadAddress,length,byref(ReadData),0,0)
if state_a != 0 :
print (' **** PLC read error')
c = windll.MBT.MBTSwapDWord(ReadData.value) >> 16

print ('MBT Read resisters state = ', state_a )
print ('Read address = ', ReadAddress )
print ('Read data = ',c )

return c



def write(OffsetAddress, data, c=None):
WriteAddress = BaseAddress + OffsetAddress
WriteData.value = windll.MBT.MBTSwapDWord(data << 16)
state_a = windll.MBT.MBTWriteRegisters(socket,WriteAddress,length,byref(WriteData),0,0)
if state_a != 0 :
print (' **** PLC write error')

print ('MBT Write resisters state = ', state_a )
print ('Write add = ', WriteAddress )
print ('Write data = ', WriteData.value )

## read back
c = read(OffsetAddress)
return c


connect()
write(0,1)
data = read(0)
print(data)
disconnect()





## -----------------------------------------------
## 'VB source
##Public Const MODBUSTCP_TABLE_OUTPUT_REGISTER = 4
##Public Const MODBUSTCP_TABLE_INPUT_REGISTER = 3
##Public Const MODBUSTCP_TABLE_OUTPUT_COIL = 0
##Public Const MODBUSTCP_TABLE_INPUT_COIL = 1
##Public Const MODBUSTCP_TABLE_EXCEPTION_STATUS = 7
##
##Public Declare Function MBTInit Lib "MBT" () As Long
##Public Declare Function MBTExit Lib "MBT" () As Long
##Public Declare Function MBTConnect Lib "MBT" (ByVal szHostAddress As String, ByVal port As Integer, ByVal useTCPorUDP As Long, ByVal requestTimeout As Long, hSocket As Long) As Long
##Public Declare Function MBTDisconnect Lib "MBT" (ByVal hSocket As Long) As Long
##Public Declare Function MBTReadRegisters Lib "MBT" (ByVal hSocket As Long, ByVal tableType As Byte, ByVal dataStartAddress As Integer, ByVal numWords As Integer, pReadBuffer As Any, ByVal fpReadCompletedCallback As Long, ByVal callbackContext As Long) As Long
##Public Declare Function MBTReadCoils Lib "MBT" (ByVal hSocket As Long, ByVal tableType As Byte, ByVal dataStartAddress As Integer, ByVal numBits As Integer, pReadBuffer As Any, ByVal fpReadCompletedCallback As Long, ByVal callbackContext As Long) As Long
##Public Declare Function MBTReadExceptionStatus Lib "MBT" (ByVal hSocket As Long, pExceptionStatus As Byte, ByVal fpReadCompletedCallback As Long, ByVal callbackContext As Long) As Long
##Public Declare Function MBTWriteRegisters Lib "MBT" (ByVal hSocket As Long, ByVal dataStartAddress As Integer, ByVal numWords As Integer, pWriteBuffer As Any, ByVal fpWriteCompletedCallback As Long, ByVal callbackContext As Long) As Long
##Public Declare Function MBTWriteCoils Lib "MBT" (ByVal hSocket As Long, ByVal dataStartAddress As Integer, ByVal numBits As Integer, pWriteBuffer As Any, ByVal fpWriteCompletedCallback As Long, ByVal callbackContext As Long) As Long
##Public Declare Function MBTSwapWord Lib "MBT" (ByVal wData As Integer) As Integer
##Public Declare Function MBTSwapDWord Lib "MBT" (ByVal dwData As Long) As Long
##
##Private Socket As Long






0 件のコメント: