Real-Time Measurement and Control

cancel
Showing results for 
Search instead for 
Did you mean: 

Best Architecture - Object Oriented Programming on a Desktop and Real-time Target. Best method of passing data between classes on both targets?

Hi Muelmann,

 

If you are making a command-based architecture I suggest not using shared variables.  Shared variables are excellent for monitoring data such as temperatures, pressures, etc.  Shared variables are also good for asynchorous setting like P, I, and D constants for PID control loops.  Shared variables are not very effective for command-based architecture, because they rely on polling methods to ensure that no messages are missed.

 

If you are doing message based communication I suggest you use TCP or UDP.  You don't have to start from scratch building your communication scheme.  You could use something like:

http://zone.ni.com/devzone/cda/epd/p/id/2739

http://zone.ni.com/devzone/cda/epd/p/id/6091

 

To coordinate the host and RT machine with up-to-date private data, you could  flatten the data and send it overTCP.  I haven't tried it but it seems reasonable.

Brian K.
0 Kudos
Message 11 of 20
(3,064 Views)

I use NSV's all the time for such 'command' architectures.  They are lossless when buffering is enabled, plus they can be formed from any LV data structure.

My current method also employs a 'return notification' to verify that a message was received.

0 Kudos
Message 12 of 20
(3,055 Views)

sachsm is correct about variable buffering. As long as you don't overflow the buffer, you won't lose data since the protocol is built on TCP. When you enable buffering you just have to be aware of the behavior you get. Each time the node executes on the diagram you will get the oldest point in the buffer, like any FIFO. Therefore, if you are only concerned with the latest value you should not use buffering. For commands, buffering works great. You can monitor the timed out? output or error cluster of the variable to know if you are reading stale data. 

 

Muelmann, I think what you are currently doing sounds straight forward and maintainable (sending a command and variant data to update an object).

 

However, I hesitate to say "go for it" when you start talking about trying to reflect the objects across both targets.

 

How many objects will your application have?

 

Will you be dynamically creating new object while your application is running?

 

Similar to what sachsm suggested with variable typedefs... If your objects are statically defined, meaning you are not creating objects at run-time, then you could use shared variables to hold your object data and use the methods of each class to update the shared variable value. However, then you would also have to create a mutexing scheme so you don't edit the data on both targets at once. Here we are talking about a mutex that is shared over the network... yikes.

 

Does your application need to run deterministically? If so, I would definitely avoid any kind of mutexing with the host PC.

 

I would stick with your current implementation if possible.

 

 

One more idea... not sure if this is a good idea or not and it may depend on your application, but one other idea would be to use some kind of batch update to all the objects, rather than trying to track all the changes at run-time on both targets. For example, when a user wants to change some object data from the host, you could:

 

1) Have cRIO stop modifying object data

2) Have cRIO send all object data to the host

3) The user updates the object data on the host

4) The user "commits" the changes they have made

5) Send all the object data back to cRIO, updating its local copy of all the object data

6) continue with the application...

 

That seems more managable than synch'ing every change that occurs individually.

 

Kurt 

 

 

Message Edited by jkurtw on 09-15-2009 09:34 PM
0 Kudos
Message 13 of 20
(3,054 Views)

The RT target will host 2 objects and I do not plan to dynamically create any new objects while the application is running.

 

The project I'm working on is a hardware in the loop simulator.  Particular outputs of the simulator need to be ran in either an "Auto" or "Manual" mode; the "Auto" mode being where the RT target determines the values of certain outputs and the "Manual" mode being where the Desktop target (user) determines the values of the outputs. 

 

I think I will avoid having the shared variables hold the object data.  I'm still thinking of implementing an architecture similar to what I mentioned in my post above (it's basically the queued message handler/state machine architecture where particular cases of the state machine call methods on the class data stored on that target). 

 

With this implementation, I'm thinking that I can avoid the issue of both targets updating the data at the same time by using an "Auto/Manual" control.  The state of the "Auto/Manual" control would only be controlled by the Desktop target.  Also, there would be a unique "Auto/Manual" control for each set of data that could potentially be modified by either the RT target or the Desktop target (separate controls are needed because it's possible for some outputs from the simulator to be in an "Auto" mode while others are "Manual"). 

 

Whenever the user sets this control to "Auto", the RT target can freely modify the data that is associated with it and the Desktop target will receive updates of this data on a periodic basis (approximately 2 Hz) so that it can display the data to the user.  By updating the Desktop target's data on a periodic basis rather than on a "on-change" basis when the RT target has control of the data, I think I can cut down on the traffic being sent over the shared variables. 

 

When the control is set to "Manual" then the RT host will not be allowed to modify the data; the desktop target will send updated data values to the RT target whenever the user modifies the data.  The RT target will act on whatever data is stored in the object at the time it needs to update the outputs of the hardware.  By implementing it this way, I'm hoping I can avoid mutex issues associated with the Desktop putting a lock on the data and slowing down the RT target.  

 

Does this make sense?  I really appreciate your feedback.  Bouncing these ideas around has helped me a lot.

 

 

