LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Reading LabView signals through DLL calls from Java

Hello,

I have the following problem. I have built a GUI in Java that will display a "real-time" graph of certain LabView measurement. The VI which generates the signals has to be executed from Java. Browsing through the forums, I've been driven to think that building a DLL of the VI and calling it from Java is the easiest way to go. So I've generated the DLL with this function prototype:

 

void Test(double In2, double *Out2)

 

Where Out2 is the measurement I'm interested in. The execution of Test lasts 5 seconds but I want to read the values of Out2 every (say) 100ms. I know how to call the DLL from Java (using JInvoke), but I'm not really sure how to make those measurements. What I've attempted is a multi-thread approach: One thread calls Test and the other loops while reading the value of Out2... But all I get is a measurment of 0 during the execution of the DLL and a -1.9178.. value after Test ends. I should point out that this -1.9178.. value is exactly the last data point of the measurement. I am by no means an expert but wouldn't that suggest that the memory register where Out2 gets stored is only getting updated after Test ends?

 

I'm really new to LabView so I'm not sure if this problem has to do with the Java code or something to do with the VI.. how the blocks are connected or something....?

 

Thanks

 

0 Kudos
Message 1 of 2
(2,823 Views)

I know it's not the same problem/application but I think it will help! I have to measure 1ms signal through twincat tcadsdll.dll, from beckhoff. When I call the dll function that will read the VALUE from PLC the sampling time is too slow. Beckhoff solution is too bypass windows and use what they call as notifications (messages). I'm still trying to see how I can program this in Labview, If anyone knows how to read a fast signal from beckhoff modules in LABVIEW please help! 

http://www.ackermann-automation.de/ have a library that can read Beckhoff modules in Labview, I'm still looking on it.

 

Searching Beckhoff help system I've found this:

 

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.

#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <winbase.h>
#include "c:\twincat\ads api\tcadsdll\include\tcadsdef.h"
#include "c:\twincat\ads api\tcadsdll\include\tcadsapi.h"

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

void main()
{ 
  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) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
  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, Callback, hUser, &hNotification);
  if (nErr) cerr << "Error: AdsSyncAddDeviceNotificationReq: " << nErr << '\n';
  cout << "Notification: " << hNotification << "\n\n";
  cout.flush();

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

  // Finish transmission of the PLC variables 
  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 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(); 
0 Kudos
Message 2 of 2
(2,649 Views)