How to develop communication module between PLC and PC
The ADS protocol (ADS: Automation Device Specification) is a transport layer within the TwinCAT system. We use the ADS library provided by Beckhoff to communicate with the run time of the PLC. There are varieties of DLL provided by Beckhoff but we are talking here about DLL developed for the dot Net framework. The name of the DLL is TwinCAT.Ads.dll. This ADS library (DLL and library are used to mean the same thing in this document) wraps TCP/IP or UDP/IP protocols.
In this article, we shall develop our own DLL that will wrap the TwinCAT ADS DLL (TwinCAT.Ads.dll) for easy use. The DLL will be used to read-write data from PLC. It will notify us when some variables in the PLC have changed as well.
If you have seen the article https://www.hemelix.com/scada-hmi/twincat-hmi/beckhoff-twincat-hmi-javascript-framework-verses-extension-module/ then you may have noticed we have a module in the C# path that is PLC Data driver. We shall develop and describe how we can develop that module in this article. The bigger picture of the sample application will be as shown in the following image.
PLC DataManager is a DLL developed by us that can be loaded and linked by any application such as TwinCAT HMI, windows application, and so on. This is a helper class that implements reading, writing, and subscription mechanism. See how the events work in C# at https://www.hemelix.com/software/csharp-tutorial/
private TcAdsClient adsClient;
adsClient.AdsNotificationEx += new AdsNotificationExEventHandler(adsClient_AdsNotificationEx);
private void adsClient_AdsNotificationEx(object sender, AdsNotificationExEventArgs e)
{
string tag = null;
int handle = (int)e.UserData;
tag = variableHandles.FirstOrDefault(x => x.Value == handle).Key;
if (tag != null && ChangeUpdate != null)
{
ChangeUpdate(tag, e.Value); //notify to upper level of the application
}
}
If we use TwinCAT.Ads.dll library in our visual studio project and we add a reference to the DLL then we can declare a variable type TcAdsClient. We need to create an event handler to get notification from the DLL. We pass a handler function when some thing happens that interests us ( see event section of https://www.hemelix.com/software/csharp-tutorial/).
If we use APP(WindowsFormsApp1) then we need to subscribe to the needed variables by ourselves and on the other hand, if we use APP (WindowsFormTestWithDLL) then the subscription is done in the PLC DataManager module.
If we use the ADS library directly then we need to subscribe to the change notification by ourselves.
notificationHandles.Clear();
try
{
//register notification
notificationHandles.Add(adsClient.AddDeviceNotificationEx("MAIN.testBool", AdsTransMode.OnChange, 100, 0, handleBool, typeof(Boolean)));
notificationHandles.Add(adsClient.AddDeviceNotificationEx("MAIN.testInt", AdsTransMode.OnChange, 100, 0, handleInteger, typeof(Int16)));
notificationHandles.Add(adsClient.AddDeviceNotificationEx("MAIN.testReal", AdsTransMode.OnChange, 100, 0, handleReal, typeof(float)));
notificationHandles.Add(adsClient.AddDeviceNotificationEx("MAIN.testString", AdsTransMode.OnChange, 100, 0, handleString, typeof(String), new int[] { 80 }));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Download the test project ADS_Windows_Example_Hemelix.zip, there are 4 modules in the solution as described in the following table.
Tips
=> When we create DLL it is better to make or use same .NET Framework. If these are different then we have strange problems, hard to debug.
=> If you run the test sample on your PC then the PLC and PC should be in the same network (same LAN or VPN)
=> The PLC AMS Net ID should be added to the PC, more https://www.hemelix.com/automation/structured-text-how-to-add-route-for-plc/
=> short iclwValue = 0; //if we write int icwValue = 0; will cause problem in ADS, see the data type
Tips
=> Our old .Net friend TwinCAT.Ads.dll does not work fully with later version of TwinCAT run time. I see some older .Net program with that DLL works OK but the same program does not work OK with later version of TwinCAT program.
I see if I update the DLL from package manager (I tried version 4.x) from the following page and it seemt OK
=> ADS State
‘%s%ADS.Diagnostics::runtime::PLC1::adsState%/s%’
adsState can be for example,
11 => Error
adsState is returned as a string, for example, if the PLC is not in ‘Run’ mode then we can prompt an error
=> ADS State Change By ST Code
Tips
Tips 01:
Windows data type and size are different in TwinCAT structured text. This causes problems, especially when we write data over ADS in C#. Here is an example, we have declared a variable in the Windows program as the following
int myWinInt = 200;
object rawValue = myWinInt ;
client.WriteAny(handle, rawValue); // This will throw an exception “parameter size not correct” if the variable in PLC is declared as INT type.
myPLCIntType : INT := 0; //Declared in PLC
Solution:
Make sure the data size in PLC is equal to or higher than the size of the Windows variable, the above case can be solved in the following way.
int myWinInt = 200; // 4 bytes in Windows
myPLCIntType : DINT := 0; // 4 bytes in PLC
OR
short myWinInt = 200; // 2 bytes in Windows
myPLCIntType : INT := 0; // 2 bytes in PLC
DownLoad the sample
Download the sample from the link given above.
Next, let’s try to understand how to publish at https://www.hemelix.com/scada-hmi/twincat-hmi/how-to-publish-twincat-hmi/
Ask questions related to Hemelix sample code and design at Google group https://groups.google.com/g/hemelix