I have a project where the program will run 4 independent test fixtures. It will read 4 sets of finger switches and run a test program for each of those fixtures.
At first, I considered a program with 4 while loops with each one running the same DAQmx digital read VI, looking for digital inputs specific to its fixture loop, and then proceed with testing when its finger switch is activated. But I'm wondering what the impact will be on 4 separate trying to read the same DAQmx-read VI.
Option 2 is to have a 5th loop only running the DAQmx-read VI and storing the data in a functional global variable (FGV). The other 4 loops would read from the FGV and act accordingly. But is this arrangement a potential race-condition?
Use the DAQmx Change Detection Event.
Basically you set up an event structure; the event structure fires when one of the lines changes, Hi to Lo, Lo to Hi, etc. You then figure out which line fired and fire a message to an appropriate loop which responds to the event.
Below is a simple mock-up. You need a while loop around the event structure, close the task, etc.
You can also look Digital - Change Detection VI in the Example Finder. It doesn't use an event structure, but will do what you need. I prefer the Event Structure approach.
Thank you, mcduff. Do you see this detection be in its own loop, or in the respective loop for each fixture?
Here's what I'm working with:
The resulting read is stored into the FGV. There are 3 digital lines needed to be read to start a test for a given fixture:
I've uploaded the files. Have I set myself up for a race condition?
One other question: since the "check finger switch and part-in-nest.vi" is being read by 4 separate loops, should it be non-reentrant or a shared clone?
I need to get ready for a meeting that I am supposed to lead, so sorry for the brief reply.
One Loop - Read Digital Inputs, then decide what to do
Other Loops - Get message(Queue, Notifier, Channel, User Event) from the Read Digital Inputs VI, do whatever they need to do.
USE THE ARRAY TO CLUSTER FUNCTION. Sorry for shouting.
Look at Producer Consumer type architectures. Depending on your Speed requirements, a single loop is also possible. JKI State Machine highly recommended.
2016 Version Attached of Snippet
I did not wire the rising/falling edge channels in the DAQmx Timing function. Wire all channels to both to look for both events, Hi to Lo, Lo to Hi. If you don't need both then just wire what you need. There should be a state machine in the while loop below, but if your logic is fast then maybe not. Play around with the attached VI and trip your lines to see if it works for you. Then add your other loops.
This isn't a question you asked, but here's a nifty little trick to reduce all that wire clutter in msg #3.
[Edit: after posting I see that mcduff also illustrated a more standard method to convert an array to a cluster. The main difference is that the standard method requires you to right-click and set the desired cluster size in order to get the right sized output. The trick I showed gets it right inherently. Even if you were to modify the # booleans in the typedef'ed cluster. Nothing would break. (Though a mismatch between array size and cluster size would result in either truncation or default False filler elements.)
This whole thing came up recently in a discussion with a colleague about mods to a reuse code template we use often. The template used the standard method, which meant that the code would usually start out broken because the # elements in our cluster typedef varies quite a bit from app to app. I hoped my "trick" would help to auto-adjust, but alas! It did not.
I think it might only work for simple native types like boolean, numeric, or string. Our cluster contains queue refs whose datatype is a class of our own making. Apparently, all that was too much for the Type Cast function to deal with and it broke the wires anyway.
But that's why the idea was fresh in mind and yours is a situation where it works. Granted, not terribly helpful here where your array and cluster sizes are both dictated by hardware and aren't really subject to change.]
Thanks, mcduff! I can't wait until Monday to try it out.
As for the array-to-cluster, I don't know what I was thinking. I had completely forgotten about that.
Years ago, I had used queue functions in a producer-consumer program and had elements lost during the program for some reason. I don't recall what the issue was. In any case, I've found FGV to handy to hold states without destroying them. I'll look back into a one-producer-to-many consumer operation.
Many, many thanks for your help,
Thanks, mcduff! I can't wait until Monday to try it out.
I'll look back into a one-producer-to-many consumer operation.
Queues really won't work in that scenario; they can with some hacks but not recommended. User Events or Channel Wires can have one to many without being lossy.
Once again, think of the time scale of your experiment. Parallel is always nice, but harder to program and debug.
What happens when a line changes state? Does it access a piece of hardware? If another line changes state during this time, will it try to access the same hardware as the other? If so, you probably cannot have real parallel operations.
PS @Kevin_Price's solution to your array to cluster problem is better than my recommendation. The type cast is easier to implement and if your type def changes there is no broken code.
Upon further research, I found that NI-9425 for our CDAQ chassis does not support change detection since it is software-timed. ARRGGG! This project has been nothing but a series of kick-in-crotches.