Jump to content
LewisG

Architecture Help - Actor Framework, State Machine?

Recommended Posts

I have to develop an application and I would like some help designing the architecture.

 

The system controls a number of pumps and valves to create flow around a network of pipes.  There are flow meters in the network which are used as feedback for PID to maintain a flow.  The network of pipes is gradually opened up to get flow and then PID kicks in to maintain a flow.  The test sequence is pretty much a big state machine.  For example:

1.       Open valve 1

2.       Wait for pressure to build

3.       Ensure temperature is not over limit

4.       Etc

 

I will have a number of different screens which I want to load into a main sub-panel:

·         Main SCADA screen (show state of all valves pumps etc)

·         Test setup screen (configure tests)

·         I/O screen

·         Alarm screen

I will also have a number of I/O processes:

Inputs

·         Digital (valve sates)

·         Analogue (flow meters, temperature etc)

·         Modbus and serial devices (flow meters)

Outputs

·         Digital Output – Valves etc

·         Analogue  - Proportional valves

 

I want to use the Actor Framework because I’ve used it 3 times now and it is easy to spawn processes, make popups, inter-process messaging, error handling etc.  I can have all my processes separate (high cohesion) with separate user interfaces (if they have a UI) .

 

My problem is that AF and State machines don’t really go that well together (correct me if I’m wrong).

What happens when I want to do PID or loop in the same state?

Time delayed message?

A a VI for each state and enqueue the next or same state from within that VI?

 

Does anybody know a good way to incorporate a state machine into AF or should I chose a different way of doing things?

 

Any thoughts will be appreciated.

Cheer

Lewis

Share this post


Link to post
Share on other sites

You definitely do not want to have you PID timing based on time delayed send or AF messages in general. Remember, a message is guaranteed to get there, but it's not guaranteed to be handled in any time. So if you have a "Check PID" message, but the "Log data" message gets in there before it, the log data will happen first, then the "Check PID" will happen as soon as it can after the logging is done. This could introduce a lot of jitter.

 

Another design principal that you should follow when writing actors is that messages shouldn't take too long to execute. Obviously "long" is very subjective, but in general you shouldn't have a message for something like "Wait for pressure to build" since it probably takes a handful of seconds at minimum. This means that you Actor's thread is locked for that time. So you cant send it an abort message if needed, you cant stop the actor, etc.

 

The easiest way to do long running tasks or time dependent tasks using the AF is to have helper loops. To do this you override actor core, and drop another loop on the block diagram. Now you need to create some communication mechanism (regular old Qs, notifiers, etc) to communicate between the message handler Q (which is what the Parent's actor core is) and your new helper loop. You'll probably store a copy of this reference in your private data so Messages can communicate with your helper loop. You're probably already done something similar to this when writing UI Actors.

 

Your helper loops will probably look very similar to a traditional state machine. The only difference is this additional communication mechanism.

Share this post


Link to post
Share on other sites

Thanks for the reply!

 

If I was to have a wait for pressure to build, I would keep en-queuing the "Wait for pressure" message from within the message until it was up to pressure and then enqueue the next state.  I wouldn't have a blocking message.

 

I don't like the idea of parallel helper loops because you are basically re-creating the AF.  Why not just create a nested actor? I could create a state machine nested actor.  In the nested actor, when it is time to do PID, enqueue the PID message and the PID message can keep enqueueing itself until it is finsihed.  I don't really like this solution (hence my initial post) because it gets difficult if PID as enqueued a message to itself but the caller has sent a message to go idle.  The nested actor goes idle but there is still a PID message in the Queue.

Share this post


Link to post
Share on other sites

Helper loops are an essential part of any AF project. Helper loops do all of the heavy lifting of your actor, while messages are just the public interface for the actor. There are times when you can get away with just doing things in messages (like a file logger for example), but anything that's doing anything meaningful will probably need to happen in helper loops. The reason you don't create nested actors is because you need finer control of things like timing or execution order or whatever. With a  helper loop you can make sure that the Idle message stops any PID messages, or that the PID checking happens every X ms or whatever.

Share this post


Link to post
Share on other sites

My problem is that AF and State machines don’t really go that well together (correct me if I’m wrong).

.....

or should I chose a different way of doing things?

 

You have already answered your question. You know that it doesn't fit the task but perhaps not why. Look at what will be needed for system wide state control, sequencing and subsystem interaction. If they are required and must be deterministic; there are better, less painful solutions.

Share this post


Link to post
Share on other sites

You definitely do not want to have you PID timing based on time delayed send or AF messages in general. Remember, a message is guaranteed to get there, but it's not guaranteed to be handled in any time. So if you have a "Check PID" message, but the "Log data" message gets in there before it, the log data will happen first, then the "Check PID" will happen as soon as it can after the logging is done. This could introduce a lot of jitter.

 

Another line of reasoning would be to ask why you have PID and Logging in the same actor.  If a “PID actor†is only handling messages to do with PID control, then there may be advantages to keeping all actions serialized in one loop.  

BTW, Lewis, the AF group at NI.com is the best place to ask AF questions.  More people who use the AF extensively will be watching.

Share this post


Link to post
Share on other sites

BTW, Lewis, the AF group at NI.com is the best place to ask AF questions.  More people who use the AF extensively will be watching.

 

I don't frequent the NI groups nearly as much and enjoy having some of this discussion at LAVA.  

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.