12-05-2011 08:47 AM
I am writing an extension to a DAQ written in Labview by a predecessor in my group. The extension consists of a new VI containing a bunch of code that tells the DAQ how to undertake several different types of Calibration. The existing DAQ loops at roughly 1.5Hz when it is given a trigger. To eliminate certain race conditions I need to lock the other calibration DAQ so that it loops just after the existing DAQ. I have currently done this using global variables to pass a Notifier between the existing DAQ and the calibration DAQ which waits for this notification before looping.
This worked fine but now I wish to compile both VI’s into executables. Obviously at this point I need to switch from using Global Variables to Shared Variables. Does anyone know a way of doing this as I can’t seem to pass a Notification Refnum via a shared Variable, or can anyone suggest an alternative method of doing such a task?
*I am using the latest version of Labview and have access to all packages and modules.
Solved! Go to Solution.
12-06-2011 01:39 PM - edited 12-06-2011 01:41 PM
@labviewusers wrote:
[...] wish to compile both VI’s into executables. Obviously at this point I need to switch from using Global Variables to Shared Variables. [...]
Edit deleted - I didn't realize you were talking about TWO seperate EXE's.
@labviewusers wrote:
*I am using the latest version of Labview and have access to all packages and modules.
Your LabVIEW splash screen must be well decorated!
12-06-2011 02:04 PM
Another approach which is a bit more event driven is to use a network queue. While this code is not 100% in terms of error processing it is a fairly reliable solution when working on the same machine.
12-06-2011 02:59 PM
Ye to put this into context:
This DAQ runs concurrently twice in two separate Exe's controlling two custom designed boards which run an experimental real time fast feedback position correction system for a particle accelerator. There is also a separate executable which runs a code which controls a mover system for the apparatus which measures the beam inside the accelerator and another which runs a system used to control the phase of some input signals.
Although these systems are complex they are more traditionally what I understand labview to be used for, passing information from a serial connection into data files and setting firmware on the boards.
The calibration Exe (a new idea and very much a work in progress) then sits on top of these other exes and implements a suite of control and calibration algorithms (written in C++ and Python) designed to perform various tasks. The problem I am having is a bunch of race conditions. We could of coarse implement all these systems into one large Exe, this however puts us into a situation where if one thing crashed (and if you know anything about experimental physics this isn’t infrequent) everything fails. It also means that changing one part and in particular the control algorithms could cause everything to fail, something highly undesirable as beam time is precious and at the very least you want your DAQ to always work.
Originally all this code was “linked together” using Global Variables and although there were some race conditions these were all carefully ironed out. When the decision was made to compile the individual VI’s into separate executables we ran into problems which I’ve been unable to fix. I’ve had a number of ideas, thinking maybe I could use the realtime module for example but this seems to be designed more for controlling discrete systems on different machines rather than many systems on the same machine.
The main problem I have as I say is to lock the loop between the DAQ and the calibration VI together. Every time a bunch travels through the accelerator (about 1.5Hz) the DAQ triggers. I have set up the system so that the DAQ then processes the data and afterwards passes the settings it has used (how many tiggers it has saved to a file for example) to the calibration VI along with a notification. This is setup to wait for this notification and when it receives it looks at the information given and makes decisions based on this information about what the DAQ or other VIs should the do (ie stop saving data, move the movers and then start saving data again with a different filename).
The problem seems to occur because as I can’t work out how to send a notification I can’t make the DAQ and the calibration VI lock together. This means they end up in a situation where both will be reading and writing to the same variables at the same time which obviously means the whole thing gets screwed up.
I get the impression that this system isn’t strictly what labview was designed to do and I may just be pushing it to it’s limits. I also realise however that I come from perhaps a more traditional programming background (Java, C++ etc) and I’m new to it and don’t understand it’s full scope so if anyone could offer me a way of doing this or a better way to structure the system as a whole I would be very grateful.
Thanks.
12-06-2011 11:54 PM
First, LabVIEW is more than capable to handle this application. Your preconceptions of LabVIEW are not accurate. What you lack is a solid understanding of program architectures and system design. I don't mean that to be an insult or to belittle you but simply to say you currently lack the background to envision the system. I have developed systems in LabVIEW that are considerably larger and more complex than what you described.
I suggested using networks queues which would help to control your system and keep things synchronized. Each of your tasks could wait on a queue for a command/data. While waiting it will not access your shared resources. Your independent tasks can message one another when it is appropriate to operate. Using global or shared variables would mean that your system is polling and there is no coordination. This as you have learned leads to race conditions.
If you truly don't want to use queues you should consider using a semaphore. One method would be to have a shared file which would be locked by a task when it is using a shared resource. Only one task/application can obtain a lock on a the file and the other applications would have to wait until the file is unlocked. While this is not ideal it is a workable solution to your problem. One problem you can run into is if one application locks the files and then it crashes. However proper testing of your applications should minimize crashing. If you are experiencing lots of crashes you need to find and fix some bugs. While not perfect LabVIEW is a stable system and crashes are a result of a bug in your application.
Yet another method which was suggested earlier would be to use a TCP messaging system. Much like the queues your system would only take action when a message was received. If there is no messages you simply wait for one to arrive. Again, this synchronizes your tasks to prevent them from acting on your shared resource at the same time.
On nice thing about LabVIEW is that it is very easy to create parallel tasks. So even if you separate some of your tasks into separate applications portions of those applications can continue to execute at the same time provided they are not accessing your shared resource. A separate parallel task in the application could be waiting on a message or a semaphore using one of the above suggestions.
12-07-2011 08:06 AM
@labviewusers wrote:
The problem seems to occur because as I can’t work out how to send a notification I can’t make the DAQ and the calibration VI lock together. This means they end up in a situation where both will be reading and writing to the same variables at the same time which obviously means the whole thing gets screwed up.
I get the impression that this system isn’t strictly what labview was designed to do and I may just be pushing it to it’s limits. I also realise however that I come from perhaps a more traditional programming background (Java, C++ etc) and I’m new to it and don’t understand it’s full scope so if anyone could offer me a way of doing this or a better way to structure the system as a whole I would be very grateful.
My first LabVIEW project was at a nuclear physics accelerator. Back in 1999 or there abouts. I adapted the TCP client/server example of the time to send information between processes (didn't actually understand how TCP worked, just hacked the example). Don't worry, your not pushing LabVIEW limits just yet. Your big problem seems to be race conditions caused by having multiple parallel processes as writers to the same by-reference variable. Those race conditions were "carefully ironed out" with duct tape, but the duct tape didn't hold when you upped the stress on the system. The most effective solution is to not have any variable that is written to by more than one process. Each Shared Variable should have only one writer; if this means increasing the number of Shared Variables, that's fine. Personally, I use TCP messaging like Mark suggests, but I suspect it would be easier to adapt your system to Shared Variables. Just have separate variables for each communication direction.
-- James
12-11-2011 05:16 AM
Network variables did the job perfectly, enough control for what I was trying to do.
Thanks.
M