LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Flexible Control of an RT Target State?

Solved!
Go to solution

Hi,

 

I'm developing a project which requires a desktop computer hosting a LabVIEW application to control the state of a RT target (myRIO). The problem I'm running into is that I'd like to be able to control what phase the RT target is working in, such as Initialize, Configure, Shutdown, Idle. This seems to call for a State Machine design pattern, but the trouble is that I'd also like to make sure that the data these different states are dependent on are configured appropriately before they're exectured.

 

So my question is as follows:

Is there any existing design pattern that allows us to reliably queue up different states to control a real time target, whilst ensuring that every time we queue a 'Configure' state, for example, all of the data that the Configure state is dependent on is queued with it?

 

What I've been thinking:

I've been thinking that an array of desired states could be held within an object, and that we're only able to read the state of the object publically; setting the array is private to the object. A set of publically accessible methods to that class could be called so that for each addition of a new state to the state queue would be done through a SubVI, whose connector pane defines the data dependencies. However I'm not sure how you'd get this working between both the PC and the RT target, since LVOOP is pass by value rather than pass by reference.

 

I'd really like to hear your thoughts.


Alex Thomas, University of Manchester School of EEE LabVIEW Ambassador (CLAD)

0 Kudos
Message 1 of 6
(2,597 Views)

I just thought of something that could work.

 

Maybe instead of a single object holding the state, the object could define the state instead. For example, we could have a generic class called State, which has a dynamic dispatch VI called Execute State. Another class called Configure could extend State, who could override Execute State to perform configuration specific operations; and an instantiation of Configure would need all of the data it's dependent on. Establishing control of the RT application could be done by buffering State objects.


Alex Thomas, University of Manchester School of EEE LabVIEW Ambassador (CLAD)

0 Kudos
Message 2 of 6
(2,587 Views)

Hi Alex,

 

A quick approach to passing data back and forth between a host and RT system could be through the use of Shared Variables, would this possibly be a solution to your problem? I think this would let you pass through your configuration data as well as the state information you need.

 

To build up a queue of states, you could implement a kind of queued message handler, where instead of an event structure, you feed into the queue with a network shared variable, but I'm not sure if this is what you meant by queuing up states for your RT. For controlling the flow of your code for the Initialize, Configure and Shutdown states could be coded directly into the state machine, and then user input may be needed for the idle states or when re-configuration is needed through the network shared variable?

 

Overview link just incase: Real-Time VI to Host VI Communication Methods

 

Hope this helps

0 Kudos
Message 3 of 6
(2,510 Views)

LabVIEW 2012 and 2013 ship with two Real-Time Project Templates that you can use to do what you want.  They use a Queued Message Handler as the main "State Machine" loop, which allows (indeed, encourages) you to pass in the Configuration parameters when you call Configure.  They also use Network Streams to allow the Host to "send Messages" (a.k.a. Commands) to the Target, and the Target to send Messages to the Host.

 

BS

0 Kudos
Message 4 of 6
(2,504 Views)
Solution
Accepted by topic author Alex.T

Hi,

 

Thanks for your help guys. I had considered Shared Variables, and got these working originally, but I was hoping for a solution that would be a bit more flexible rather than static instanation of various control parameters which is commonly what Shared Variable implementations seem to expect. I also wanted to create an architecture that was a bit 'stricter', I didn't want to be transmitting variant data types across with 'next state' commands so that I could avoid error cases where the data could might processed inappropriately. I felt like the application was begging for OOP!

 

To get around this, I created a design pattern which I've dubbed the 'Classy State Machine', which uses LabVIEW classes to define the functionality of a particular state within a class, rather than defining it on the runtime platform. I'm hoping this will lead to a more flexible design, allowing you to interchange the functionality of the RT target by transmitting new state objects, whilst also ensuring that the data that is critical to the state is transmitted along with it. I've uploaded an example demonstrating it's functionality here.

 

Classy State Machine.png

 

 


Alex Thomas, University of Manchester School of EEE LabVIEW Ambassador (CLAD)

0 Kudos
Message 5 of 6
(2,470 Views)

Very pretty.  While you've marked it as a "solution", it could be much better.  Here are some suggestions.

  • Instead of "rolling your own Queue" using the Array functions (it took me a while to realize that's what you were doing with your States), use LabVIEW's Queue Operations (much neater, much less prone to error, much more understandable).  Loop 4 is an Enqueue, loop 5 is a Dequeue.  Queues work much better when they are in separate, parallel loops, as it lets each one run at its own speed.
  • Take your states off the Network Stream one at a time (instead of All at Once, which requires a For Loop to handle them).  Putting them into a real Queue would be a wonderful idea.
  • You seem to have discovered the Queued Message Handler, but have "hidden" it by using Objects.  There's a wonderful presentation (maybe by Elijah Kerry) discussing LabVIEW Objects that shows how you can use Objects to "morph" the Queued Message Handler into the Command Design Pattern for even greater flexibility.
  • By using a Time-Out on the Read Message Stream function, you can eliminate the "wasted" 90 msec in the loop.  Just process the states as they arrive, letting the Read "block" for you.

The Sample Projects that I mentioned would illustrate most of these ideas.

0 Kudos
Message 6 of 6
(2,435 Views)