If you want to have a feature that you had in your original VI, namely when the user changes the frequency/amplitude via a Gauge/Knob/etc. control, then you could use a State Machine with an Event structure sitting in the "Task running" case. Timeout case is not needed, so never timeout. When the user changes frequency/amplitude, you get these values in the corresponding Event case, and feed these parameters into shift registers, so you can use the new values in the "Init" case. Or, you just stop, clear, then re-create the DAQmx task in that very Event case. However, be careful in this case using Events: you have to avoid accumulating up Events in the event queue, so I advice you to use for example the "mouse up" event, so the Event case only fires after the user changed the Knob to the required position, and released the mouse button, like this:
As DR2 suggested, the other way is to use the so called "non-regeneration" mode for your DAQmx AO Task. In this case you even do not need a State Machine, just a simple single While loop. You can decide which way you wanna go...
Here it is:
Wow guys, thanks a million for everything, tips, hints, examples and support!
Blokk, I'll try these 2 approaches to see if there's any difference in the shaker performance, thanks!
I'll let you know.
I want to feed a shaker I have in my lab with sinusoidal signal. The shaker 's amplifier accepts 0-5V signals and up to 6kHz.
My first attempt (attached VI), when run with a PXI6341 seems to work (the shaker moves at the desired frequency) but there's a beating below the controlled vibration that periodically appears. And moves the shaker so my clean section of the signal is between two consecutive beats (some seconds).
When run with a USB-6009 the shaker doesn't move at a constant frequency, it's like it's not able to handle the data.
Does anyone has ideas on how to solve these issues?
I'm not sure anyone has brought this up.
I'm not too familiar with the PXI6341, and I am not quite sure what "non-regeneration" mode means but I will make an educated guess. If you are using it as an AWG (Arbitrary Waveform Generator) and continuously repeating the waveform, then you have to be VERY careful that you do not have discontinuities between the end/beginning of the waveform. You can either use a windowing function or make sure you generate an integer number of sine waves.
This may be why the OP sees “beats” every few seconds.
Allowing regeneration will make for a much simpler implementation, but be sure to size your output buffer to be an exact integer # of sine cycles. Otherwise there'll be a glitch in the motion when you wrap around your output buffer from the last defined sample back to the first. (For *super-critical* glitch avoidance, please see some stuff I've posted before like in this old thread.)
If it's important not to deliver impulses to the item on your shaker, there are 3 things to be careful about:
1. AO will *not* generate a pure analog sine wave, even if you define a waveform whose voltage values fall exactly on a pure sine wave. AO will only be able to generate discrete voltage values. The part you can't control is the boad's D/A bit depth and how that converts to volts for your needed amplitude. The part you *can* control, and the one with potential to cause vastly larger impulses, is the number of samples you use to define your sinusoid period.
2. If you stop and start the task to change waveform properties, you should take pains to *gently* drive the AO voltage from wherever you left it when you stopped back to the (assumed) 0.0 volts where you're going to start up again. Even so, stopping the sinusoid will deliver *some* impulse.
3. The previously mentioned glitch that can occur when wrapping around the recirculation buffer. That's another possible impulse source.
I got sensitized to this stuff on a particularly sensitive app many years ago, the one mentioned in the thread I linked earlier. Not all apps demand great attention to all the items I mentioned.
P.S. while I was still writing everything above, jamiva just posted an excellent illustration of the wraparound glitch I referred to
Hmm, I am not sure if I understood correctly, but in the "non-regeneration" example ( http://www.ni.com/example/29872/en/ ) it is noted at step "5", that
"Compute the desired waveform, using the buffer size and the actual update rate. This VI keeps track of the phase of the waveform to ensure that the generated signal is continuous."
Does it mean this way you do not get that "glitch"?
A very fair point. I fully expect that example to avoid glitches and allow you to work with any reasonable size buffer you choose. And I must admit the implementation is pretty easy looking.
The solution I linked to arose back in about 2002, in the days of traditional DAQ with single-threaded blocking calls. Continuous feeding of an AO task with new data would prevent any other tasks from doing DAQ API calls. The AO Write equivalent function was less forgiving then too -- it wouldn't wait until there was available buffer space before writing your data chunk, it would simply throw an immediate error if you tried writing too soon. And of course, writing too late was a no-no as well. So continuous feeding of output tasks was an exercise fraught with peril and well worth avoiding when possible. Hence the math effort to find just the right buffer size to fit exact integer periods of arbitrary frequencies at discrete sample rates.
Sometimes it takes a reminder when to *unlearn* habits whose importance has waned.
If your shaker control task utilizes a fixed frequency, then computing the buffer size, etc. would work. However, in real world applications the drive frequency is never fixed and thus a precisely sized buffer is impratical.
Also Kevin_Price & jamiva are correct, you want to avoid any discontinuities (even just brief stoppages) in your signal as they can impart significant impulse loads into your shaker which can either destroy the shaker or invaidate your test.