Counter/Timer

cancel
Showing results for 
Search instead for 
Did you mean: 

Single TTL frequency output with fast update

While using a 6036E's counter to send a TTL frequency to a stepper motor driver, I constantly have to navigate around the minimum frequency I can use while updating the frequency frequently, see the following posts:
The application uses a control loop to determine what output to send to a stepper motor driver.
I also have to be careful not to start any other programs or anything else, because (I think) windows will delay updating the pulse frequency while labview's 'wait until next multiple' timer tries to make up for the lost time and tries to execute the next timer update while the previous (late) one is still active.
 
The linked posts make me believe it isn't possible to circumvent the error with our current hardware and/or software.
 
What hardware and software would solve the problem? It seems all new hardware would have to do is convert a voltage (which the 6036E can update fast enough) into a pulse train.
Are LabVIEW real time drivers for this card different in the sense that the counter is updated in a different way, so that it would avoid the first error (cannot update pulse before a full cycle has been completed)? I suppose the second error (busy doing something else) would not be an issue with a real time os.
0 Kudos
Message 1 of 8
(6,652 Views)
1. If switching over to LabVIEW RT were going to help, it wouldn't be due to functionality differences in the driver.  It would be due to the lack of jitter in your control loop rate.
 
2. There are several approaches that would let you experiment in your regular OS.
 
A.   Way back I was in a thread where I made an example for linearly ramping a stepper frequency while avoiding the error you describe.  The essence of it was to use a Timed Loop, and to assign the pulse train output as a "Timing Source" for that timed loop.  The loop iterations are thereby driven by the hardware, and you can make sure the next loop iteration won't happen until you've generated at least one pulse with the freq you just specified.   Here's the thread.
 
B.    A purely software solution would be feasible too.  The key is to decouple the calculate & control loop from the data acq update loop.  Go ahead and acquire data and calculate a desired output rate as fast as you'd like.  Each time you calc a desired freq, write it to some sort of lossy "global" such as a functional global or a Notifer.  Your data acq update loop however will need to be smarter.  It'll need to decide when it's ok for the hardware to actually update.  When it is, it will query the most recent "global" freq value and update it.
   There's a DAQmx Channel property buried deep, deep down that you can query to find out if it's ok to update.  Here's where to find it:
 
C.  Better yet, combine A & B. 
 
-Kevin P.
 

Message Edited by Kevin Price on 12-21-2006 03:49 PM

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 2 of 8
(6,640 Views)
First of all, thanks for the excellent answer Kevin.
 
1. I assumed the RT OS might use drivers with different specifications, so the same limitations would not apply, thanks for clearing that up. Also, by reading the thread you had linked, I have learned that the error actually is the result of the way the hardware works, it's not really a driver limitation.
 
2.
A. We have tried out both of your suggestions. The timed loop turned out to work well, but the solution was a bit too complicated: we had a bit of a challenge on how to stop and restart the timer (we want to be able to stop the stepper motor).
 
B. The 'ready for new value' property node works very well. We have combined this solution with solution 2A, then went for 2B only since it solves the whole problem.
 
See the attached picture for part of the code we use now.
 
Thanks for the help,
Floris
0 Kudos
Message 3 of 8
(6,507 Views)

Glad it helped!  Just thought I'd add one more little tidbit as an FYI.

In the code snapshot you posted, the frequency is updated by writing to a DAQmx Write Property node.  Once upon a time in a thread, one of the guys from NI said or implied that it should be slightly more efficient / fast to change frequency using the regular DAQmx Write.vi rather than with a property node.

The other possible issue with writing to a property node is that the two pulse parameters are not treated equivalently (unless this has changed in a more recent version of DAQmx).  One is "active" and the other is "passive."  Fortunately for you, the freq property is "active," and will cause the hardware freq to update while re-using the old value for duty cycle.  However, the duty cycle property is "passive."  Writing the duty cycle value alone will just store it there, and the hardware pulse train won't update until a freq value is written.  So people generating PWM control must always write the same constant freq value in order to "activate" the new duty cycle value.  I *think* this same principle applies to pulse trains defined in terms of high and low times/ticks, though I'm not sure which of the two parameters is the active one and which is the passive one.

Most if not all of this stuff becomes a non-issue if you update freq using DAQmx Write.vi.  I'm not at a LabVIEW PC to test right now, so I'm not sure if you can call DAQmx Write.vi without wiring both freq and duty cycle (or both high and low times/ticks).  If you *can*, I'm not sure what it uses as a default for the unwired input.  I would *hope* an unwired input would mean "retain prior value."

-Kevin P.

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 4 of 8
(6,492 Views)

In the code snapshot you posted, the frequency is updated by writing to a DAQmx Write Property node.  Once upon a time in a thread, one of the guys from NI said or implied that it should be slightly more efficient / fast to change frequency using the regular DAQmx Write.vi rather than with a property node.

I suppose I have always wondered if there is an actual difference between different ways of programming, like with property nodes and write vi's. Appearently there is 🙂

The other possible issue with writing to a property node is that the two pulse parameters are not treated equivalently (unless this has changed in a more recent version of DAQmx).  One is "active" and the other is "passive."  Fortunately for you, the freq property is "active," and will cause the hardware freq to update while re-using the old value for duty cycle.  However, the duty cycle property is "passive."  Writing the duty cycle value alone will just store it there, and the hardware pulse train won't update until a freq value is written.  So people generating PWM control must always write the same constant freq value in order to "activate" the new duty cycle value.  I *think* this same principle applies to pulse trains defined in terms of high and low times/ticks, though I'm not sure which of the two parameters is the active one and which is the passive one.

