Forums › SM Series Discussions › Calibration/Correction in MATLAB I/Q Data

- This topic has 5 replies, 2 voices, and was last updated 1 year, 4 months ago by Andrew.

- AuthorPosts

MZhanParticipantIn power calculations computed via the MATLAB I/Q capture, I am seeing a frequency-dependent offset from the power measurements presented in Spike. Is there a calibration that is being applied in Spike that is not automatically applied in the I/Q data? I see a smGetIQCorrection routine, but I wanted to clarify here what the units for the I/Q data return are and how/if I should be applying some of kind of correction to it.

AndrewModeratorThe 32-bit floating point I/Q data has the corrections applied. It is scaled to dBm. You can read more about this in the API manual in the I/Q data types section. If you are doing an FFT on the I/Q data, ensure your are normalizing your window function and properly scaling the output of your FFT. You should be able to simply do a log power conversion of the FFT results to get dBm.

Andrew

MZhanParticipantUnderstood. The perplexing thing is that we are getting frequency-dependent differences between our conversion to dBm in MATLAB and the spike results. The following is for a tone from a sig gen at -30 dBm. I recorded the correction factor for SA but did not apply it. If it were a simple scaling issue, but the calibration is already correctly applied in the float data, I would expect a consistent offset.

Frequency (MHz) MATLAB Spike Correction Factor

400 -30.5 -30.44 0.2907

1000 -31.47 -30.27 0.2586

2000 -34.26 -30.49 0.2422

3000 -31.81 -31.08 0.2457

4000 -30.96 -31.05 0.2539

5000 -32.34 -31.43 0.2505

AndrewModerator- This reply was modified 1 year, 4 months ago by Andrew.

Can you share the script you are using to calculate I/Q power? How are you measuring power in Spike? With the standard sweep mode and markers? Are you using the default Spike configuration (full 20GHz span on bootup)? Or have you modified any settings in Spike?

MZhanParticipantCode is below:

sm = SMIQReceiver(‘Networked’, ‘192.168.2.10’);

fprintf(‘Open Status: %s\n’, sm.getstatusstring());

fprintf(‘SN = %d\n’, sm.SerialNumber);captureDuration = 10e-3;

sm.CenterFrequency = 2.4e9;

sm.DecimationFactor = 2;

sm.SoftwareFilterEnabled = 1;

sm.Bandwidth = sm.samplerate() * 0.8;

sm.RefLevel = 0;

sm.PreselectorEnabled = 0;

sm.OutputFormat = ‘non-interleaved’;

Fs = sm.samplerate();

captureSamps = sm.samplerate() * captureDuration;sm.start();

iqData = sm.recv(captureSamps, true);

correction = sm.getcorrection();

sm.stop();RBW = 100e3;

NFFT = round(Fs/RBW);

freq = [-floor(NFFT/2) : ceil(NFFT/2)-1] * Fs/NFFT;

freq = freq(1:NFFT) + sm.CenterFrequency;

Pxx = fftshift(pwelch(iqData, NFFT, NFFT/2, NFFT, Fs));

power = 10*log10(Pxx*RBW);

plot(freq, power)

AndrewModerator- This reply was modified 1 year, 4 months ago by Andrew.

Consider doing your own FFT and windowing with something like the flattop window. The pwelch function uses the Hamming window which has ~1.8dB of scalloping loss and could easily account for most of the error you are seeing. The flattop windows has ~.1 dB of scalloping loss, and is much more appropriate for amplitude accuracy, and is likely what Spike is using in your measurements.

Here’s some example code for generating your own spectrum

function [spectrum] = calculatespectrum(t)

%CALCULATESPECTRUM

% Return the log spectrum of the input time domain signal

% The input is a real or complex column vector of floating point values

window = flattopwin(length(t));

if(~isreal(t))

window = complex(window);

end% Normalize window

scalar = length(window) / sum(window);

window = window.*scalar;spectrum = fftshift(fft(t.*window)./length(t));

spectrum = 10 * log10(abs(spectrum).^2);

endIf you want to compare with Spike, ensure you use the same reference level.

- AuthorPosts

You must be logged in to reply to this topic.