Event-Driven Detection of Changes to the Symbol Table

Download: 'Event-Driven Detection of Changes to the Symbol Table'.

ADS devices that support symbol names (PLC, NC, ...) store those names in an internal table. A handle is assigned here to each symbol. The symbol handle is necessary in order to be able to access the variables (see also Example 9). If the symbol table changes because, for instance, a new PLC program is written into the controller, the handles must be ascertained once again. The example below illustrates how changes to the symbol table can be detected.

#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <winbase.h>

// ADS headers for TwinCAT 3
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"

void __stdcall SymbolChanged(AmsAddr*, AdsNotificationHeader*, unsigned long);

void main()
{
long nErr;
AmsAddr Addr;
PAmsAddr pAddr = &Addr;
ULONG hNotification;
AdsNotificationAttrib adsNotificationAttrib;

// Open communication port on the ADS router
AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);
if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';

// Select Port: TwinCAT 3 PLC1 = 851
pAddr->port = 851;

// Specify attributes of the notification
adsNotificationAttrib.cbLength = 1;
adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA;
adsNotificationAttrib.nMaxDelay = 5000000; // 500ms
adsNotificationAttrib.nCycleTime = 5000000; // 500ms

// Start notification for changes to the symbol table
nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VERSION, 0, &adsNotificationAttrib, SymbolChanged, NULL, &hNotification);
if (nErr) cerr << "Error: AdsSyncAddDeviceNotificationReq: " << nErr << '\n';

// Wait for a key-press from the user
getch();

// Stop notification
nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);
if (nErr) cerr << "Error: AdsSyncDelDeviceNotificationReq: " << nErr << '\n';

// Close communication port
nErr = AdsPortClose();
if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
}

// Callback function
void __stdcall SymbolChanged(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)
{
cout << "Symboltabelle hat sich geändert!\n";
cout.flush();
}