The stepper motor driver we use doesn't really care about duty cycle, so it's just at it's default of 0.5. Before we used the frequency property node, we used a double node to write both the high and low time. It seemed to work in the same way the frequency property node does.

Most if not all of this stuff becomes a non-issue if you update freq using DAQmx Write.vi.  I'm not at a LabVIEW PC to test right now, so I'm not sure if you can call DAQmx Write.vi without wiring both freq and duty cycle (or both high and low times/ticks).  If you *can*, I'm not sure what it uses as a default for the unwired input.  I would *hope* an unwired input would mean "retain prior value."

Duty cycle is a required input of write in counter 'single channel single sample' mode. I have replaced the frequency property node with a write vi. I don't notice any difference, but since it should be slightly more efficient I will keep it this way. See the attached, but not inline showing, screenshot.

0 Kudos
Message 5 of 8
(6,482 Views)
The new solution works great, but sometimes (a few times a day) the property note gets 'stuck' and never outputs a 'true' anymore. I have to restart the main vi to get it working again. I have created an error as a workaround of this event.
 
Do you perhaps have any idea what can cause this property node to stop responding?
 
Edit: we sometimes stop the stepper motor by idleing the counter, see the init code. Might this cause the property node to stop working?

Message Edited by Floris. on 01-11-2007 04:58 PM

Download All
0 Kudos
Message 6 of 8
(6,452 Views)

Hmmm, that's a new one on me.  How exactly have you determined that the property node gets stuck?  And when you say "stuck", you mean that the value remains stuck at False while the loop keeps on running, right?

The following is just speculation, but what the heck -- let's play detective, eh?

The problem happens pretty rarely, but chronically.  That leads me to suspect something a bit random, something with a low probability of happening at any instant, but nearly inevitable when you run your loop hundreds of times per second.

That in turn makes me think, "race condition."  I get suspicious of the way you're "idling the counter" using a hardware pause trigger.  That hardware pause trigger is either controlled by a different part of the code or by an external signal.  Either way, the timing of the Pause / Unpause transitions are not sync'ed to this loop. 

Let's suppose on iteration i that all the right conditions are met and you do make the call to DAQmx Write to update the pulse freq.  However, before the pulse-in-progress is completed, let's suppose that the pause trigger transitions to the pause state.  Now on iteration i+1 the property node will be False because the counter hasn't generated a cycle with the new frequency yet.  And it will keep on staying False as long as the pulse train is paused.

And, uh, well, now I'm stuck again because I don't see why it wouldn't get back to normal operation when you Unpause the pulse train.  Are you sure that the code running the pause trigger signal isn't somehow stuck?

Finally an idea for a workaround.  Unless your pause trigger needs to be hardware-timed, you could choose not to use one at all.  You can call DAQmx Stop to stop the pulse train and then DAQmx Start to re-start it.  Stops and Starts aren't too terribly slow -- it's the Clear and Re-Creates that you'd want to avoid inside a loop.

-Kevin P.

 

 

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
Message 7 of 8
(6,417 Views)

Hmmm, that's a new one on me.  How exactly have you determined that the property node gets stuck?  And when you say "stuck", you mean that the value remains stuck at False while the loop keeps on running, right?

See the error handling generating code in never_ready.png 🙂

That in turn makes me think, "race condition."  I get suspicious of the way you're "idling the counter" using a hardware pause trigger.  That hardware pause trigger is either controlled by a different part of the code or by an external signal.  Either way, the timing of the Pause / Unpause transitions are not sync'ed to this loop. 

We pause the counter via software output --> DIO7 --> advanced piece 'o hardware (a wire) --> PFI1. Of course, we've looked for a software solution at first.

Let's suppose on iteration i that all the right conditions are met and you do make the call to DAQmx Write to update the pulse freq.  However, before the pulse-in-progress is completed, let's suppose that the pause trigger transitions to the pause state.  Now on iteration i+1 the property node will be False because the counter hasn't generated a cycle with the new frequency yet.  And it will keep on staying False as long as the pulse train is paused.

And, uh, well, now I'm stuck again because I don't see why it wouldn't get back to normal operation when you Unpause the pulse train.  Are you sure that the code running the pause trigger signal isn't somehow stuck?

Yes, we are sure. The stepper motor can still move, but only at a fixed speed.

Finally an idea for a workaround.  Unless your pause trigger needs to be hardware-timed, you could choose not to use one at all.  You can call DAQmx Stop to stop the pulse train and then DAQmx Start to re-start it.  Stops and Starts aren't too terribly slow -- it's the Clear and Re-Creates that you'd want to avoid inside a loop.

Before we used a property node to update the counter frequency, we had a test program that used stop and start blocks to pause the motor and restart with another frequency. This actually was too slow. Nevertheless we've tried to rewrite the code, but I got discouraged because the 'CO.RdyForNewVal' property node doesn't like it when the task is stopped and throws an error.

The program as it is now works well enough. It seems bug free, we only sometimes encounter labview 'features'. Thanks for all the help.

Floris

0 Kudos
Message 8 of 8
(6,326 Views)