11-15-2007 08:26 PM
11-16-2007 09:40 AM
11-16-2007 11:06 AM
Unfortunately, getting rid of the ramping routine isn't an option for me. These are high-current drivers connected to laser diodes which put out a few hundred watts each. Slamming the current "on" can result in failure of the diode -- and they aren't exactly cheap. Like it or not, this is functionality I have to provide.
Besides, I really don't think the problem lies within the ramping routine itself, as it appears to work just fine. The problem appears to be that something resets the notifier before the data loop has a chance to register that it went "True"...but only under the specific circumstance I described. The code works under all other circumstances. Notifiers are intended to provide communication between VIs so I don't think I'm using them improperly here.
Thanks for the reply!
11-16-2007 11:45 AM
11-16-2007 12:30 PM
The notifier is only set inside the main VI. The subVI monitors it, but never actually writes to it.
A race condition is possible, of course, but heck if I can find it. Here is the sequence as it happens, maybe you can see it?
1. Current is ramping. Main VI is in the Set Current state. SubVI is executing.
2. User presses All Diodes Off button. "True" notification is sent. All Diodes Off state is queued.
3. SubVI receives "True" notifier. SubVI terminates.
4. Set Current state also receives "True" notifier. Set Current state sets notifier back to "False", then terminates.
5. All Diodes Off state is dequeued. All Diodes Off state executes. All Diodes Off state generates a user event. Nothing is written to the notifier, so it's still returning "False" -- as it should.
6. User event fires. Get Data state is queued. Nothing is written to the notifier.
7. Get Data state is entered and the DAQ loop starts. The loop monitors the notifier, but does not write to it.
8. Another front panel event is fired (i.e. the user has pressed a button). "True" notification is sent.
Now, what is supposed to happen at this point is, the Get Notifier Status VI receives a "True" value and terminates the loop. As I mentioned, this is indeed what happens in all other circumstances except this particular one.
As I understand it -- and maybe this is where the problem lies -- a notifier can only hold one piece of data at a time, and that data is not consumed when it is read. Therefore, if the event structure in the producer loop writes a "True" value to the notifier, that notifier will return a "True" value until something else writes a "False" value to the notifier. Is that right?
The producer loop ONLY writes "True" values to the notifier. Therefore, if another event were to fire right after the first one, the value written to the notifier would still be "True".
We are inside the DAQ loop, which does not write to the notifier. Therefore it can't be setting that notifier to "False".
We never exit the DAQ loop -- that's the problem here -- so we aren't entering any other state in the consumer loop which could conceivably set the notifier to "False".
I can look into making the notifier data a three-state value instead of a two-state value, but I would still dearly love it if someone can explain what's going on here. Obviously I'm missing something!
11-16-2007 12:38 PM - edited 11-16-2007 12:41 PM
11-16-2007 01:03 PM
Here is the code.
If I use "Cancel Notification" instead of writing a "False" value to the notifier, what does "Get Notifier Status" return? The default value of the data type (in this case, a "False" boolean)?
11-16-2007 01:59 PM
11-16-2007 06:17 PM
Well, I gave that a try (using the Wait on Notifier VI as opposed to the Get Notifier Status VI). Now the subroutine doesn't respond to the notifier. If I send the notifier while the subroutine is in the middle of its current ramp, it doesn't register. The subroutine finishes its ramp, then returns control to the main VI, which goes on to execute whichever state was queued up (in this case, All Drivers Off).
This may actually drive me crazy.
Good idea on the queue instead of control refs. That makes sense.
I am using continuous acquisition...I explicitly start the task, enter the loop, collect data, and then stop the task when the loop terminates. I had understood that it was better practice to explicitly start and stop tasks. I can't run the DAQ all the time, in a third loop, because one of the subroutines has to use those tasks to make sure the driver is doing what it's supposed to be doing.
Thanks a lot for your help...I take it by your referral to the "mystery race condition" that it wasn't immediately obvious to you either?
11-19-2007 09:42 AM