You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Ads funktioiden avulla voi toteuttaa kättetelyn c++ ja Beckhoffin logikan välillä.

{code}

 

#include "beckhoff.h"

//variables of callback functions

ULONG nCount;
SYSTEMTIME              SystemTime, LocalTime;
FILETIME                FileTime;
LARGE_INTEGER           LargeInteger;
TIME_ZONE_INFORMATION   TimeZoneInformation;
unsigned long pNotificationData;
unsigned long pNotificationHNotification;
unsigned long pNotificationCbSampleSize;
unsigned long huser;
unsigned int b[10];
unsigned short portt[10];


Beckhoff::Beckhoff(QObject *parent) :
    QObject(parent)
{

}



// Callback function

void __stdcall EventsInPlc(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)
{
  int                     nIndex;
  ++nCount;
  // Output value of the variable
  //cout << "Value: " << *(ULONG *)pNotification->data << '\n';
  //cout << "Notification: " << pNotification->hNotification << '\n';
  pNotificationData= *(ULONG *)pNotification->data;
  pNotificationHNotification= pNotification->hNotification;
  // Convert time stamp to SYSTEMTIME
  LargeInteger.QuadPart = pNotification->nTimeStamp;
  FileTime.dwLowDateTime = (DWORD)LargeInteger.LowPart;
  FileTime.dwHighDateTime = (DWORD)LargeInteger.HighPart;
//aikafunktiot eivat toimi
  //  FileTimeToSystemTime(&FileTime, &SystemTime);
  // Calculate time in local representation
//  GetTimeZoneInformation(&TimeZoneInformation);
//  SystemTimeToTzSpecificLocalTime(&TimeZoneInformation, &SystemTime, &LocalTime);
  // Output time stamp
  //cout << LocalTime.wHour << ":" << LocalTime.wMinute << ":" << LocalTime.wSecond << '.' << LocalTime.wMilliseconds <<
  //     " den: " << LocalTime.wDay << '.' << LocalTime.wMonth << '.' << LocalTime.wYear << '\n';
  // Size of buffer in bytes
  //cout << "SampleSize: " << pNotification->cbSampleSize << '\n';

  pNotificationCbSampleSize=pNotification->cbSampleSize;

  // 32-bit variable (including pointers) that are set by AddNotification // (See main)

//  cout << "hUser: " << hUser << '\n';

  huser=hUser;

  // Output ADS address of the sender

  //cout << "ServerNetId: ";


  for (nIndex = 0; nIndex < 6; nIndex++){


    b[nIndex]=(int)pAddr->netId.b[nIndex] ;

    portt[nIndex]= pAddr->port;

  }

  //cout.flush();

}


// TwinCAT router callback function

void __stdcall RouterCall (long nReason)

{

  switch (nReason)

  {

  case AMSEVENT_ROUTERSTOP:

    qDebug()<< "TwinCAT-Router stop";

    break;

  case AMSEVENT_ROUTERSTART:

      qDebug()<< "TwinCAT-Router start";

    break;

  case AMSEVENT_ROUTERREMOVED:

      qDebug()<< "TwinCAT-Router removed";

    break;

  default:

      QString tmp1;

      tmp1.setNum(nReason);

      qDebug()<< "TwinCAT-Router AMS-Event " << tmp1;

    break;

  }

}


// ADS state callback function

void __stdcall ADS_StateCallback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)

{

  INT       nIndex;

  nIndex = *(short *)pNotification->data;

  switch (nIndex)

  {

  case ADSSTATE_RUN:

    qDebug()<< "PLC run";

    break;

  case ADSSTATE_STOP:

    qDebug()<< "PLC stop";

    break;

  default :

    QString tmp1;

    tmp1.setNum(nIndex);

    qDebug()<< "PLC ADS-State" << tmp1;

    break;

  }

}


//!Read DLL version

/*!

This program determines the version of the DLL file.

*/

