Beckhoff#TcAdsDllとC++でADS通信してみよう

こちらの記事は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’;
}

Result

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする