06-08-2011 04:02 PM
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
08-02-2011 05:06 PM
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:
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; staticULONG
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();