void Beckhoff::ReadDLLversion()

{

    long nTemp;

    AdsVersion* pDLLVersion;

    QString tmp1,tmp2;

    nTemp = AdsGetDllVersion();

    pDLLVersion = (AdsVersion *)&nTemp;

    tmp1.setNum((int)pDLLVersion->version);

    tmp2="versio=";

    tmp2+=tmp1;

    tmp2+=" revision=";

    tmp1.setNum((int)pDLLVersion->revision);

    tmp2+=tmp1;

    tmp2+=" build=";

    tmp1.setNum((int)pDLLVersion->build);

    tmp2+=tmp1;

    ansver=tmp2;

    emit OkMessage(ansver);

   // emit Errors(ansver);

}


//! Write flag synchronously into the PLC

int Beckhoff::WriteFlagSynchronouslyIntoThePLC()

{

    LONG                    nErr, nPort;

    //ULONG                   hNotification, hUser = 0;

    //AdsNotificationAttrib   adsNotificationAttrib;

    pAddr = &Addr;

    // Open communication port on the ADS router

    nPort = AdsPortOpen();

    nErr = AdsGetLocalAddress(pAddr);

    if(nErr){

        emit Errors("Not local address found");

        return -1; }

    pAddr->port = AMSPORT_R0_PLC_RTS1;//mika tama on?

    // Write value to MD0 mika MDO??

    nErr = AdsSyncWriteReq( pAddr, 0x4020, 0x0, 0x4, &dwData );//mita ovat parametrit

    if (nErr){

        emit Errors("ads sync writing not succeed");

        return -2;}

    // Close communication port

    nErr = AdsPortClose();

    if (nErr){

        emit Errors("ads can not close port");

        return -3;

    }

}



//! Read flag synchronously from the PLC

/*! In this example program the value in flag double word 0 in the PLC is read and displayed on the screen.

*/

int Beckhoff::ReadFlagSynchronouslyFromThePLC()

{

  long      nErr, nPort;

  pAddr = &Addr;

  int i=0;

  // Open communication port on the ADS router

  nPort = AdsPortOpen();

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr){

      tmp.setNum(nErr);

      tmp1+="Error: AdsGetLocalAddress: ";

      tmp1+= tmp;

      emit Errors(tmp1);

  }

  pAddr->port = AMSPORT_R0_PLC_RTS1;

  // Read value from MD0 and display

  do

  {

    i++;

    nErr = AdsSyncReadReq(pAddr, 0x4020, 0x0, 0x4, &dwData);

    if (nErr){

      tmp=  "Error: AdsSyncReadReq: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      tmp1.setNum(dwData);

      tmp+=" ";

      tmp+=tmp1;

      emit Errors(tmp);

      tmp.setNum(dwData);

      tmp+=" ";

      emit SendData(tmp);

    }

  }

  while (i<10);//getch() == '\r');    // Read the next value (use Carriage return as delimitter), stop otherwise

  // Close communication port

  nErr = AdsPortClose();

  if (nErr){

      tmp=  "Error: AdsPortClose: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

  }

  return 1;

}


//! Read ADS status

/*!

This program reads the status of the PLC. The variable of type ADSSTATE which contains information such as, for example, whether the PLC is in the RUN or STOP state.

*/

int Beckhoff::ReadAdsStatus()

