05-24-2019 01:52 PM
Good afternoon,
I'm working on a supervisory VI to PLC.
My main.vi consists of 5 principal subVIs: one OPC-DAQ and four workspaces (see Capture1.png).
All subVIs will be always running inside the main.vi
The menu buttons does the function of show/hide the front panel of its corresponding workspace subVI.
The workspace subVI gets data from the OPC-DAQ.vi through a queue (and notifiers, but my problem is with the queue).
Here's my problem: the OPC-DAQ subVI enqueues elements to a queue named "q_medições". And each workspace subVI have a dequeue element for "q_medições".
What I want is:
- When first Menu Button (Menu Button is a Radio Button control), only first workspace subvi will be dequeing elements from "q_medições"
- When 2nd menu button is on, only the 2nd workspace subvi will be dequeing elements from "q_medições"
- Same for 3rd and 4rd buttons
Please see a example of block diagram from a workspace subVI. These subVIs knows the current Menu Button from the "n_menuAberto" notifier
There's a way to temporary stops a listener listening a queue without releasing the queue?
What is the best way to "hold" the Dequeue Element function until the right Menu Button is pressed?
Solved! Go to Solution.
05-24-2019 02:45 PM
@mthheitor wrote:
There's a way to temporary stops a listener listening a queue without releasing the queue?
What is the best way to "hold" the Dequeue Element function until the right Menu Button is pressed?
There are two ways to block a Queue -- don't Enqueue, or don't Dequeue. I created a little test routine (I, at first, didn't think this was possible, but it worked ...), shown here using a Stream Channel Wire instead of a Queue (I'm something of a "nut" about Channel Wires).
Here's how it works:
I wrote this in LabVIEW 2018. I'm attaching it as a Snippet and as a VI. If you had attached your VI instead of a picture of your VI, I could have made sure you were running LabVIEW 2018 and could run this example -- oh, well.
DEMO Multi-Queue
Bob Schor
05-24-2019 02:49 PM
There are a few ways to do this. I think the simplest would be to just use multiple queues. Instead of the listeners trying to ignore messages, make the sender enqueue the messages to different places depending on where it needs to go. Another way is to use User Events, which can register and deregister for event notifications using Dynamic Event Registration. You'd still need another communication method to control the registration and deregistration though, as once you deregister for events you stop being able to send messages via said Event 🙂
Another way to do this would be a "message dispatcher", where there's an intermediate "listener" that can receive elements from your main queue and can send them on to separate queues.
Having your listeners stop listening means you have to repeat code in ALL listeners to get them to stop listening to the queue, whereas doing it from the sender means it only happens in one place. Having multiple items dequeue from the same queue is typically, but not always, bad practice. Multiple dequeuers are usually used when you have multiple worker functions trying to process data from the same source that can be recombined later, as each element only gets dequeued one time, no matter the number of listeners.
Contrast that with User Events, where you can call Register For Event in each listener. Each Registration will receive the Event when it's sent out, so ALL of your subVI's will see all messages. You could then include an "address" in the message to tell the Event Structures to only process events sent to them, and to ignore all others.
05-24-2019
05:02 PM
- last edited on
07-18-2024
03:08 PM
by
Content Cleaner
Sorry @Bob_Schor, these VI Snippet are something I always wanted to learn, but the pinned post in the forum doesn't do a lot to teach about snippets (https://forums.ni.com/t5/LabVIEW/Notice-Attach-VI-Snippets-to-post-rather-than-upload/td-p/3660471)
But this does: https://knowledge.ni.com/KnowledgeArticleDetails?id=kA03q000000x2PkCAI&l=en-US. Please pin this tutorial within the inside the pinned post of the Forum. Cause I always thought Snippet were something about the forum, not a LabVIEW feature.
(I know this sounds like non-smart, but I have friends that does not know about the snippets. The word "snippet" is something I've only see in LabVIEW, and it was a little confusing in my opinion. But now I know what is a snippet, thanks.)
I'm using LV2012 and could not run your code. Please, can you save in LV2012?
05-24-2019 05:34 PM
@BertMcMahan multiples queues sounds like wasting resources, because the data is always the same (measurements from sensors). The only thing that changes is what each workspace subVI do with the data. The 1st workspace (Home), for example, let the user freely interact and move with the LVDT, cylinder, hydraulic pumps and motors. The 2nd workspace (Testing) do a automatized test to a specimen...
And one of the sensors has a 5 MHz acquisition rate (during the standard test), imagine send this data through 4 different queues.
I'm using User events to do simple things like start and stop camera, send stop to some loops. I think implement the listen/stop-listen system with User Events would be too much complicated, at least for my current knowledge.
The message dispatcher have the same thing that I want to avoid: multiple queues for the same data.
I have only one producer in the queue (OPC-DAQ.vi), and only one consumer (workspace subVI). But the dequeue change its place according with the Menu Buttons of the main.vi.
I do not want multiple dequeue at the same time, only one dequeue will be active.
About the "address" it's a interesting idea. I'm thinking in use a "Preview Queue Element" before each "Dequeue Element", if I have elements in the queue, verify if the workspace subVI is the corresponding active (Menu Radio Button = workspace.vi) before dequeue each element of the "q_medições". Maybe this can work 🙂
Thank you for the tips.
05-24-2019 05:39 PM
You don't need to send data along all four queues- you select one of the four queues on which to send data. On other words, your sender chooses one queue and sends it to that queue and that queue alone.
The dispatcher doesn't send copies of the same data either, it just decides to forward some of the data along, taking the responsibility of deciding the "to" queue away from the VI generating the data. It only sends it along one of the queue wires, not all four.
05-24-2019 07:11 PM - edited 05-24-2019 07:16 PM
@mthheitor wrote:
About the "address" it's a interesting idea. I'm thinking in use a "Preview Queue Element" before each "Dequeue Element", if I have elements in the queue, verify if the workspace subVI is the corresponding active (Menu Radio Button = workspace.vi) before dequeue each element of the "q_medições". Maybe this can work 🙂
Don't do this - it's a recipe for race conditions! What happens if someone else dequeues from the queue during the time in between your "Preview Queue Element" and "Dequeue Element"? Then the element you get from the queue will not be the same as the one you previewed. Follow BertMcMahan's advice and use a separate queue for each or use a user event with an address.
05-25-2019 04:09 AM
hi,
Preview q will work , the receivers should de-Q after ensuring the information is meant to them.
05-25-2019 01:31 PM
@mthheitor wrote:
I'm using LV2012 and could not run your code. Please, can you save in LV2012?
I'll try. I'm "on the road" for a few days, but have my laptop, so I should be able to download my own code and see if I can Save for Previous ...
Bob Schor
05-26-2019 07:36 AM
@Bob_Schor wrote:
@mthheitor wrote:
I'm using LV2012 and could not run your code. Please, can you save in LV2012?
I'll try. I'm "on the road" for a few days, but have my laptop, so I should be able to download my own code and see if I can Save for Previous ...
Channels were not around in 2012, so you will have that issue.
I will also put my vote behind the multiple queues. It is a lot simpler for your message handlers. Ultimately, I say you should have a library for each message handler. In that library, you have an Action Engine for maintaining the queue that it receives data on that is set to be private (don't let outside functions mess with it, only the receiver of the queue data should maintain the queue) and have a public VI for sending messages through that queue. Then your main VI just has to decide which "Send Message" VI to call to get the data to the right place.