01-25-2019 04:44 AM
Hi All,
My Application:
I have two data acquisition devices. 1. A force sensor 2. output from an ESP32 microcontroller. Both are using visa commands for serial COM ports. And then, the data are plotted in a graph and also written to a text file. For a better sny. architecture, I used a Producer Consumer pattern. After many research in NI forum, I found out that the reason for not executing the consumer loops is that there are 2 dequeues. Then I commented those out to see and it works. I'd like to know from the experts, is there a way that I can resolve this issue. (I was thinking of using a FGV or a notifier also... But I'll wait for your expert answers..)
Thank you very much in advance. Attached is a .7z + vi
Best,
Shane
Solved! Go to Solution.
01-25-2019 05:58 AM - edited 01-25-2019 05:59 AM
Try to cleanup your block diagram first. Here may get solution, Try this.
01-25-2019 06:01 AM
Not only do you have one consumer consuming two queues, you have one queue being consumed in two consumers...
And a lot of messy wires, void space, uninitialized shift registers, etc.
01-25-2019 06:06 AM
Hi Shane,
big problem: you have one loop putting elements into the queue, but 2 loops dequeuing elements. This will not work (reliable) at all…
A queue is used to provide a "many producers, but just one consumer" scheme. You may use notifiers for a "one producer, many consumers" scheme…
(Or combine FileWrite and GraphDisplay in one loop to use only one consumer.)
01-25-2019 06:11 AM
Hi, Shane
next time, please, make simple example with your problem, we don't want search problems in big VI.
you've made some fundamental errors, see image.
1 you ignore data flow
2 you read from ONE Q in TWO loops
stages in your vi:
stage1:1+2 create Q.
stage2: Loop "3" works. Works Loop "3" and Loop "6". Because you've connect out shift register from loop 3 to in tunnels of loops 5+7. On this stage you "fill" both queues.
stage3: Q2 have destroyed.
stage3 (start at the same time as stage3): Loops 5+7 work. BUT. Q2 was killed at stage3. So, you will get errors every iteration. AND. You read Q1 in both loops. And nobody knows, which loop will get data. Every time when you dequeue element, it remover from queue, so, another reader will get next element.
01-25-2019 06:12 AM
Hi wiebe@CARYA
I understood the problem. I'm new to LabVIEW with a expertise in java. I thought if uninitialized, LabVIEW would automatically initialize them according to it's data type.
01-25-2019 06:17 AM - edited 01-25-2019 06:21 AM
Several more helpful replies came in after I started replying but before I finished. Some but not all my thoughts below have been covered. In particular, crossrulz did a nice job breaking down detailed issues. Anyway, my pre-edited post is below.
--------------------------------------------------------
2 key concepts:
1. Each queue should have only 1 consumer as wiebe already noted.
2. Both your sensor loops should "publish" to the same queue. Your main loop would consume from only this 1 queue. (It might then publish to a different queue that the logging loop consumes from.) Then the two sensor loops can run at different speeds and the main loop won't need to care.
To enable this, you might adopt the following approach as shown in the "Queued Message Handler" template. (It's the way I typically do stuff.) The datatype for the queue shared by main and sensor loops should be a cluster of String and Variant or else Enum and Variant. (As always be sure to typedef your cluster.) The String / Enum is used to identify what kind of data is contained in the Variant. So the main loop receives a "message" on this queue, unbundles the received cluster, enters a case structure based on the String / Enum, and inside the case structure it converts the Variant into the appropriate data.
Once you do this, you pretty much *are* running a Queued Message Handler, often abbreviated on the forums as QMH.
-Kevin P
01-25-2019 07:44 AM
@ShaneJ007 wrote:
Hi wiebe@CARYA
I understood the problem. I'm new to LabVIEW with a expertise in java. I thought if uninitialized, LabVIEW would automatically initialize them according to it's data type.
OT: Just to note that this feature (not initializing them by default) is a very useful one. It allows function global variables (aka. FGV, action engines, global buffers, etc.). The SR will retain it's data state over VI calls.
01-25-2019 08:21 AM
@GerdW wrote:
Hi Shane,
...
A queue is used to provide a "many producers, but just one consumer" scheme....
If seeing someone use a screwdriver as a chisel makes your skin crawl, the following spoiler you may just want to skip over.
Back in the early days of this forum Chillie Charly was running a "List" to track who was contributing to the forums, how many Stars etc. He and I teamed up to develop the code that skimmed the forum to get the required stats. This amounted to a datasocket read of each person's profile. Using a For loop to iterate through all of the contributors was slowed down by how long it took to complete the datasocket read. In order to speed up the data collection we implemented a "worker pool" of VIs that would work in parallel all doing data socket reads and the results were then pushed into a common queue to be analyzed. The results were delivered to the analysis code as you mentioned, "Many Producers, but a common consumer".
But on the other side we used a single queue that was populated with a list of all of the IDs that were needed to do the datasocket reads. All of the workers would look at the same queue and wait for an ID to become available. We did not care which worker got the info. All we needed was SOMEBODY do the work.
So it ended up being a "scatter the seeds to the wind" and wait for something to grow.
Ben
01-25-2019 09:55 AM
Thanks a lot guys for helping me to identify the problem in such a short amount time..