こちらの記事はBeckhoffが提供するライブラリを使用し、C++でTwinCAT3 Runtime3とADS通信します。
さ、はじめよう。
TcAdsDll
TcAdsDllは、他のADSデバイスとの通信機能を提供します。それらのライブラリを使って、TwinCAT Messageルータを介して、ローカルのTwinCATシステムまたはリモートTwinCATシステムと通信できます。
そのTcAdsDllは、 C APIやCOM interfacesで利用できます。
How to Use it?
Project>Propertiesを開きます。
Configuration Properties>Linker>InputでTcAdsDll.libのPathを追加します。
こちらはlibのPathです。
C:\TwinCAT\AdsApi\TcAdsDll\Lib\TcAdsDll.lib |
また、プログラムにTcAdsApi.hとTcAdsDef.hのヘッダーファイルをプロジェクトに追加してください。
#include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h” #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsApi.h” |
Example1:Get DLL Version
Example1ではDLLのバージョンを取得します。
AdsGetDllVersion
ADS-DLL のバージョン番号、revision番号、ビルド番号を取得できる関数です。また、long型の戻り値は、ADS-DLLに関連する3つの項目をコード化した形で含まれています。
LONG AdsGetDllVersion( void ); |
AmsNetId
ADS デバイスの NetId は、この構造体になります。また、NetIdは、6桁の数字で構成されています。
注意するのは、この構造体は、UCHAR型の6つの要素を持つ配列で構成され、配列の各要素には、1〜255 の値を指定できます。NetIdは、TwinCATシステムサービスを使用して設定します。
typedef struct { UCHARb[6]; } AmsNetId, *PAmsNetId; |
Program
こちらはDLL の情報を取得するサンプルコードです。
#include <iostream> #include <conio.h> #include <windows.h> #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h” #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h” using namespace std; int main() { long nTemp; AdsVersion* pDLLVersion; AmsNetId* pAmsNetId; void* pData = NULL; nTemp = AdsGetDllVersion(); pDLLVersion = (AdsVersion*)&nTemp; cout << “Version: ” << (int)pDLLVersion->version << ‘\n’; cout << “Revision: ” << (int)pDLLVersion->revision << ‘\n’; cout << “Build: ” << pDLLVersion->build << ‘\n’; cout.flush(); _getch(); } |
Result
Example2:Run/Stop the PLC Runtime
Example2ではPLC Runtimeを起動・停止する方法を示します。
AdsPortOpen
TwinCATメッセージルータとの接続を確立します。また、ADSルータによってプログラムに割り当てられたポート番号が返されます。
LONG AdsPortOpen( void ); |
AdsGetLocalAddress
ローカルの NetId とポート番号を取得します。また、関数のエラーステータスを返します。
LONG AdsGetLocalAddress( PAmsAddr pAddr ); |
Parameter-pAddr
AmsAddr型の構造体ポインタになります。
ADSSTATE
typedef enum nAdsState { ADSSTATE_INVALID = 0, ADSSTATE_IDLE = 1, ADSSTATE_RESET = 2, ADSSTATE_INIT = 3, ADSSTATE_START = 4, ADSSTATE_RUN = 5, ADSSTATE_STOP = 6, ADSSTATE_SAVECFG = 7, ADSSTATE_LOADCFG = 8, ADSSTATE_POWERFAILURE = 9, ADSSTATE_POWERGOOD = 10, ADSSTATE_ERROR = 11, ADSSTATE_SHUTDOWN = 12, ADSSTATE_SUSPEND = 13, ADSSTATE_RESUME = 14, ADSSTATE_CONFIG = 15, // system is in config mode ADSSTATE_RECONFIG = 16, // system should restart in config mode ADSSTATE_MAXSTATES } ADSSTATE; |
AdsSyncWriteControlReq
ADS サーバーの ADS ステータスおよびデバイスステータスを変更できる関数です。また、関数のエラーステータスを返します。
LONG AdsSyncWriteControlReq( PAmsAddr pAddr, USHORT nAdsState, USHORT nDeviceState, ULONG nLength, PVOID pData ); |
[in]pAddr
ADS サーバの NetId とポート番号を持つ構造体です。
[in]nAdsState
発行したいADS Statusを指定します。
[in]nDeviceState
発行したいDevice Stateを指定します。
[in]nLength
データサイズ(バイト単位)。
[in]pData
ADSデバイスに追加送信されるデータへのポインタ。
AdsPortClose
TwinCATメッセージルータへの接続をクロスします。また、関数のエラーステータスを返します。
LONG AdsPortClose( void ); |
Program
こちらはキーボードのRキーでPLC Runtimeを起動し・SキーでPLC Runtimeを停止できるサンプルコードです。
#include <iostream> #include <conio.h> #include <windows.h> #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h” #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h” using namespace std; int main() { long nTemp; AdsVersion* pDLLVersion; AmsNetId* pAmsNetId; void* pData = NULL; nTemp = AdsGetDllVersion(); pDLLVersion = (AdsVersion*)&nTemp; cout << “Version: ” << (int)pDLLVersion->version << ‘\n’; cout << “Revision: ” << (int)pDLLVersion->revision << ‘\n’; cout << “Build: ” << pDLLVersion->build << ‘\n’; // USHORT nAdsState; USHORT nDeviceState=0; long nErr, nPort; AmsAddr Addr; PAmsAddr pAddr = &Addr; int ch; nPort = AdsPortOpen(); nErr = AdsGetLocalAddress(pAddr); if (nErr) { cerr << “Error: AdsGetLocalAddress: ” << nErr << ‘\n’; } else { cout << “No Error\n”; } pAddr->port = 851; cout << “(R) -> PLC Run\n”; cout << “(S) -> PLC Stop\n”; cout.flush(); ch = _getch(); ch = toupper(ch); while ((ch == ‘R’) || (ch == ‘S’)) { switch (ch) { case ‘R’: nAdsState = ADSSTATE_RUN; break; case ‘S’: nAdsState = ADSSTATE_STOP; break; } nErr = AdsSyncWriteControlReq(pAddr, nAdsState, nDeviceState, 0, pData); if (nErr) cerr << “Error: AdsSyncWriteControlReq: ” << nErr << ‘\n’; ch = _getch(); ch = toupper(ch); } // Close the communication port nErr = AdsPortClose(); if (nErr) cerr << “Error: AdsPortClose: ” << nErr << ‘\n’; } |
Example3:Write and Read Single Variables
Example3ではPLC Runtime内部GVLの変数の読み書き方法を示します。
AdsSyncReadWriteReq
ADSサーバーに同期してデータを書き込みやデータを受信できる関数です。また、関数のエラーステータスを返します。
LONG AdsSyncReadWriteReq( PAmsAddr pAddr, ULONG nIndexGroup, ULONG nIndexOffset, ULONG nReadLength, PVOID pReadData, ULONG nWriteLength, PVOID pWriteData ); |
[in]pAddr
ADS サーバの NetId とポート番号を持つ構造体です。
[in]nIndexGroup
インデックスグループになります。
[in]nReadLength
ADSデバイスが返すデータの長さ(バイト単位)。
[out]pReadData
ADSデバイスから返されたデータを含むBufferになります。
[in]nWriteLength
ADSデバイスに書き込まれたデータの長さ(バイト単位)になります。
[out] pWriteData
ADSデバイスにデータを書き込むBufferになります。。
AdsSyncWriteReq
ADSデバイスに同期してデータを書き込みできる関数です。また、関数のエラーステータスを返します。
LONG AdsSyncWriteReq( PAmsAddr pAddr, ULONG nIndexGroup, ULONG nIndexOffset, ULONG nLength, PVOID pData ); |
[in]pAddr
ADS サーバの NetId とポート番号を持つ構造体です。
[in]nIndexGroup
インデックスグループになります。
[in]nIndexOffset
インデックスのオフセットになります。
[in]nLength
ADS Serverに書き込むデータのサイズ(バイト単位)。
[in]pData
ADSサーバーに書き込まれるデータへのポインタになります。
Program
こちらはGVL.MyRealの実数変数を読み書きするサンプルコードになります。
#include <iostream> #include <conio.h> #include <windows.h> #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h” #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h” using namespace std; int main() { long nErr, nPort; AmsAddr Addr; PAmsAddr pAddr = &Addr; unsigned long lHdlVar; int nIndex; short Data[10]; char szVar2[] = { “GVL.MyReal” }; float myRealData; // Open communication port on the ADS router nPort = AdsPortOpen(); nErr = AdsGetLocalAddress(pAddr); if (nErr) cerr << “Error: AdsGetLocalAddress: ” << nErr << ‘\n’; // Select Port: TwinCAT 3 PLC1 = 851 pAddr->port = 851; cout << “Data[” << nIndex << “]: ” << Data[nIndex] << ‘\n’; } nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar2), szVar2); myRealData = 3.145; nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(myRealData), &myRealData); if (nErr) cerr << “Error: AdsSyncReadReq: ” << nErr << ‘\n’; else { cout << myRealData << ‘\n’; } cout.flush(); _getch(); // Close communication port nErr = AdsPortClose(); if (nErr) cerr << “Error: AdsPortClose: ” << nErr << ‘\n’; } |
Result
Example4:Write and Read Array Variable
Example4は変数配列を読み書きするサンプルコードになります。
#include <iostream> #include <conio.h> #include <windows.h> #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h” #include “C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h” using namespace std; int main() { long nErr, nPort; AmsAddr Addr; PAmsAddr pAddr = &Addr; unsigned long lHdlVar; int nIndex; short Data[10]; char szVar[] = { “GVL.Mydata” }; float myRealData; // Open communication port on the ADS router nPort = AdsPortOpen(); nErr = AdsGetLocalAddress(pAddr); if (nErr) cerr << “Error: AdsGetLocalAddress: ” << nErr << ‘\n’; // Select Port: TwinCAT 3 PLC1 = 851 pAddr->port = 851; // Fetch handle for the PLC variable nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar), szVar); if (nErr) cerr << “Error: AdsSyncReadWriteReq: ” << nErr << ‘\n’; // Read values of the PLC variables (by handle) //nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(Data), &Data[0]); Data[0] = 123; Data[1] = 44; Data[2] = 1; Data[3] = 2; Data[4] = 3; Data[5] = 4; Data[6] = 5; Data[7] = 6; Data[8] = 7; Data[9] = 8; nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(Data), &Data[0]); if (nErr) cerr << “Error: AdsSyncReadReq: ” << nErr << ‘\n’; else { for (nIndex = 0; nIndex < 10; nIndex++) cout << “Data[” << nIndex << “]: ” << Data[nIndex] << ‘\n’; } cout.flush(); _getch(); // Close communication port nErr = AdsPortClose(); if (nErr) cerr << “Error: AdsPortClose: ” << nErr << ‘\n’; } |