(株)キーエンスのシーケンサーと通信をするライブラリー KV COM+ Library Ver.1 DLL用サンプル
キーエンスのシーケンサーとDelphiを使用して、通信をしてシーケンサーを動作させる場合、RS232Cにより動作させる事が一般的ですが、USB、LAN、Bluetooth等を使用して、通信コントロールが出来るライブラリーが、用意されています。
対応言語として、Visual Basic Visual C++ 2010/2008... EXCEL Acces 等々となっていますが、このライブラリーのActiveXが、Delphiではうまく使用出来ないようです。(よくある事なのですが)
AnsiCoadのDelphiの場合は、接続対象とか、トリガの関連付けをコードで書く必要があり、UniCoadのDelphiだと、エラーになって、パッケージとして取り込めないようです。(エラーになる部分を無効にして、接続対象とか、トリガの関連付けをコードで書く必要あり)
Dllもあるのですが、Delphi用には用意されていません。
Dllを使用した場合、トリガーを使用する為には、トリガー用のルーチンを作成する必要があります。
タイマーを利用して、周期的にデーターのサンプリングをして、変化のチェックをするようにしますが、通信速度に注意を払う必要があります。
そこで、DllをDelphiから利用する為のユニットを作成し、通信のテストをする事にしました。
全てのテストをしたわけでは無いのですが、問題なく通信が出来ています、トリガー用のルーチンのテストはしていません。
通信用のユニットの作成は、C++用のヘッダファイルと、マニュアルを参考にしました。
残念ながら、此処でヘッダファイル、マニュアル等を公開できません、必要であれは、キーエンスより、KV COM+ Libraryを入手してください。
キーエンスのシーケンサーを使用しない限り必要の無いものです。
C++からDelphiに変換する多少の参考になるかも知れませんが。
サンプルプログラムは、実際に装置を動かすようにはなっていません、キーエンスのマニュアルにあるDLL関数の例題を確認したものです。
LAN、Bluetoothに関しては、使用したパソコンと、相手のシーケンサーに用意されていなかった為、通信の確認がされていません。
プログラムを起動したら、まず最初にiniボタンをクリックします、次に、connectUSBか、connectRS232Cボタンで接続します。
終了する場合は、discnnect ボタンで接続を終了します。
シーケンサーのメモリー、リレー番号等は、プログラムの内容を修正して下さい。
メモリー、リレーの番号は各シーケンサーのマニュアルを参照する必要がありますが、一応 DBPlcdef.pas にコメントとして表示してあります。
ヘッダファイルの内容の変換について
#define DB_BITDEV_RW_MAX 16
#defineについては、
const DB_BITDEV_RW_MAX = 16;
の様に定数として宣言
LONG,PLONGは、LONGINT,PLONGINTを使用すればよいのですが、変更を少なくするため LONG,PLONGを宣言
LONG
= LONGINT; // LONG 追加 Int32
PLONG = ^LONG;
typedef void* DBHCONNECT;
// 接続ハンドル
ハンドルなので、整数とそのポインターを宣言
DBHCONNECT = Cardinal;
PDBHCONNECT
= ^DBHCONNECT;
typedef enum { // 動作モード
......,
} DBMode;
この形の宣言は、Delphiに無いので、列挙型として実行文で工夫をするか、CONSTとして定数宣言をします。
DBModeに関しては、列挙型にするだけで、DLLとリンクできました。
{$SCOPEDENUMS ON} // TDBMode
スコープ 無くても可
TDBMode =
DB_MODE_INVALID = 0,
.......
);
{$SCOPEDENUMS OFF}
PDBMode = ^TDBMode;
typedef enum {
//通信速度
DBCOMBAUD_9600 = 9600,
.......
} DBComBaud;
通信速度はDBComBaudを整数として渡すので、
DBComBaud = integer;
と宣言
速度の宣言は列挙型で
TDBComBaud
= ( //通信速度
DBCOMBAUD_9600 = 9600,
.......
);
の様にして、値は、
Speed := integer(DBCOMBAUD_115200) // Delphi では、直接値を参照しない
のようにして設定しますが、Constで宣言した方が、簡単に済みます。
const
DBCOMBAUD_9600 = 9600;
........
typedef struct { // デバイス情報
WORD wKind;
// デバイス種別
.....
} DBDevInfo;
これは、Delphiのrecord型と同じなので
type
TDBDevInfo = record
wKind : WORD;
........
end;
PDBDevInfo
= ^TDBDevInfo;
enum DBPlcId {
DBPLC_DKV3000 = 0x0203,
.......
}
この場合も Const 宣言の方が簡単ですが列挙型を使用
DBPlcId = integer;
TDBPlcId
= (
DBPLC_DKV3000 = $0203,
DBPLC_DKV5000 = $0203,
.....
);
DBPlcI を integer として宣言
DBPlcI := integer(DBPLC_DKV3000)
の様にして使用。
他の部分の宣言も殆ど同じです、変換したDatabuilder.pas DBPlcdef.pas を参照すればわかります。
DLLのルーチンには、ansicahr 用と widechar 用があるので、$IFDEF UNICODE で呼び出しルーチンを選択
function
DBConnect(lpszDestName: PCHAR; PlcId: TDBPlcId; phConnect: PDBHCONNECT):
DBERROR;
var
iPlcId : DBPlcId;
// integerと同じ
begin
iPlcId :=
ord(PlcId); // ord は smallint; integer(Plcid)でも良い 列挙型 を 整数に変換して次に渡す
{$IFDEF
UNICODE}
Result := DBConnectW(lpszDestName,iPlcId,phConnect);
{$ELSE}
Result := DBConnectA(lpszDestName,iPlcId,phConnect);
{$ENDIF}
end;
エラーがエラーコードしか帰らないので、コードからエラーの内容を取得するルーチン、モードコードからモード文字取得ルーチン、通信モードコードから通信モード文字を取得するルーチンを追加して、実行時のデバッグを容易に出来る様にしました。
function DBERRSTRING(DBERRCOAD: LONG): string; // エラー番号から文字データー取得
function
KVModeString(KvMode: TDBMODE): string; // KVモードから文字コード取得
function
CominfoTypeNoComtypestr(ComTypNo: DBComtype): string; // 通信モード番号から文字情報取得
ユニットには、ストップウォッチを追加して、コマンド送信してから、応答が帰るまでの時間を測定するようになっていますが、あくまでも確認用であり、実際には必要ありません。
Stopwatch コンポーネントも一緒にダウンロードできるので、インポートして使用して下さい。
プログラムの開始時にマルチメディアタイマーの精度を最小値に設定、終了したら元へ戻します。
COMスピードを正しく設定するのに必要らしいのですが、原因は不明です。
これ以外のDLLでは、この様な事をしたことはありません。
var
MMPeriodF:
Boolean; // timeBeginPeriod set Flag
MMMin: Cardinal;
// MMTime 最小値
TMinMax: TIMECAPS;
// これを設定しないと正しくCOMスピード設定されない
procedure
TForm1.FormCreate(Sender: TObject);
begin
TimeGetDevCaps(@TMinMax,sizeof(TMinMax));
// MMTIMの仕様取得
MMMin := TMinMax.wPeriodMin;
// 最小値の取得
if
timeBeginPeriod(MMMin) = 0 then MMPeriodF := true;
// MMTIMEの最小値が設定できたらTrue 解除用
end;
procedure TForm1.FormDestroy(Sender:
TObject);
begin
if MMPeriodF
then timeEndPeriod(MMMin); //
MMTIMEの最小値が設定されていたら解除
end;