Jump to content

jki state machine producer consumer loop


hburd

Recommended Posts

Hi

 

Has anyone adapted the jki state machine into the producer-consumer loop design with queues and event structures? Could you share examples?

 

thanks

 

Hi!

 

Yes, we do this at JKI, in a variety of ways. You can put a Read Queue function in the timeout frame or you can use Dynamic User Events. This opens up a pretty big discussion -- to get things rolling I'll post an example that uses Dynamic Registration of User Events.

 

Producer_Consumer_JKI_State_Machine__LV82_.vi (LabVIEW 8.2)

 

Front Panel

1.png

 

Block Diagram

0.png

 

Key things you should note:

  • The "Events: Register" and "Events: Unregister" frames are called by "Macro: Init" and "Macro: Exit" to handle the dynamic registration.
  • The event registration reference routed above the Event Structure is important. There are some LabVIEW type-propagation bugs caused when you wire out of the right-side Dynamic Event Terminal to the Case Structure tunnel.
  • The event data type(s) will propagate all the way to the Event Structure.
  • You can resize the Register for Events function in the "Events: Register" frame for adding other user events.
  • You can have multiple consumers (you can have multiple JKI State Machine's register for the same user event) -- this makes it a true publish-subscribe architecture.
  • Note that user events get queued and there is no way to preview or flush the queue (since NI did not intend for them to be used for pub-sub architectures, even though it's so natural...). This can cause big performance problems if your producers generate too many events (especially of large data) and your consumer loop does not iterate fast enough (calling the event structure to process the events).
  • You can wire clusters and arrays into the Register for Events function, in order to group events by name (with a cluster of user events) or have a single frame handle events from multiple sources (with an array of user events).
  • Watch out for the bug where Event Structure frames can incorrectly remap to other dynamic events

I'll post more noteable stuff, if I recall it. Also, if anyone else has comments, ideas, or knows of other things to watch out for, please feel free to join in on the discussion.

 

Cheers,

Link to comment
Share on other sites

Sure -- I've updated the example VI (re-saved in LabVIEW 8.2).

Thanks, Jim.

 

I'm thinking that User Events are the way I should handle things that I dynamically launch and let run in the background. I had used Queues & Notifiers for this but that requires me to poll for the event. I've written the program for one ATE this way. Is this an appropriate use of User Events?

 

You said in your first post that this "opens up a pretty big discussion". It should be very interesting; I hope it takes off.

 

Jim

Link to comment
Share on other sites

Hi!

 

Thanks for sharing the example for the JKI state machine applied to the producer consumer loop, it was very useful.

 

However, I am not sure what is the best way to share data between the producer-consumer loop. I can send the Message from the producer to the consumer, but, for example, if I need to send together with the Message another data, for example, a Boolean (to be processed in the consumer loop), what is the best way to do it? Should I use a variant (cluster of string-message and Boolean-data) as the user event data type in the producer loop, or there is a better way?

 

 

thanks

 

Helcio

Link to comment
Share on other sites

Hi,

 

I have a question about initialization. What if you need to initialize something for the producer loop to run and it would make sense to do the initialization in the state machine loop? Is there a good way to do that and then signal the producer loop to start?

 

Cindy

Link to comment
Share on other sites

However, I am not sure what is the best way to share data between the producer-consumer loop. I can send the Message from the producer to the consumer, but, for example, if I need to send together with the Message another data, for example, a Boolean (to be processed in the consumer loop), what is the best way to do it? Should I use a variant (cluster of string-message and Boolean-data) as the user event data type in the producer loop, or there is a better way?

 

Hi Helcio,

 

First, I would create separate user events for every event type. If you need to pass generic data with specific events, consider using LVOOP objects as the generic data, with child classes for decoding specific data. You can group your user events in a cluster, before passing them into the Register for Events. I'll try to post an example of this, soon.

 

Second, I like to make my event data a cluster and pass all relevant data in the cluster. Examples of this extra data are timestamp, additional data, etc. I tend not to pass "generic" string/variant data that has to be decoded programmatically. Again, I typically user LVOOP objects when I have to pass generic data.

 

-Jim

Link to comment
Share on other sites

I have a question about initialization. What if you need to initialize something for the producer loop to run and it would make sense to do the initialization in the state machine loop? Is there a good way to do that and then signal the producer loop to start?

 

Hi Cindy,

 

You might consider using a Rendezvous -- have the Producer wait on a Rendezvous (of size 2) that the consumer (state machine) will wait on (therefore causing producer and the consumer to stop waiting).

 

I'll try to post an example of how to do this, soon (since, I've got to go to a meeting, right now).

 

-Jim

Link to comment
Share on other sites

Hi Jim,

 

I tried to do what you have said for the producer consumer loop with events and data for the JKI state machine. I created a cluster with user all user events I needed and worked from there. I am sending the project file attached for labview version 2009 (could not be saved in Labview version 8.2 because it generates an error). I hope that this is what you had in mind.

 

However, I have no clue how I could use LVOOP to avoid having to convert variant, therefore you will see conversions all over the code:

post-2790-1256858174.jpg

post-2790-1256858474_thumb.jpg

 

 

 

regards

 

Helcio

 

Hi Helcio,

 

First, I would create separate user events for every event type. If you need to pass generic data with specific events, consider using LVOOP objects as the generic data, with child classes for decoding specific data. You can group your user events in a cluster, before passing them into the Register for Events. I'll try to post an example of this, soon.

 

Second, I like to make my event data a cluster and pass all relevant data in the cluster. Examples of this extra data are timestamp, additional data, etc. I tend not to pass "generic" string/variant data that has to be decoded programmatically. Again, I typically user LVOOP objects when I have to pass generic data.

 

-Jim

jki_producer_consumer_loop_with_events_and_data_lv_2009.zip

Link to comment
Share on other sites

I tried to do what you have said for the producer consumer loop with events and data for the JKI state machine. I created a cluster with user all user events I needed and worked from there. I am sending the project file attached for labview version 2009 (could not be saved in Labview version 8.2 because it generates an error). I hope that this is what you had in mind.

 

Helcio,

 

You did pretty good :wacko:

 

Here is a new version with some changes:

 

jki_producer_consumer_loop_with_events_and_data_lv_2009.zip

You'll notice several things:

 

Every different event now has a type definition

Will definitely save you a LOT of time, if the event data ever changes.

 

The cluster of user events is now a type definition

Could save you a LOT of time, when the number of events ever changes.

 

I renamed "jki create and register events.vi" to "jki create events.vi"

"Creating" and "Registering" events should be separated, because we might have multiple consumer loops that register (subscribe) to the events.

 

1.png

 

I renamed the event cluster output of "jki create events.vi" to "My User Events"Since this is the name that shows up in the event structure, we want it to be readable ("user events out" doesn't really apply well).

 

0.png

 

Don't use variant data + string message for events with well-defined data type

Using variants takes too much work. Since you have multiple events, make each events data type different.

 

2.png

 

There are still a few more improvements that I would probably make, that move it into a more object-/component-oriented" design. I'll make another follow-up post, soon, with some of these improvements.

 

Regarding LVOOP...

However, I have no clue how I could use LVOOP to avoid having to convert variant, therefore you will see conversions all over the code:

Sorry about that. LVOOP is a pretty advanced topic. In case you're interested, what I meant was: you can create a parent class called "Event.lvclass" and then create child classes for specific event types. Each child class can implement a dynamic method called "Handle Event.vi". Inside the event structure, when the event happens, you can call "Event.lvclass:Handle Event.vi". This will then dynamically dispatch to the child implementation, based on the type of the event object.

Link to comment
Share on other sites

  • 1 month later...
  • 1 month later...

Hi again,

 

The jki state machine producer consumer loop is working nicely using it in the way described by you. I was wondering what would be the best way to use the jki state machine producer consumer loop to intercommunicate with other jki state machines Producer consumer loops (JKI SM PC loop) in the same project, but not in the same vi.

 

For example, suppose I have 1 JKI SM PC loop that continuously acquire data from the serial port. What would be the best way to transfer the data from this jki sm pc loop to another jki sm pc loop in another vi which will plot the serial data acquired? Or alternatively, in the example given above (jki_producer_consumer_loop_with_events_and_data_lv_2009.zip), what if another vi sends a command for this jki state machine PC loop execute the command for displaying a certain message on the screen?

 

Would the answer be to use notifiers? I mean, if I put a "wait on notification" in the timeout event structure of the jki sm pc loop that will execute the commands and a "send notofication" in the jki state machine PC loop that sends the commands?

 

thanks

 

Helcio

Link to comment
Share on other sites

The jki state machine producer consumer loop is working nicely using it in the way described by you. I was wondering what would be the best way to use the jki state machine producer consumer loop to intercommunicate with other jki state machines Producer consumer loops (JKI SM PC loop) in the same project, but not in the same vi.

 

Hi Helcio,

 

The way that we tend to do this at JKI is to use GOOP-style objects/components. A component has a process that is a JKI state machine. Each component has a method called "Get Public Events" that outputs a cluster of its public events. Components can then easily register for the events of other components inside their own JKI State Machine process loops.

 

We also usually have a "Get Private Events" method that can be used by the component for sending messages/commands into its own process. This gets very tricky in a hurry, especially when you need to get data back from the process after it is finished handling the message/command. This can be achieved in a variety of ways.

 

Does that sort of answer your question?

 

Thanks,

Link to comment
Share on other sites

Hi Jim,

 

Thanks for the information. I guess I really have to start learning GOOP, it will be very useful.

 

thanks again!

 

 

Helcio

 

Hi Helcio,

 

The way that we tend to do this at JKI is to use GOOP-style objects/components. A component has a process that is a JKI state machine. Each component has a method called "Get Public Events" that outputs a cluster of its public events. Components can then easily register for the events of other components inside their own JKI State Machine process loops.

 

We also usually have a "Get Private Events" method that can be used by the component for sending messages/commands into its own process. This gets very tricky in a hurry, especially when you need to get data back from the process after it is finished handling the message/command. This can be achieved in a variety of ways.

 

Does that sort of answer your question?

 

Thanks,

Link to comment
Share on other sites

Hi Jim,

 

Thanks for the information. I guess I really have to start learning GOOP, it will be very useful.

 

thanks again!

Helcio

 

Hi Helcio,

 

You're very welcome. Yes, I think you're probably at a point where you would benefit from learning about OOP. A great place to start, even if I do say so myself, is the appendix on OOP techniques in LabVIEW for Everyone. I talk about the history of by reference OOP implementations in LabVIEW and talk a little bit about the principles of OOP.

 

Cheers!

Link to comment
Share on other sites

  • 4 months later...

Hi Jim,

 

I read the GOOP chapter indicated by you in the book. Also I am trying to learn more OOP, but still I continue without a clue in how to implement the JKI producer loop to share data with other JKI producer consumer loops. Could you post an example of that when you have time?

 

Also, there will be a presentation section in the NIWEEK 2010 dedicated to the comparison between the JKI state machine and the other types of state machine. Could you post the presentation on this website for those, like me, who won't attend the NIWEEK?

 

Thanks

 

Helcio

 

 

 

Hi Helcio,

 

You're very welcome. Yes, I think you're probably at a point where you would benefit from learning about OOP. A great place to start, even if I do say so myself, is the appendix on OOP techniques in LabVIEW for Everyone. I talk about the history of by reference OOP implementations in LabVIEW and talk a little bit about the principles of OOP.

 

Cheers!

Link to comment
Share on other sites

Hi Jim,

 

I read the GOOP chapter indicated by you in the book. Also I am trying to learn more OOP, but still I continue without a clue in how to implement the JKI producer loop to share data with other JKI producer consumer loops. Could you post an example of that when you have time?

 

Also, there will be a presentation section in the NIWEEK 2010 dedicated to the comparison between the JKI state machine and the other types of state machine. Could you post the presentation on this website for those, like me, who won't attend the NIWEEK?

 

Thanks

 

Helcio

 

Hi Helcio,

 

Please post/send us a reminder after NIWeek and we'll post links to the NIWeek presentations. This should include a lot of good stuff, including info about sharing data between JKI State Machine loops.

 

Stay tuned!

 

Thanks,

 

-Jim

Link to comment
Share on other sites

  • 1 month later...

Hi Jim!

 

The Ni week should be over tomorrow, so could you, please, post the link for the ni week presentations? Please could you also post the VIs in the presentation JKI STATE MACHINE VERSUS NI STATE MACHINE so that everybody can be able to download and follow the presentation?

 

thanks very much

 

Helcio

Link to comment
Share on other sites

  • 2 weeks later...
Hi Jim!

 

The Ni week should be over tomorrow, so could you, please, post the link for the ni week presentations? Please could you also post the VIs in the presentation JKI STATE MACHINE VERSUS NI STATE MACHINE so that everybody can be able to download and follow the presentation?

 

thanks very much

 

Helcio

 

Hi Helcio,

 

Sorry for the delay. NIWeek is a hectic time :)

 

We have just posted our presentation slides in a new blog post: NIWeek 2010 Recap and Technical Session Slides.

 

Thanks,

Link to comment
Share on other sites

  • 9 months later...

Hello all,

 

Finally there are better clues of how to use JKI state machine for exchanging data with others jki state machines (Thanks Justin!): Here is the link of the template library for that Justin Goeres created for his presentation at CLA summit 2011 Template jki intercommunication with other jki state machines

 

post-2790-0-34717300-1306614560_thumb.png

 

However, as Justin Goeres mentioned in the CLA summit 2011 (VI SHOTS PODCAST), there is a problem when using his template if you need the timeout case in the event structure. Attached there is an example in labview 2010 (a little modification of what Justin Goeres' example) to try to make this problem clearer: Whenever a registered event is fired, Labview will reset the timeout event structure in the event structure where this event is registered if there is 1 or more registered events with no case to handle them in this event structure. There is a huge discussion if this is a bug or not (Lava link). But, as you can see in the template, Justin registers an entire cluster of user events all at once independently of them having a case to handle them in the event structure. This makes very practical and more maintainable code, but at the cost of having huge headache if you need the timeout case in the event structure. Hopefully NI will come up with some solution for this in the next version of labview.

 

I am still trying to figure out how to use it. I am really very, very tired of using queues to make the JKIs state machines to intercommunicate. Please, if someone has an example of use for it, please share it.

 

thanks

 

Helcio

 

 

 

 

Hi Helcio,

 

Sorry for the delay. NIWeek is a hectic time :)

 

We have just posted our presentation slides in a new blog post: NIWeek 2010 Recap and Technical Session Slides.

 

Thanks,

Event Structure Timeout Bug 2.vi

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

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