{

  //ADSSTATE mikähän mättä kun ei voi käyttää alla

  unsigned short nAdsState;

  USHORT	nDeviceState;

  pAddr = &Addr;

  nPort = AdsPortOpen();// Open communication port on the ADS router

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr){

      tmp1.setNum(nErr);

      tmp="Error: AdsGetLocalAddress: " ;

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  pAddr->port = AMSPORT_R0_PLC_RTS1;

 // do

 // {

    nErr = AdsSyncReadStateReq(pAddr, &nAdsState, &nDeviceState);

    if (nErr){

        tmp1.setNum(nErr);

        tmp="Error: AdsSyncReadStateReq: " ;

        tmp+=tmp1;

        emit Errors(tmp);

    }

    else{

      tmp= "AdsState: ";

      tmp1.setNum(nAdsState);

      tmp+=tmp1;

      tmp+= "DeviceState: ";

      tmp1.setNum( nDeviceState);

      tmp+=tmp1;

      emit OkMessage("message ok");

      emit SendData(tmp);

    }

 // }

  //while ( getch() == '\r'); // continue on a carriage return, finish for any other key

  nErr = AdsPortClose();// Close communication port

  if (nErr){

      tmp=  "Error: AdsPortClose: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  return 1;

}


//! Read ADS information

/*!

Each ADS device contains a version number and an identification. The example program reads this information from the PLC and displays it on the screen.

*/

int Beckhoff::ReadAdsInformation()

{

  LONG           nErr, nPort;

  AdsVersion     Version;

  AdsVersion     *pVersion = &Version;

  char           pDevName[50];

  pAddr = &Addr;

  nPort = AdsPortOpen();// Open communication port on the ADS router

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr){

      tmp1.setNum(nErr);

      tmp="Error:  AdsGetLocalAddress: " ;

      tmp+=tmp1;

      emit Errors(tmp);

  }

  pAddr->port = AMSPORT_R0_PLC_RTS1;

  nErr = AdsSyncReadDeviceInfoReq(pAddr, pDevName, pVersion);

  if (nErr){

      tmp1.setNum(nErr);

      tmp="Error:  AdsSyncReadDeviceInfoReq: " ;

      tmp+=tmp1;

      emit Errors(tmp);

  }

  else{

      tmp1.sprintf("%s",pDevName);

      tmp= "Name: ";

      tmp+=tmp1;

      tmp+="Version: ";

      tmp1.setNum((int)pVersion->version);

      tmp+=tmp1;

      tmp+="Revision: ";

      tmp1.setNum((int)pVersion->revision);

      tmp+="Build: ";

      tmp1.setNum(pVersion->build);

      tmp+=tmp1;

      emit OkMessage(tmp);

  }

  // Close communication port

  nErr = AdsPortClose();// Close communication port

  if (nErr){

      tmp=  "Error: AdsPortClose: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

}


//! Start/stop PLC

/*! The following program starts or stops run-time system 1 in the PLC. */

int Beckhoff::StartStopPlc(bool start)

{

    USHORT      nAdsState;

    USHORT      nDeviceState = 0;

    long        nErr, nPort;

    int         ch;

    void        *pData = NULL;

    //AmsAddr     Addr;

    pAddr = &Addr;


    // Open communication port on the ADS router

    nPort = AdsPortOpen();

    nErr = AdsGetLocalAddress(pAddr);

    if (nErr){

        tmp="Error: AdsGetLocalAddress: ";

        tmp1.setNum(nErr);

        tmp+=tmp1;

        emit Errors(tmp);

        return -1;

    }

    pAddr->port = AMSPORT_R0_PLC_RTS1;

    if(start==true){

        nAdsState = ADSSTATE_RUN;

    }

    else{

        nAdsState = ADSSTATE_STOP;

    }

    nErr = AdsSyncWriteControlReq (pAddr, nAdsState, nDeviceState, 0, pData);

    if (nErr){

        tmp="Error: AdsSyncWriteControlReq: ";

        tmp1.setNum(nErr);

        tmp+=tmp1;

        emit Errors(tmp);

        return -1;

    }

    // Close communication port

    nErr = AdsPortClose();// Close communication port

    if (nErr){

        tmp=  "Error: AdsPortClose: ";

        tmp1.setNum(nErr);

        tmp+=tmp1;

        emit Errors(tmp);

        return -1;

    }

}



//! Access an array in the PLC

/*!

An array, located in the PLC, is to be read by means of a read command. The variable is addressed here by its handle. The length of the whole array is provided as the length for the function AdsSyncReadReq(). The address of the first array element is given as variable.

*/

int Beckhoff::AccessAnArrayInThePLC()

{

  long          nErr, nPort;

  pAddr = &Addr;

  unsigned long lHdlVar;

  int           nIndex;

  short         Data[10];

  char          szVar []={"MAIN.PLCVar"};

  // Open communication port on the ADS router

  nPort = AdsPortOpen();

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr){

      tmp="Error: AdsGetLocalAddress: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  pAddr->port = AMSPORT_R0_PLC_RTS1;

  // Fetch handle for the PLC variable

  nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar), szVar);

  if (nErr){

      tmp="Error: AdsSyncReadWriteReq: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  // Read values of the PLC variables (by handle)

  nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(Data), &Data[0]);

  if (nErr){

      tmp="Error: AdsSyncReadReq: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  else

  {

      tmp="";

      for (nIndex = 0; nIndex < 10; nIndex++){

          tmp=+" Data[";

          tmp1.setNum(nIndex);

          tmp+=tmp1;

          tmp+="]: ";

          tmp1.setNum(Data[nIndex]);

          tmp+=tmp1;

          //emit SendData(tmp);

      }

      emit SendData(tmp);

  }

  // Close communication port

  nErr = AdsPortClose();// Close communication port

  if (nErr){

      tmp=  "Error: AdsPortClose: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

}



//! Event driven reading


/*!

If values from a PLC or NC are to be displayed continuously on a user interface, then it is very inefficient to use AdsSyncReadReq(), since this function must be called cyclically. By defining what are known as notifications (messages), a TwinCAT server can be made to transmit values via ADS to another ADS device. A distinction is drawn between whether the TwinCAT server is to transmit the values cyclically, or only when the values change.

A notification is begun with the AdsSyncAddDeviceNotificationReq() function. After this, the callback function is automatically invoked by TwinCAT. AdsSyncDelDeviceNotificationReq() is used to halt the notification again. Since the number of notifications is limited, you should ensure the notifications no longer required by your program are deleted. You will find further information under the description of the AdsNotificationAttrib structure.

The following program starts a notification on flag double word 0 in the PLC. Each time the PLC variable changes, the callback function is invoked. The callback function receives a variable of type AdsNotificationHeader() as one of its parameters. This structure contains all the necessary information (value, time stamp, ...).

Advice: Don't use time intensive executions in callbacks. Remind to sync your callback and your mainthread, if you access each other (e.g. critical sections, mutex, events).

*/



int Beckhoff::EventDrivenReading()

{

//  long                   nErr, nPort;

  //AmsAddr                Addr;

  //PAmsAddr

  pAddr = &Addr;

  //ULONG                  hNotification, hUser;

  AdsNotificationAttrib  adsNotificationAttrib;


  // Open communication port on the ADS router

  nPort = AdsPortOpen();

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr){

      tmp=  "Error: AdsGetLocalAddress: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  pAddr->port = AMSPORT_R0_PLC_RTS1;


  // Specify attributes of the notification

  adsNotificationAttrib.cbLength = 4;

  adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA;

  adsNotificationAttrib.nMaxDelay = 20000000; // 2sec

  adsNotificationAttrib.nCycleTime = 10000000; // 1sec


  // 32-bit variable (including pointers) that are passed to the callback function

  hUser = 3474573467;


  // Start transmission of the PLC variables

  nErr = AdsSyncAddDeviceNotificationReq(pAddr, 0x4020, 0, &adsNotificationAttrib, EventsInPlc, hUser, &hNotification);

  if (nErr){

      tmp=  "Error: AdsSyncAddDeviceNotificationReq: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      tmp+="Notification: ";

      tmp1.setNum(hNotification);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

  // Wait for a key-press from the user

  //getch();

}


int Beckhoff::StopEventDrivenReading()

{

  // Finish transmission of the PLC variables

  nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);

  if (nErr){

          tmp=  "Error: AdsSyncDelDeviceNotificationReq: ";

          tmp1.setNum(nErr);

          tmp+=tmp1;

          emit Errors(tmp);

          return -1;

  }

  // Close communication port

  nErr = AdsPortClose();// Close communication port

  if (nErr){

      tmp=  "Error: AdsPortClose: ";

      tmp1.setNum(nErr);

      tmp+=tmp1;

      emit Errors(tmp);

      return -1;

  }

}


/*

// Callback function

void __stdcall Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)

{

  int                     nIndex;

  static ULONG            nCount = 0;

  SYSTEMTIME              SystemTime, LocalTime;

  FILETIME                FileTime;

  LARGE_INTEGER           LargeInteger;

  TIME_ZONE_INFORMATION   TimeZoneInformation;


  cout << ++nCount << ". Call:\n";


  // Output value of the variable

  cout << "Value: " << *(ULONG *)pNotification->data << '\n';

  cout << "Notification: " << pNotification->hNotification << '\n';


  // Convert time stamp to SYSTEMTIME

  LargeInteger.QuadPart = pNotification->nTimeStamp;

  FileTime.dwLowDateTime = (DWORD)LargeInteger.LowPart;

  FileTime.dwHighDateTime = (DWORD)LargeInteger.HighPart;

  FileTimeToSystemTime(&FileTime, &SystemTime);


  // Calculate time in local representation

  GetTimeZoneInformation(&TimeZoneInformation);

  SystemTimeToTzSpecificLocalTime(&TimeZoneInformation, &SystemTime, &LocalTime);


  // Output time stamp

  cout << LocalTime.wHour << ":" << LocalTime.wMinute << ":" << LocalTime.wSecond << '.' << LocalTime.wMilliseconds <<

       " den: " << LocalTime.wDay << '.' << LocalTime.wMonth << '.' << LocalTime.wYear << '\n';


  // Size of buffer in bytes

  cout << "SampleSize: " << pNotification->cbSampleSize << '\n';


  // 32-bit variable (including pointers) that are set by AddNotification // (See main)

  cout << "hUser: " << hUser << '\n';


  // Output ADS address of the sender

  cout << "ServerNetId: ";

  for (nIndex = 0; nIndex < 6; nIndex++)

    cout << (int)pAddr->netId.b[nIndex] << ".";

  cout << "\nPort: " << pAddr->port << "\n\n";

  cout.flush();

}



*/


//!Access by variable name

/*!

The following program accesses a PLC variable that does not have an address. Access must therefore be made by the variable

 name. Once the PLC variable in the example program exceeds 10 it is reset to 0.

All data that ADS devices make available to the outside is organised by means of IndexGroups and IndexOffset.

An IndexGroup can be thought of as a table, with each entry being addressed by the IndexOffset.

The TwinCAT PLC has, for example, IndexGroups in which the variables that belong to the input/output or flags regions

 are stored. IndexGroups are also available to the TwinCAT PLC through which system functions may be addressed.

The IndexGroups ADSIGRP_SYM_HNDBYNAME and ADSIGRP_ SYM_VALBYHND are important for the example program.

The IndexGroup ADSIGRP_SYM_HNDBYNAME is used to request a handle from a PLC variable identified by name.

The variable can be accessed with the aid of this handle and the IndexGroup ADSIGRP_SYM_VALBYHND.

The variable's handle is passed as the IndexOffset.

*/

void Beckhoff::AccessByVariableName()

{

    int i=0;

  long      nErr, nPort;

  AmsAddr   Addr;

  PAmsAddr  pAddr = &Addr;

  ULONG     lHdlVar, nData;

  char      szVar []={"MAIN.PLCVar"};


  // Open communication port on the ADS router

  nPort = AdsPortOpen();

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr) qDebug() << "Error: AdsGetLocalAddress: " << nErr << '\n';

  pAddr->port = AMSPORT_R0_PLC_RTS1;


  // Fetch handle for an <szVar> PLC variable

  nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_HNDBYNAME, 0x0, sizeof(lHdlVar), &lHdlVar, sizeof(szVar), szVar);

  if (nErr) qDebug() << "Error: AdsSyncReadWriteReq: " << tmp.setNum(nErr);

  do

  {

    // Read value of a PLC variable (by handle)

    nErr = AdsSyncReadReq( pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(nData), &nData );

    if (nErr){

        qDebug() << "Fehler: AdsSyncReadReq: " << tmp.setNum(nErr);

        break;

    }

    else

      qDebug() << "Wert: " << tmp.setNum(nData);

    //cout.flush();

    if (nData > 10)

    {

      // Reset the value of the PLC variable to 0

      nData = 0;

      nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_VALBYHND, lHdlVar, sizeof(nData), &nData);

      if (nErr){

          qDebug() << "Error: AdsSyncWriteReq: " << tmp.setNum(nErr);

          break;

      }

    }

    i++;

  }while(i<10);  // read next value with RETURN, else end


  //Release handle of plc variable

  nErr = AdsSyncWriteReq(pAddr, ADSIGRP_SYM_RELEASEHND, 0, sizeof(lHdlVar), &lHdlVar);

  if (nErr) qDebug() << "Error: AdsSyncWriteReq: " << nErr << '\n';


  // Close communication port

  nErr = AdsPortClose();

  if (nErr) qDebug() << "Error: AdsPortClose: " << nErr << '\n';

}