Muelmann

 

0 Kudos
Message 14 of 20
(3,025 Views)

I am still not sure why NSV's would not work for your application.  The descriptions you gave sound very much like the system that I have running.  Isn't your Auto/Manual switch sufficient to prevent

both RT and desktop from controlling at the same time?  I do this all the time with my cRIO based PID controls.  In Auto mode the cRIO writes to NSV's that are transfered to the hardware and reads from NSV's that contain the PID gain settings.  In manual mode the cRIO PID outputs can be manually controlled from the PC.  Also, with NSV binding to my GUI all data is automatically reflected from the PC to the cRIO and from the cRIO to the PC.  Bindings are event driven with deadbanding and very efficient.  I have also developed remote tcpip communications but only use it for modal commands.

0 Kudos
Message 15 of 20
(3,022 Views)

sachsm,

 

When you use NSV's in a command architecture you would enable buffering and when you use NSV binding of your GUI data you wouldn't use buffering, correct? 

 

Have you used NSV's in an object oriented programming approach to hold data from objects and then use the methods of each class to update the shared variable value as Kurt suggests above?

 

I would need the DSC module to set the update deadbands for network shared variables, correct? 

 

Thanks.

0 Kudos
Message 16 of 20
(3,015 Views)

When you use NSV's in a command architecture you would enable buffering and when you use NSV binding of your GUI data you wouldn't use buffering, correct? 

 

Yes.

 

Have you used NSV's in an object oriented programming approach to hold data from objects and then use the methods of each class to update the shared variable value as Kurt suggests above?

 

No, but it sounds like a good idea 🙂

 

I would need the DSC module to set the update deadbands for network shared variables, correct? 

 

Yes.

 

0 Kudos
Message 17 of 20
(3,011 Views)

Muelman,

 

I don't know if this helps, but I have been running an OOP project on a RT target using NSVs with some success (although I am now at the executable build stage and seem to have hit a hiccup).  Forgive me if none of this is helpful, but below is part of the diagram that runs on the target:

 

OOP RT Example.png

 

Although not everything is shown here, you should get the basic gist.  This program runs a set of five lasers and there corresponding cooling/flow systems and can run headless based on config settings found in an INI file.  The instrument is modeled using a single class and consists of another class instantiated 5x representing the lasers as well as a data class that contains all of the data relevant for storage, display and decision making for operation.  In the first part (1), the main class is instantiated and stuffed into a data value reference (DVR) and the RT FIFO used to control the state of the target is opened.  In the figure show here, when the target is acquiring, the DVR is dereferenced and the class is accessed to make measurements.  The dereferenced class is accessed by a measurement static dispatch VI within the In Place Reference (2).  That same dereference class is also piped to some analysis VIs (3) allowing me to take advantage of LVs parallel processing capabilities by both capturing and processing the data simultaneously.  The analyzed data is then stuffed into the data class that the main instrument class has instantiated.  That data object is then pumped out, flattened to string and stuffed into the corresponding NSV (you can not pass data as an object or variant through an NSV) (4). 

 

In the bottom loop, I am simply polling NSVs that are bound to a UI on the host to see if a state change has been requested by the user.  Using the DVR, I both the event polling loop (bottom) and the control loop (top) have access to the same data set.  The In Place Element structure locks other attempts to access the DVR out until the reference is returned so it acts as a natural mutex to prevent data clashes.

 

As you can probably tell, this is still in development.  I have successfully executed this from the project, but have been having some (confounding) issues when trying to compile this to an executable - NSVs come up in funny states when they come up at all; when the whole program above is compiled and run as the startup, it doesn't seem to want to actually execute.  But other than that, everything is just dandy Smiley Wink.

 

Anyway, hope this is somewhat helpful (if not entertaining).  And consider joining Hooray for Objects! and tell us how it turns out.  I am hoping to actually start posting some of my own shenanigans at some point which should be mildly entertaining.

 

Peace, Matt

0 Kudos
Message 18 of 20
(2,421 Views)

Hey Matt,  I found that in LV 2009 you may need to wait a certain amount of time before trying to perform transactions with the SVE.  Before things improved in LV2010 I had init code in place that would delay and also loop on a NSV read node waiting for the error code to go away before proceeding into the main part of my RT app.  I also noticed a difference in this behavior between running from the DE and an EXE, it drove me crazy for a long time until I realized what the race condition was. 

0 Kudos
Message 19 of 20
(2,401 Views)

Thanks, sachsm.  I am going to try to not hijack this thread so this is the last thing I will say about the executable issue. I am using 2010 instead of 2009 so I am not sure that is the issue.  I have tried removing any SVs that control whether the program actually exectures (i.e. this would mean that the program would start, go and then you would have to kill power to stop the system instead of a proper shutdown) and it appears that the executable is not even firing (minimal CPU activity).  So, it is not immediately obvious whether this is the SV portion of the project, the OOP portion or some other issue that is creating problems.  I will post another thread when I get a chance to look at this again.

 

m

0 Kudos
Message 20 of 20
(2,371 Views)