07-29-2011 09:48 AM - edited 07-29-2011 09:50 AM
Hello! I have a problem that has been following me throughout this project, so I feel I must ask:
My project involves outputting a sine wave (to a 6341 USB board) of varying amplitude, depending on an input. I figured the easiest way was to just put a waveform generation and write in a loop. However, it seems that the loop only goes around with the frequency of the sine wave I'm generating (which is generally low - less than 40Hz), suggesting that something in the loop is blocking it. My suspicion goes to the daqmx write vi.
The help page says that it does block the loop, if the timing is set to on demand. My project however uses sample clock timing, so it should return quickly.
I've made a stripped-down version, to verify this. The 'Loop time' indicator is almost stable around the period of the output wave.
Can anyone please explain this?
Also, since I'm posting, I figure I might as well ask this too and spare another thread: while non-regeneration works ok when I set the amplitude of the generated wave to an analog input value, switching to "allow regeneration" causes the device to always output 2 periods with the same amplitude (thus significantly reducing response time). I suspect this happens because there is a (small) delay between the end of the output generation and the sending of the next waveform, so the board starts a regeneration in the meantime. Is this correct? Is there a way around this?
08-01-2011 04:30 AM
Hello BogdanB,
your assumption was right, the DAQmx write VI is blocking the loop. It does so, because the first few iterations of the loop fill the output buffer, and after that it has to wait for the device to output some data and free up some buffer space. I verified this behavior by wiring the loop time to an auto-indexing tunnel and displaying the resulting array (you will need a stop button or some other way to stop the program without aborting for this). After pressing the STOP button, you will see, that the first few loops execute in very little time, but after about 10 iterations, you will get the consistent 50 ms execution time.
Your second assumption is also correct. However, with regeneration enabled, you don't have to write every period to the output buffer. You only need to change the contents of the buffer (thus use the DAQmx Write VI) if an amplitude change is needed. Keep in mind though, that with this solution glitches can occur on the output when the buffer content is changed.
Please feel free to ask any further questions!
Daniel
08-01-2011 06:01 AM
Thank you for clearing that up!
Now the question is, how can I solve this? I was thinking that maybe I can put the write operation in a case structure, so the main loop can go around quickly, and do nothing if the device still has a lot to do, instead of blocking and waiting for another chance to write. This doesn't really seem to work though: I wired the case structure with the write operation to the difference between the current milisecond count and a local variable that gets updated at every write operation, so that it would only try to write if it were more than 30ms into the 50ms write cycle. The main loop however refused to go below 50ms. Which generates the question: does the write vi block before writing (waiting for space to be created), or after (wait until the generation is finished) ? Also, do you have any suggestions on how to check on the status of the device (will the current write position property node give me the information i need) ?
Regarding regeneration: yes, it is expected that the input will change every cycle. In fact, regeneration is used more as a fail-safe to deal with possible buffer under-runs, rather than as an accepted way of generation. So it is imperative that I can update the data quick enough to prevent guaranteed regeneration.
08-01-2011 07:25 AM
Figured I should attach a diagram of what I used, to make things clear. The waveform chart shows that the delay between an attempt to write and the following iteration is always ~50ms (after the initial set-up period)
08-01-2011 07:28 AM
If the output amplitude is expected to be updated every period, the easiest fix is to put a Wait Until Next ms Multiple VI in the loop with 50 ms wait time. This way the output buffer will only contain only one period's worth of data at all times, so you can output a different amplitude every period. I attached a sample that iterates between 5 different amplitudes.
Your suggestion to check the status of the device with the DAQmx Write Property node is absolutely correct.
08-01-2011 09:09 AM
Ok, I think I've solved the first part: using "wait for T ms" doesn't really help, since it just moves the delay from the Write VI to another part of the loop. Instead, I've added a local variable that gets updated with the ms count on every write, and the write operation is in a case structure that only executes after (T - epsilon) ms since the last write (where epsilon is the round-off error constant - a number small enough to make the delay as close as possible to T)
My main problem now is with regeneration: when I turn it on, not even the trick above works, the loop just gets delayed by 2*T (100ms). It's as if the device starts regenerating by default, not caring if it has new data to output. Any idea why this happens?