//!Read PLC variable declaration

/*!

The following information is transferred when accessing the variable declaration:

    Variable name

    Data type

    Length

    Address (IndexGroup / IndexOffset)

    Comment

    All the information listed above is transmitted in a data stream. Before this can be read, the first AdsSyncReadReq() is used to obtain the length. The data itself is transferred with the second AdsSyncReadReq(). The pchSymbols variable is a pointer, pointing to this region. The FOR-loop copies the corresponding data region into the pAdsSymbolEntry structure for each individual PLC variable. The individual information items in the PLC variables are stored in this structure. The macros PADSSYMBOLNAME, PADSSYMBOLTYPE and PADSSYMBOLCOMMENT simplify the evaluation of this data.

*/

void Beckhoff::ReadPlcVariableDeclaration()

{

  long                  nErr, nPort;

  char                  *pchSymbols = NULL;

  UINT                  uiIndex;

  AmsAddr               Addr;

  PAmsAddr              pAddr = &Addr;

  AdsSymbolUploadInfo   tAdsSymbolUploadInfo;

  PAdsSymbolEntry       pAdsSymbolEntry;


  // Open communication port on the ADS router

  nPort = AdsPortOpen();

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr) qDebug() << "Error: AdsGetLocalAddress: " << nErr << '\n';

  pAddr->port = AMSPORT_R0_PLC_RTS1;


  // Read the length of the variable declaration

  nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_UPLOADINFO, 0x0, sizeof(tAdsSymbolUploadInfo), &tAdsSymbolUploadInfo);

  if (nErr) qDebug() << "Error: AdsSyncReadReq: " << nErr << '\n';

  pchSymbols = new char[tAdsSymbolUploadInfo.nSymSize];

  if(!pchSymbols){qDebug()<<"assertion rivi 547 beckhoff.cpp";}


  // Read information about the PLC variables

  nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_UPLOAD, 0, tAdsSymbolUploadInfo.nSymSize, pchSymbols);

  if (nErr) qDebug() << "Error: AdsSyncReadReq: " << nErr << '\n';


  // Output information about the PLC variables

  pAdsSymbolEntry = (PAdsSymbolEntry)pchSymbols;

  for (uiIndex = 0; uiIndex < tAdsSymbolUploadInfo.nSymbols; uiIndex++)

  {

    qDebug()<< PADSSYMBOLNAME(pAdsSymbolEntry) << "\t\t"

         << pAdsSymbolEntry->iGroup << '\t'

         << pAdsSymbolEntry->iOffs << '\t'

         << pAdsSymbolEntry->size << '\t'

         << PADSSYMBOLTYPE(pAdsSymbolEntry) << '\t'

         << PADSSYMBOLCOMMENT(pAdsSymbolEntry) << '\n';

    pAdsSymbolEntry = PADSNEXTSYMBOLENTRY(pAdsSymbolEntry); //cout.flush();

  }

  //getch();


  // Close communication port

  nErr = AdsPortClose();

  if (nErr) qDebug() << "Fehler: AdsPortClose: " << tmp.setNum(nErr);


  // Release memory

  if (pchSymbols) delete(pchSymbols);

}



