Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Twincat ADS event driven reading stops working after a while (Java)

We developed a Java application which uses the TwinCat ADS library (DLL) to read, write and handle events from the Beckhoff PLC (CX5120). We successfully run this on several machines but unfortunately we’re currently having a problem case where the event handling suddenly stops. This is the exact scenario we went through:

  • Read, write and events are handled correctly.
  • Suddenly we don’t get any events at all anymore, reading and writing are still working correctly though.
  • Replaced the PLC for another one, started working successfully again. We assumed it was a licensing problem then.
  • After a week of unattended running, the same problem started again, PLC/ADS library seems not to be triggering events anymore and we can’t seem to get it working again in any way. Reading/writing still working as it should.

Tested using another PC with the Java application, same problem. So something in the PLC seems to freeze up / stop working.

Here's how we have setup the event handling:

// Implementation of the CallbackListenerAdsState interface
public class ADSEventController implements CallbackListenerAdsState {

......

// Register itself as listener for the ADS events (in constructor)
callObject = new AdsCallbackObject();
callObject.addListenerCallbackAdsState(this);

....

// Event handling
public void onEvent(AmsAddr addr, AdsNotificationHeader notification, long user) {
    log.info("Got ADS event for handle[{}] and with raw data[{}]", user, notification.getData());

......

// Registering notification handles for PLC variables
// If we already assigned a notification, delete it first (while reconnecting)
    JNILong notification = new JNILong();
if(var.getNotification() != null) {
    notification = var.getNotification();
    AdsCallDllFunction.adsSyncDelDeviceNotificationReq(addr,notification);
}

// Specify attributes of the notificationRequest
AdsNotificationAttrib attr = new AdsNotificationAttrib();
attr.setCbLength(var.getSize());
attr.setNTransMode(AdsConstants.ADSTRANS_SERVERONCHA);
attr.setDwChangeFilter(1000);   // 0.01 sec
attr.setNMaxDelay(2000);        // 0.02 sec

// Create notificationHandle
long err = AdsCallDllFunction.adsSyncAddDeviceNotificationReq(
    addr,
    AdsCallDllFunction.ADSIGRP_SYM_VALBYHND, // IndexGroup
    var.getHandle(), // IndexOffset
    attr, // The defined AdsNotificationAttrib object
    var.getHandle(), // Choose arbitrary number
    notification);
var.setNotification(notification);

if (err != 0) {
    log.error("Error: Add notification: 0x{} for var[{}]", Long.toHexString(err), var.getId());
}
like image 853
Inth_TS Avatar asked Jul 19 '18 07:07

Inth_TS


1 Answers

We managed to find the cause. When we register a variable we get a handle (long) from the PLC, which, in our case unexpectedly started to be negative values after a while. We also used this long value as user reference for notifications, however, we found the user reference is an unsigned long in the ADS library.

So if we set a negative value of e.g. -1258290964 as ‘arbitrary number’ in the adsSyncAddDeviceNotificationReq call, the CallbackListenerAdsState onEvent method’s parameter ‘user’ (Long) got the unsigned long representation of our signed long user reference, which is 3036676332. In our Java application we used this user reference to match an event to a specific plc variable by this handle. Since, in our example, we expected -1258290964 but got 3036676332, we never handled any events.

like image 98
Inth_TS Avatar answered Sep 22 '22 12:09

Inth_TS