Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

cDAQ Operation Complete

Solved!
Go to solution

Is there any way to find out when a cDAQ operation is complete?  More specifically I would like to be able to find out if a resource is available.  The postings that I have found so far suggest not, but I thought I'd ask.

 

I have an application that is composed of two loops.  One is around an event structure which handles the GUI inputs, and in the timeout frame I handle periodic system health checks (operating temp, pressure etc.).  The other loop contains the main application.  In the main application, all of the I/O is done sequentially so there is never more than one cDAQ operation from it at any given time.  The same is also for the I/O in the event structure.  Where I can (and do) get resource conflicts is when the two loops act simultaneously.

 

I was hoping that this (Error -50103 The Specified Resource is Reserved) would not bite me since I am using a 9178 chassis.  Having enough timing engines apparently doesn't help if two processes are simultaneously trying to talk to the same module and/or line.  I am currently using a boolean as a sort of "lock out - tag out" but would like to implement something a bit neater.  Is it possible to test for the availability of a resource before trying to access it?

 

Jim

Jim

LV 2020
0 Kudos
Message 1 of 4
(3,169 Views)
Solution
Accepted by topic author lmtis

The best I was able to find is the DAQmx property node Task Done (DAQmx Task Property Node»Task Done).  You could do something with reading this property node and using that to trigger a case structure in your top loop.  This isn't going to be as elegant as I think you would like, there unfortunately does not seem to be a way to just check a resource and see if it is available.

 

You could use the 50103 error as a check to see if the resource is free and just clear out the error and try again if it is thrown.  It'd be a very hacked together way of checking to see if the resource is free.

Doug Farrell
Solutions Marketing - Automotive
National Instruments

National Instruments Automotive Solutions
Message 2 of 4
(3,147 Views)

Hi Jim,

 

Here's another way to look at it.

 

What if DAQmx had a function that did what you are asking for? Let's call this hypothetical function DAQmx Is Resource Available.vi, and say that it returns a Boolean indicating whether the specified resource is available to be reserved. There's a major problem with this interface: it asks a question, but the answer is wrong by the time that it finishes asking.

 

How could this fail? A race condition like this could happen:

  1. Thread A: Starts to call DAQmx Is Resource Available.vi.
  2. Thread A: DAQmx looks up whether the resource is reserved. No, it's not reserved, so DAQmx gets ready to return true (available).
  3. Thread A's time slice expires, and thread B is ready to run, so the operating system pre-empts thread A and starts running thread B instead.
  4. Thread B: Calls DAQmx Create Channel.vi, then DAQmx Start Task.vi, reserving the resource.
  5. Thread B's time slice expires, so the OS pre-empts B and starts running A again.
  6. Thread A: DAQmx Is Resource Available.vi returns true: the resource is available.
  7. Thread A: Calls DAQmx Create Channel.vi, then DAQmx Start Task.vi, but gets an error. The resource is not available anymore, because thread B reserved it.

 

The only way that DAQmx could reliably tell you whether a resource is reserved is by preventing other threads from reserving it, otherwise the answer is wrong by the time you finish asking the question. And DAQmx already provides three ways to do that: you can call DAQmx Control Task.vi, with action set to "reserve" or "commit", or you can call DAQmx Start Task.vi. "Reserve" reserves the resources. "Commit" reserves the resources and programs the hardware. "Start" reserves the resources, programs the hardware, and starts the task running.

 

If you don't want to have DAQmx actually reserve the resources, you need to keep track of the resource sharing yourself. And a global Boolean isn't going to work, because that won't prevent race conditions like the one I described. You would need to use a synchronization object like a semaphore, critical section, or mutex to control access to the resources.

 

LabVIEW has several mechanisms that could be used to do this. You could use a single-element queue: at the beginning of your program, insert an element representing the resource; when you want to use the resource, dequeue it; when you're done using the resource, enqueue it again. You could use a functional global (a subVI containing an uninitialized shift register) to mark the resource as "in use" or "not in use". You could also use a semaphore. There are probably many other ways I haven't thought of.

 

Brad

Message Edited by Brad K on 01-22-2010 12:29 PM
---
Brad Keryan
NI R&D
Message 3 of 4
(3,134 Views)

Brad and Doug,

 

Thank you both for your replies.  As you said Brad, my current solution is not satisfactory because of possible race conditions.  Because of the slow speed at which this application operates, I got around that with a pause after "grabbing" the boolean that is long enough to allow any existing users of the resource time to complete the task.  Either Doug's idea to check for the exact error code or your idea with the queue wuold work perfectly, and I could kick myself for not thinking of either one.  I think I am going to try your idea of using the semaphore just because I have never used them before.  I wish that I could have checked both of your answers as being the solution, because they both are.

 

Thank you for your time and assistance.

 

Jim

Message Edited by lmtis on 01-22-2010 01:35 PM
Jim

LV 2020
0 Kudos
Message 4 of 4
(3,120 Views)