//!Detect status change in TwinCAT router and the PLC

/*!

When an application is actually running it is often important to interrogate the status of TwinCAT and/or of its components; e.g., whether the PLC is in the RUN state. To avoid the need to repeatedly issue this inquiry, changes in the status can be detected very effectively with the aid of callback functions.

The following example program monitors the status of the PLC (run-time system 1) and of the TwinCAT router.

By invoking the AdsAmsRegisterRouterNotification() function, the given callback function will be invoked every time the status of the TwinCAT router changes. The current status can be interrogated by means of the parameters that are transferred.

The AdsSyncAddDeviceNotificationReq() is used to monitor the status of the PLC. The data that is passed to the callback function represents the current status of the PLC.

uses void __stdcall ADS_StateCallback(AmsAddr*, AdsNotificationHeader*, ULONG);

uses void __stdcall RouterCall(LONG);

*/

int Beckhoff::DetectStatusChangeTwinCatRouterAndPLC()

{

  LONG                    nErr, nPort;

  ULONG                   hNotification, hUser = 0;

  AmsAddr                 Addr;

  PAmsAddr                pAddr = &Addr;

  AdsNotificationAttrib   adsNotificationAttrib;


  // Open communication port on the ADS router

  nPort = AdsPortOpen();

  nErr = AdsGetLocalAddress(pAddr);

  if (nErr){ qDebug() << "Error: AdsGetLocalAddress: " << tmp.setNum(nErr);}

  pAddr->port = AMSPORT_R0_PLC_RTS1;


  nErr = AdsAmsRegisterRouterNotification(&RouterCall);

  if (nErr){ qDebug() << "Error: AdsAmsRegisterRouterNotification: " << tmp.setNum(nErr);}


  // Invoke notification

  adsNotificationAttrib.cbLength       = sizeof(short);

  adsNotificationAttrib.nTransMode     = ADSTRANS_SERVERONCHA;

  adsNotificationAttrib.nMaxDelay      = 0; // jede Aenderung sofort melden

  adsNotificationAttrib.dwChangeFilter = 0; //

  nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_DEVICE_DATA, ADSIOFFS_DEVDATA_ADSSTATE, &adsNotificationAttrib, ADS_StateCallback, hUser, &hNotification);

  if (nErr) { qDebug() <<  "Error: AdsSyncAddDeviceNotificationReq: " << tmp.setNum(nErr);}


  // The following calls return errors if TwinCAT is halted

  nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);

  if (nErr) { qDebug() << "Error: AdsSyncDelDeviceNotificationReq: " << tmp.setNum(nErr);}


  nErr = AdsAmsUnRegisterRouterNotification();

  if (nErr) { qDebug() <<  "Error: AdsAmsUnRegisterRouterNotification: " << tmp.setNum(nErr);}


  nErr = AdsPortClose();

  if (nErr){ qDebug() <<  "Error: AdsPortClose: " << tmp.setNum(nErr);}

  return 1;

}




  • No labels
You must log in to comment.