I am attempting to synchronize the control of a proportional pneumatic valve with the angular positions of of rotor shaft equipped with a quadrature encoder so that the valve control is phase locked (at least to within a few degrees) with the shaft. I have several PXI modules at my displosal byt the PXI-6281 is the only module with analog output so this is what I am using. The shaft itself only rotates in one direction but at fairly high rates (~2500 RPM). The encoder is 1024 cycles per revolution and I have been able to use the A,B and Z channels from it to measure angular position which is then measured using an external 20 kHz clock that has been synchronized with several other Analog Input channels. My next step has been to get the analog ouput working along with this but it is giving me headaches.
My initial thought was to use the 1024 cycle/rev A channel from my encoder as a sample clock for the analog output. Then using a hardware timed single point analog output, I would just split my desired periodic voltage output signal into 1024 values and send the appropriate value at proper angular position and I figured that the hardware should be to handle this as the PXI-6281 spec says it can do one channel at 2.86 MS/s. I started the code using a nice clean clock signal from another device (PXI - 6602) since the encoder signal is sometimes pretty noisy and things seemed to work up until about 1000 Hz at which point the "DAQmx Wait for Next Sample" started to say that it was missing some edges and I saw some blips in the voltage ouput. Since I'll ultimately be going to pretty high rates (1024 cycles/rev * 2500 RPM = 42,667 Hz) I think that I need to find another way to do this (or maybe this will work and I am doing something wrong).
Has anyone run into this missed edge problem and have any idea what could be causing it. Could it just be because of noise in the clock signal that it is missing edges? Should I instead try this with a full revolution of analog ouput already in the Buffer and use the 1/REV Z signal?
Thanks in advance for your help and I have attached a copy of my trial code that just calculates a sin value for each iteration of the hardware timed loop.
I forgot to mention that one of the key problems with my current method of using the 1024 cyc/rev signal as a clock is that due to vibrations and background noise levels the encoder will occasionally give and erroneous or missed reading (i.e. it skips a cycle) that over time will result in a phase drift/error of the valve control with respect to the controller. For my encoder angular postion measurment this is dealt with by putting a filter on all three encoder channels (A,B,Z) and the Z indexing is enabled to restart the whole thing. Ideally I would have this same functionality so that every revolution when the shaft is at 45 degrees the valve is doing what it is supposed to do at 45 degrees (give or take a degree or two). I don't think though that at the rates I am trying to do this at I could simply take an encoder angular position measurement and then use a look up table or something to find the appropriate analog ouput value.
As far as I can tell, the value of your analog output is pre-determined and can be pre-written to the DAQmx buffer so there shouldn't be any need to do hardware-timed single point. Is this the case? The 2.86 MHz spec assumes you are buffering your outputs. Hardware-timed single point does not use a buffer and relies on the software and OS to write single-point data quickly enough to keep up with the clock. Unless you're on a real-time OS this operation is non-deterministic and not sustainable at higher rates.
If there are glitches on your encoder signal (which is common for encoders), I would recommend enabling digital filtering on the 6289 (see M Series User Manual). You can't directly set the digital filter for a sample clock source, but if the same PFI line is set as part of a counter task you can configure it this way (see here).
So, I think a continuous analog output task with the pre-allocated values for each position would be best. The buffer will be regenreated by default, so you only have to write the 1024 samples once before the task is started. For the sample clock, you may use the A output of the encoder but you should apply digital filtering to remove glitches (use the dummy counter workaround linked above). The 6.425 us setting is probably a good starting point--assuming an approximate 50% duty cycle your encoder pulses should be at least 11 us at 2500 RPM.
One downside is that you would not be re-synching with the Z index pulse, but hopefully digital filtering should fix the problems you were having with picking up duplicate edges.
Thank you very much for your input. I now understand why the single point hardware timed method wasn't the route to go. I have taken your advice and am attempting to use the 1024 counter on the encoder as a sample clock for the buffered waveform divided into 1024 points per revolution. The attached code shows what I am doing, using a counter on a different device to simulate the encoder clock, then writing my waveform to the buffer and streaming it to the Analog Output continuously. This seems like it will work with one exception.
I am finding that the code appears to work properly when the dummy filtering is disabled on Ctr0 of the 6281 (I am using PFI 😎 but that when I activate filtering, it stops working and doesn't appear to be recieveing the counter edges. Having read the comments on the dummy counter technique I can't figure out what I might be doing wrong but something associated with the filtering is clearly at fault.
Also, looking ahead is there any reason I shouldn't be able to add several Analog Input acquisition tasks to this code to simultaneously record data?
I figured out why the filtering was not working. Despite indicating that the default was 6.425 u for the minimum pulse width it was set to 2.56 m. I changed it and everything seems to work for the time being.
Thanks again for your help,
I also added a start trigger for the analog output that uses the filter Z signal from the encoder (1/REV) so that the AO signal starts at the same angular position at least first time around. What I notice however is that the signal phase immediately begins to shift which indicates that it is likely missing an edge here or there even with the filtering on the A (1024/REV) signal enabled. I believe that if the PXI-6281 could handle AO retrigggers then I could solve this problem pretty easily but I don't think that is has that capability. Is there someother way to mimic that type of behavior so that if the phase begins to move way off the AO will adjust itself accordingly. Perhaps the buffer could occasionaly be rewritten?
Are you missing edges or picking up duplicate edges? The filtering would help the duplicate edges case (which is what I might expect to see) but wouldn't change anything if the problem is missing the edges altogether. Is the output of your encoder 0-5V?
You are correct that retriggerable AO is not supported on the 6281. Later generation X Series cards do have this feature, but triggers would be ignored while the generation is still taking place so you would miss an entire revolution of your encoder if you aren't picking up enough clock edges.
I think the best bet is to try to clean up the signal itself. If it's 0-5V then I'm not sure why you would be missing edges, can you confirm that this is the case? If not, perhaps you can use an external buffer to clean up the digital signal.
Yes I am using a 0-5 V output on the encoder.
I believe that you are correct in that it is not missing edges but rather detecting additional edges as the phase of the AO consistently shifts to the left (i.e. what occurred at 90 degree before will occur at 85 degrees). That being said I am still not sure what a good approach to fixing this is. You mentioned an external buffer? Because the phase shifts relatively slowly from one revolution to the next could the entire task be stopped and restarted occasionally using the start trigger linked to the Z signal to mimic resetting the phase? Or would this be extremely slow.
It would take a couple ms to restart the task in software. If this is acceptable then it's not a bad option, but you will have some time when no signal at all is being output while the task is restarting. It wouldn't continue until the z index pulses high.
The external buffer I mentioned could be used to clean up the digital signal before it is sent to the DAQ card. You might want to scope the encoder output first to get an idea of what you're dealing with, but an external schmitt trigger with hysteresis might do the trick.
I was able to clean up the signal enough so that it doesn't get any extra edges within a reasonable amount of time and everything is now looking pretty good. My current program simultaneous controls the valve using the 1024 Sample Clock, records several analog inputs on a different device (PXI-6123) using the same clock, and records the angular position of the rotor. All this is great but I have noticed another problem.
The data that is being stored is either in 1D arrays or Waveform and I am a bit concerned about the time associated with each sample. Generally you use a sample clock that is nice and uniform in terms of time in between samples and so synchronized data is no problem. Each sample is just dt seconds after the previous one. However, because my current program uses the encoder 1024 signal itself, the time in between samples is not necessarily uniform. I have seen that the time step is actually set by whatever I put as input to the rate for the sample clock even though that rate could easily be incorrect.
Ideally I would like some way to register an actual time stamp (relative to start) for each of the data points. Is there some way that a time source on the device could also be "read" at the same time as each analog input/output is recorded/generated?