12-20-2019 06:36 AM
Solved! Go to Solution.
12-30-2019 12:18 PM
So, I'm not super familiar with the DAQ toolbox from MATLAB, but I have a guess as to what might be happening. In LabVIEW/C/C++/C# implementations of the NI-DAQmx drivers, there is a direct call to the driver to query the actual (i.e., coerced) sample rate. I'm not sure how the "time" vector gets generated (it's don't think it's the NI-DAQmx driver, so I'm guessing it's MATLAB code that does this), but it could be that it's not using that call under the hood. I'm also not sure exactly how rounding in MATLAB works. If you, for example, ask the driver to sample at 2048 S/s, but MATLAB represents that value as 25600.00001656845 or whatever, it could be that the DAQmx driver rounds up to the next supported sample rate (51200 S/s). If MATLAB then decides to generate the time vector based on the assumed sample rate (25600 S/s, let's say) and not the actual sample rate (51200 S/s, let's say), then you could see the issue you're seeing. The LabVIEW/C/C++/C# APIs from NI take of these niche rounding cases, but I'm not sure if the MATLAB one does.
Basically, I'm not sure how trustworthy the time vector is since it's almost certainly not NI generating it. (I say that because none of the NI-provided APIs in any language I've used generate a time vector, just a t0 and a dt, which is all the info you need to reconstruct a time vector without wasting RAM to represent every single time stamp for every sample like the DAQ toolbox appears to be doing.)
If you set a sample rate of 2048 and record data for 60 seconds, you should see 2048*60 samples in the returned data and time vector. If you see more samples, then you know it's probably this rounding error taking place. If a rounding error is confirmed to be the culprit, one "easy" fix might be to subtract 1 from your selected sample rate and pass that into the DAQ toolbox - I.e., change "session_1.Rate=fs;" to "session_1.Rate=(fs - 1);". There are no 9234-supported sample rates that differ by only 1 Hz, so this should always be safe for the 9234, and the true sample rate will always be rounded up to the next supported sample rate. If the time vector is really generated by MATLAB, as I suspect, based on the requested and not the actual sample rate, then it should be unaffected, and the rest of your code's logic should work.
01-01-2020 11:05 AM
Thank you for your reply!
I checked my data files and I do get the correct number of samples in my returned data and time vectors (sampling rate * duration). There is, however, something weird going on with the time vector as the time step seems to be inconsistent.
For example, in one of my data files, the time vector looks like this:
0
4.882800000000000e-04
9.765600000000000e-04
1.464840000000000e-03
1.953120000000000e-03
2.441400000000000e-03
2.929680000000000e-03
3.417960000000000e-03
3.906240000000000e-03
4.394520000000000e-03
The difference between two consecutive time entries (time step) is
4.882800000000000e-04
4.882800000000000e-04
4.882800000000000e-04
4.882800000000000e-04
4.882799999999998e-04
4.882800000000002e-04
4.882800000000002e-04
4.882799999999998e-04
4.882799999999998e-04
4.882799999999998e-04
Now, theoretically, all time steps should be the same, however, that is not the case. I am not sure what causes MatLab to construct an inconsistent time step, but this is obviously ruining the sampling rate, which in this case should be 2048, but in reality taking 1/time_step, I get
2.048005242893422e+03
2.048005242893422e+03
2.048005242893422e+03
2.048005242893422e+03
2.048005242893423e+03
2.048005242893421e+03
2.048005242893421e+03
2.048005242893423e+03
2.048005242893423e+03
2.048005242893423e+03
02-24-2020 05:29 AM
02-24-2020 08:02 PM
FWIW, the so-called differences in the time steps you posted are utterly negligible. You've got 15 significant digits of total agreement, and it's no surprise at all that tiny discrepancies show up at the 16th -- it's simply the nature of 64-bit floating point representation.
So again, I don't know what's meant about "data disruption" at certain rates. But I'm still inclined to put more scrutiny on the Matlab code, including some of the things croohcifer already brought up.
I see 3 plots that are very similar in shape but with a different amount of "stretch" along the freq axis. The farther you move to the right, the more they're shifted relative to one another. This would be consistent with a small error in the "delta freq" because the visible "shift" increases as the frequency increases.
The 4th plot starts by seeming to have a "delta freq" of about 1/2 what it should be. But eventually, the calculated response takes on some different shape characteristics than the others.
I've never used the data acq toolbox and have pretty minimal knowledge of Matlab. But I see you assign an intended acquisition time t and a # samples n, but I don't see them used to define your data acq task. At present your requested sample rate is input by the operator. It appears you used to calculate it from an average of the time steps. I would expect the latter method to be nominally more likely to be accurate. However, if you didn't clear out your time vector between runs, a later run might not overwrite *all* the time values held over from the prior run. That could easily lead to enough error in the average time step to explain the "stretch" effect seen in 3 of the plots.
But at the moment, that calculation is commented out. It just isn't clear whether it was commented out before or after you generated the plots.
Honestly, I'm a little dubious that your issues would be explained by the "data disruption" idea. That kind of bug would affect your time domain data. If you lost raw time domain data, I don't think you'd get 3 frequency domain plots that were ready to overlay almost perfectly, subject to a small correction to their respective frequency increments.
Whatever that bug is, I'm still not so sure you can't get reasonable results just by making some adjustments in your Matlab code.
-Kevin P
02-25-2020 05:30 AM
Hi, Kevin!
Thank you for your comments!
I discussed this issue with MathWorks technical support, and they confirmed that it is indeed a bug, and they are working to solve it.
Before that, I went through numerous MatLab tutorials about data acquisition, and I modified my code several times trying lots of different settings including setting duration and # of samples as a session property. It made no difference.
MathWorks suggested to test a very simple setup to see if the problem still persists. Basically, I connected my NI-6341 card to my laptop; the card was then directly connected to NI-9234 card, and this card connected back to laptop. I generated a simple sine wave with a frequency of 2 Hz, and I plotted output signal and the input signal read by NI-9234. In this simple test any other test equipment as shakers and transducers were excluded; additionally there were no calculations of transfer functions - I simply plotted two unprocessed signals.
The code I used is shown here:
clc %clear command window
clearvars %clear all variables from the workspace
close all %delete all figures
daq.getDevices; %display connected devices
session_1=daq.createSession('ni'); %create session for a specific vendor
fs=input('Input a sampling rate in Hz: '); %[Hz]
t=10; %test duration [s]
session_1.Rate=fs;
n=fs*t; %total number of data points
%add input channels to the session
addAnalogInputChannel(session_1,'Dev1','ai0','Voltage'); %excitation signal
%add output channels to the session
addAnalogOutputChannel(session_1,'Dev3','ao1','Voltage');
dt=1/fs;
wave_freq=2;
duration=0:dt:t;
output_data=sin(2*pi*wave_freq*duration);
output_data=output_data';
% figure
% plot(output_data);
% title('Sine wave excitation signal')
% xlabel('Data points')
% ylabel('Sine wave magnitude')
queueOutputData(session_1,output_data); %prepare the output signal for application
[data,time]=session_1.startForeground(); %start data acquisition
measured_signal=data(:,1);
figure
plot(time,output_data,time,measured_signal)
legend
This plot below shows the generated sine wave in blue and the measured signal in orange; sampling rate 3200 Hz. There is a slight lag there but at least the measured signal is also a sine wave of 2 Hz, and it follows the trend of the input signal.
Now, this plot below again shows input signal in blue and output in orange at a sampling rate of 5120 Hz. It is obvious that the measured output signal has some sort of data disruption, which, I believe, causes my transfer function curves to deviate.
I find it very interesting what happens at the sampling rate of 25600 Hz. In my initial post, data measured at this sampling rate deviate the most. Plot below shows that at this sampling rate, the output signal only shows a sine wave with a frequency of ~1 Hz, while the input is 2 Hz.
Now, work-around for this problem would be to use sampling rates that show no data disruption/deviation. However, I have modified my test setup already to exclude NI-9234, and I am using NI-6341 for analogue output signal and analogue inputs. Using the same MatLab script as in my initial post, there is no data deviation anymore.
Thank you!
02-25-2020 08:23 AM
You literally just proved my comment from above... There is simply some kind of rounding error - probably in the representatation of the double precision float sample rate variable - taking place in the MATLAB wrapper around the DAQ functions.
Let's clarify a few things.
When you refer to a "data disruption", what you're actually referring to is perceived drift. Your sine wave isn't "disrupted" (this isn't a signal processing term), it was just acquired at the wrong sample rate. At a sample rate of 3200 S/s, your signals look as though they don't drift. There appears to be no rounding error in this case - i.e., you ask for acquisition at 3200 S/s, and the DAQ driver actually does that.
At 5120 S/s, they appear to drift, where 10 cycles of the input results in only 9 cycles of the output. This would be consistent with 5120 getting rounded up to the next supported 9234 sample rate (51200/10 = 5120 and 51200/9 = 5688.88888). The ratio of those two sample rates is 9:10, which is why you see 9 cycles of output for every 10 of input at this sample rate.
At 26500 S/s, they appear to drift, where 2 cycles of input results in only 1 cycle of output. This would be consistent with 26500 getting rounded up to the next supported 9234 sample rate (51200/2 = 26500 and 51200/1 = 51200). The ratio of those two sample rates is 1:2, which is why you see 1 cycles of output for every 2 of input at this sample rate.
As I stated above:
If you see more samples, then you know it's probably this rounding error taking place. If a rounding error is confirmed to be the culprit, one "easy" fix might be to subtract 1 from your selected sample rate and pass that into the DAQ toolbox - I.e., change "session_1.Rate=fs;" to "session_1.Rate=(fs - 1);". There are no 9234-supported sample rates that differ by only 1 Hz, so this should always be safe for the 9234, and the true sample rate will always be rounded up to the next supported sample rate. If the time vector is really generated by MATLAB, as I suspect, based on the requested and not the actual sample rate, then it should be unaffected, and the rest of your code's logic should work.
Please give that a try and let us know if it solves your problem.
02-25-2020 09:13 AM - edited 02-25-2020 09:19 AM
The analysis from croohcifer sounds spot-on to me.
See if your Matlab toolbox provides functions for querying the actual sample rate(s) used by the output and input tasks (sessions?). Querying the actual sample rate would help demonstrate the things croohcifer identified that and also be useful for your further processing, including the possibility that you might need to make your own *correct* time vector.
Doing some further investigation and digging like this seems like a better alternative than being stuck waiting on some kind of bug fix from Matlab. (While I don't *know*, I wouldn't rule out the possibility that Matlab support could have an inaccurate understanding of NI's products. What they think is their own bug might be partly due to insufficient knowledge about sample rate quantization on devices like the 9234.)
-Kevin P
02-27-2020 05:49 AM
Thank you croohcifer and Kevin for your comments!
I tried setting session sampling rate to (fs-1) however I still see that the output signal does not follow the input signal. The only way I know how to check the sampling rate in MatLab is to calculate 1/time_step and take the mean value of that. I haven't found any other way.
These are the results I got by trying (fs-1):
2048 Hz
5120 Hz
25600 Hz
As I mentioned before, I have excluded NI-9234 from all of my tests and I am using NI USB-6341 instead where I do not get this issue.
Thank you!
02-27-2020 09:36 AM
1. It's good to know you've got a workaround using a USB-6341.
2. I tried looking up a function list for Matlab's data acquisition toolbox to see if I could spot something useful. Wow, the list of available functions is shockingly small!
3. If you've got a trusted function generator and scope, you could make some headway characterizing the issue with the 9234. That'll be up to you of course, you've got a workaround already. But the 9234 *does* have some nice features (24-bit conversions, integrated anti-alias filter...) which could make it worthwhile.
You'd just generate a steady sine or square wave at a known frequency while capturing it with the 9234 at various sample rates. Then you can post-process the data and times, which might let you figure out the needed compensation factor to cover over the bug in the Matlab toolbox.
-Kevin P