Register    Login
 
Professional OPC Development Tools
And Services
 
 
SupportOnline Forums
 
Links: Related Pages
 
Links: Related Services
 
Links: Related Support
 
Links: Related Resources
 
Online Forums

Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see link in upper right corner) in order to Post questions. You do not have to be a licensed user.

OPC Labs team is actively monitoring the forums, and provides answers as soon as possible. For your convenience, we have also assembled a Frequently Asked Questions page.

Please do not use the Contact page for technical support.

HINT: You may use the Search feature (magnifier icon below) in the forums to locate the information you need. You can also search our entire Web site (the search box in the upper right corner of every page).

 
 
SupportSupportDiscussions (re...Discussions (re...QuickOPC-ClassicQuickOPC-ClassicQuickOPC-COM  QuickOPC-COM OPC Read/Write issues in VS2005 C++OPC Read/Write issues in VS2005 C++
Previous Previous
 
Next Next
New Post
 11/30/2011 7:29 AM
 
Hi there,

I am new to both DCOM, OPC and QuickOPC development ... so I apologize in advance for trivialities. My task is to read several values from an OPC server, to do some processing and to write some values back to the same server. This loop is repeated every few seconds essentially forever.

For development I am using C++ in VS2005, so I started with the example called Examples\CPP\VS2008\Win32\ReadMultipleItems. After some initial troubles, I can compile and run this and it works. However, I'm having three issues at a second look ...

1. I looped the code in that example's main function to read 1027 items each time. It takes 4.2 seconds to execute on each loop. The OPC server is on another machine but the network is fast. Is this normal? What can I do to hurry this up? I would like to do it in under 1 second. One point may be to declare the various members somewhere outside but I am not familiar enough with DCOM to do this and have it still work ... help?

2. The function "->Vtq" on line 37 of that example rarely but sometimes fails returning an exception in debug mode. No text is output just a FAILED macro returns an opc_issue exception ... what can I do? How can these errors be caught and nicely dealt with?

3. I attempted to rewrite the same example to do writing ... I failed. Basically, I have an array of doubles that I have to write out. The conversion of that to VARIANT and so on is something that I probably messed up. I'm trying to use the function ReadMultipleItemValues and this crashes. Can someone show how to convert an array of doubles to the right VARIANT array that will work with this function.

Basically what I am looking for is the ReadMultipleItems example broken into two bits - initialization of everything and the core suitable for looping - and then also extended for writing an array of values and possibly for error checking.

Btw, the OPCserver I have to link to does not support subscribing to values, so I really must poll them all on every loop ...

Thank you very much!
New Post
 11/30/2011 11:11 PM
 

Hello.

Ad 1. I am assuming that those 4.2 seconds are for 2nd and subsequent invocations of the method (the first invocation causes various startup tasks and can take longer than subsequent ones). If all invocations take so long, there might be various reasons for this. I do not want to enumerate them all here, so let's start with one, and if that is not the reason, we will continue investigating deeper. Please start by doing this experiment: Run the EasyOPC Utility, and on the OPC-DA Globals tab, under Client Parameters, change "Trocessing interval timeouts" from 50 to 150, and change "Topic processing total timeout" from 1000 to 5000. These are tunings that could help the performance with larger number of items. After making this change, press OK, and make sure that the EasyOPC process is not running (easyopcl.exe in Task Manager), so that when you start your application, it gets a chance to pick up the new values. Please repeat your measurements then and let me know the results.

Ad 2. The code in ReadMultipleItems example is not complete with regard to error handling. The proper approach would be to test the DAVtqResultPtr->Exception for null-ness. Only if it is NULL, the DAVtqResultPtr->Vtq is valid and can be accessed. If the Exception is not null, obtain IComException interface from it, and handle it, using fields such as Message and HResult. You will see an example of it in the example I will send for point 3 below. I will need to know the details of that exception (Message, HResult, ...) in order to tell you more about what is happening.

Ad 3. Please see this thread: http://www.opclabs.com/Support/Online... for example that writes multiple values and works.

Best regards

New Post
 12/1/2011 12:26 AM
 
Thank you for your helpful suggestions.

Ad 1. I made those changes and it did not improve. The times are the same as before. The very first time that I start my program, the first read loop takes about 16 seconds, after that the loop takes about 4 seconds. However when I then start my program a second time, even the first loop execution takes about 4 seconds and then remains at that level ...

Ad 2. Using your method, I retrieved an error. It occurs particularly with 2 of my over 1000 items and says: "Topic not updated for the first time (timeout)."

Ad 3. Using your example, the writing operation now writes. Thank you.

With regard to the timing problem, could it be related to having to instantiate various object on every execution of the loop, e.g. the IEasyDAClientPtr or the CComSafeArray ResultArray among several others?
New Post
 12/2/2011 12:33 AM
 

I made a test with 1000 items, using our simulation server, locally. The time to read these 1000 items (on subsequent reads) is around 1 second. Doing this over network, and with server that may (or may not) have lower performance, is therefore likely to give a time that is considerably higher than 1 second.

I understand that you are looking for better performance, so I plan to do more tests in order to see whether this can be improved further, in a hope that if they help with my test, they may be beneficial to your situation, too.

I know that your network is fast; have you, however, made a test where the OPC server and OPC client are both on the same machine, so that we have trusted information about whether the bottleneck has to do with the communication, or something else (performance of the client or the server)?

Can you please tell me which OPC server are you connecting to? I find it hard to believe that it does not support subscriptions. It would be very unusual (and clearly not compliant with OPC); in addition, I think that the server must at least "pretend" that it does support them, because we are calling functions that are related to subscriptions, and if they were failing, you would be getting error messages.

As you know, repeated reads are inefficient, so I am trying to figure out why we cannot go "the right way". The expected sustained throughput with subscriptions (locally) can be 4000 changes per second or more.

Instantiating unnecessary objects inside the loop is not particularly good, but I do not think it has a substantial influence in this case. I still suggest that you move the creation of EasyDAClient object outside the loop. I suppose that the times you are giving are just for the read method call (these other things should not be significant anyway, but should be ruled out in the timing nevertheless).

New Post
 12/4/2011 4:22 AM
 
I did more careful timings. The single line

CComVariant vResults(EasyDAClientPtr->ReadMultipleItems(machine.c_str(), server.c_str(), CComVariant(LPSAFEARRAY(*ItemInArray)), vMissing));

takes about 1.5 seconds each subsequent time. The following code takes another 2.5 seconds each time

for(i = ResultArray.GetLowerBound(0); i < ResultArray.GetUpperBound(0); ++i)
{
IDAVtqResultPtr DAVtqResultPtr(ResultArray[i]);
if(DAVtqResultPtr->Exception == NULL)
{
IDAVtqPtr DAVtqPtr(DAVtqResultPtr->Vtq);
value[i] = (float) DAVtqPtr->Value.dblVal;
}
else
{
ICOMExceptionPtr COMExceptionPtr = DAVtqResultPtr->Exception;
_tprintf(_T("%d: failure: %s\n"), i, COLE2T(COMExceptionPtr->Message));
}
}

so it seems that the actual reading time concurs with yours given that my network adds some overhead. However getting the result out of the data structure is expensive. Am I doing something wrong? I should note that the number of exceptions is low, so that the part in the else clause does not matter much.

The OPC Server that I'm connecting to is part of a package called RecordData, which is an internal developement of a power provider in Germany, so it is not a standard commercial OPC server. I will try to do it with subscriptions and see how far I get.
Previous Previous
 
Next Next
SupportSupportDiscussions (re...Discussions (re...QuickOPC-ClassicQuickOPC-ClassicQuickOPC-COM  QuickOPC-COM OPC Read/Write issues in VS2005 C++OPC Read/Write issues in VS2005 C++

 
 
 
 
 

 
 
 
 
Home|Services|Products|Purchase|Downloads|Support|Resources|Company|Contact
Copyright 2007-2012 by OPC Labs Terms Of Use Privacy Statement May 20, 2012