Intermodulation products (third order) from MATLAB and FFT are too low
Show older comments
Hi,
The intermodulation products I get from an FFT are too low but they scale correctly against my wanted frequency signal power, at a 3:1 ratio which is correct according to the theory. http://www.electronicdesign.com/what-s-difference-between/what-s-difference-between-third-order-intercept-and-1-db-compression-point
Is there any fundamental reason why MATLAB may not produce intermodulation values at what they should be?
I have developed a script that takes two closely spaced frequencies combined in a waveform and put them through an amplifier transfer curve. The transfer curve is from actual amplifier data.
The amplitude of the waveform before amplification is scaled to what the amplitude should be after amplification. Due to the nature of the amplifier transfer curve, the scaling is non linear at higher amplitudes. This should cause intermodulation, I see the intermodulation on an FFT and record their values.
Unfortunately, the intermodulation values are too low. I know this because my Third Order Intercept point is too high compared to real data. https://en.wikipedia.org/wiki/Third-order_intercept_point
Any Advise would be appreciated.
13 Comments
David Goodmanson
on 28 Jan 2018
Hi Nathan,
Is the transfer curve something like gain as a function of input level for a family of frequencies? If so, do you have to fit each gain curve to a polynomial or something similar in order to proceed further and find the third order harmonics?
Nathan Kennedy
on 28 Jan 2018
David Goodmanson
on 28 Jan 2018
Edited: David Goodmanson
on 28 Jan 2018
To do this, do you get from the table the gain g0 in the linear region, and fit the gain curve to the amplitude expression A_out = g0 - g2*A_in.^2 ... + possibly other terms ?
To be able to create the expression y_out = g0*y_in - g2*y_in.^3 where y_in is the signal?
Nathan Kennedy
on 28 Jan 2018
Edited: Nathan Kennedy
on 28 Jan 2018
David Goodmanson
on 29 Jan 2018
Edited: David Goodmanson
on 29 Jan 2018
What value of TOI are you looking to get?
I took a look at the amplifier gain plots. The lower one says dBm in the title and dB on the x and y axes. Is dBm on the axes correct?
The upper one says InputPower(V) and InputPower(V) which does not make sense unitwise, and if it were volts does not correspond to the lower one in terms of 1Vrms = +13 dBm.
Nathan Kennedy
on 29 Jan 2018
Edited: Nathan Kennedy
on 29 Jan 2018
Greg Dionne
on 29 Jan 2018
Have you tried using TOI in the Signal Processing Toolbox?
Nathan Kennedy
on 29 Jan 2018
David Goodmanson
on 30 Jan 2018
Edited: David Goodmanson
on 31 Jan 2018
Hi Nathan, could you post an amplifier gain curve in a text or mat file? In that case I will let you know how the TOI code I have comes out.
Walter Roberson
on 10 May 2018
Please do not close questions that have an answer.
Jan
on 10 May 2018
@Nathan: You got a lot of help in this forum. Then removing your contributions is impolite and against the nature of this forum. Please don't do this.
Rena Berman
on 15 May 2018
(Answers Dev) Restored edit
Ebrahim Soujeri
on 28 Jul 2021
Hello
Could you send me the code (or a link to it), please?
Answers (3)
Nathan Kennedy
on 5 Feb 2018
Edited: Jan
on 10 May 2018
0 votes
David Goodmanson
on 9 Feb 2018
Edited: David Goodmanson
on 14 Feb 2018
Hi Nathan,
I ran my old toi code and came up with 24 dBm = -6 dBW which is pretty close to what you are looking for. The code is not very sophisticated compared to what the toi function in the Signal Processing toolbox can do, but it's a reasonable answer.
Before doing that I took the gain curve from test_help.m and fit it to a parabola ~~ ( constant - v_in_tc^2 ). That's in plot 1 and I think you will agree that the fit is pretty good. This simple gain curve does not ever saturate but it is good somewhat past the 1dB compression point before it goes funny (fig 2). In this model if you include the linear gain curve you can calculate right through the toi without extrapolating, although I used a well known expression to calculate it anyway for small input values.
The code uses A for input amplitudes, B for output amplitudes. Result is Btoi_dBm = 24.1078
(get v_in_tc and v_out_tc, length 51)
Atc = v_in_tc(:)'; % row vectors
Btc = v_out_tc(:)';
A = (0:.0001:6e-3); % wider set of input values
gaincurve = Btc./Atc;
% fit the curve with gainfit = glin*(1 - Ain^2/C^2)
M = [ones(size(Atc))', -(Atc.^2)']; % mini vandermonde matrix
c = M\gaincurve';
glin = c(1); % linear gain
C = sqrt(glin/c(2));
gainfit = glin*(1-A.^2/C^2);
% find gain curve for one input frequency as a check
A0 = sqrt(3/4)*C;
G = @(glin,A0,yin) glin*yin.*(1 - yin.^2/A0^2);
Azero = zeros(size(A));
B = toifun(G,glin,A0,A,Azero); % freq. 1 input only, no freq. 2
gaincheck = B(2,:)./A; % frequency 1 output, then /input
% find the point 1 dB down on the gainfit curve
dB1 = 10^(-1/20); % factor for 1dB down
Ad = sqrt(1-dB1)*C;
Bd = glin*Ad*(1 -Ad^2/C^2);
figure(1)
plot(Atc,gaincurve,A,gainfit,A,gaincheck,Ad,Bd/Ad,'o') % Ain vs gain
grid on
% find toi
nstart = -5;
nfin = -1;
ptsdec = 20;
A1 = logspace(nstart,nfin,(nfin-nstart)*ptsdec+1);
A2 = A1;
B = toifun(G,glin,A0,A1,A2);
Blin = glin*A2;
Binter = B(4,:); % output at freq. 2*f2-f1
Bf2 = B(3,:) % output at freq.f2
Atoi = A2.*sqrt(Blin./Binter); % vector of toi calculations
Atoi = Atoi(round(length(A2)/3)) % pick a representative value
Btoi = glin*Atoi;
% results; convert to dBm
glin_dB = 20*log10(glin)
Ad_dBm = v2dbm(Ad) % 1 dB compression point, input
Atoi_dBm = v2dbm(Atoi) % third order intercept, input
Bd_dBm = v2dbm(Bd) % 1 dB compression point, output
Btoi_dBm = v2dbm(Btoi) % third order intercept, output
figure(2)
loglog(A1,Bf2,A1,Binter,A1,Blin) % Ain vs linear (f2) and intermod (2*f2-f1) amplitudes
grid on
function B = toifun(G,glin,A0,A1,A2)
% row vectors A1,A2 are input amplitudes of two cosine waves f1,f2, f1<f2
% B is an 8 row matrix of output amplitudes whose rows have frequencies:
% 2*f1-f2, f1, f2, 2*f2-f1, 3*f1, 2*f1+f2, 2*f2+f1, 3*f2
nA = length(A1);
B = zeros(8,nA);
% make a time array; delf = 1 for fft frequency array
N = 1e3;
t = (0:N-1)/N;
f1 = 10;
f2 = 11;
y1 = cos(2*pi*f1*t);
y2 = cos(2*pi*f2*t);
ind = [2*f1-f2 f1 f2 2*f2-f1 3*f1 2*f1+f2 2*f2+f1 3*f2] +1;
for k = 1:nA
yin = A1(k)*y1 + A2(k)*y2;
yout = G(glin,A0,yin);
z = fft(yout)/N;
B(:,k) = abs(2*z(ind));
end
end
function dBm = v2dbm(Vrms)
% dBm from Vrms
% dBm = v2dbm(Vrms)
dBm = 10*log10(Vrms.^2/50) + 30;
end
Nathan Kennedy
on 13 Feb 2018
Edited: Nathan Kennedy
on 9 May 2018
0 votes
5 Comments
David Goodmanson
on 13 Feb 2018
Hi Nathan,
Maybe I should have done more annotation. Actually I am running through a lot of different amplitude levels and finding the intermods from an fft. Those levels are in the vectors A1 and A2 which are created in the '% find toi' section just before the toifun function definition. Then toifun runs through the levels one by one (same level for each of f1 and f2), does the fft and saves the results.
The code has a line for Blin, the linear gain amplitude at f2. And a line for Binter, the intermod amplitude at 2*f2-f1, which is annotated as such. Then fig.2 plots those (along with a third line). The two lines cross at 3.59 V which is about -6 dBW which is close to what you said it is expected to be.
For data, I took the 51-point arrays v_in_tc and v_out_tc from the attachment test_help.m in your answer of Feb 5. (I should mention that the preference of the website is that what you are posting as answers should really be comments).
After you supply v_in_tc and v_out_tc at the top, if the script does not run as is, let me know. Fig. 1 shows a fit of the data to a polynomial.
I will take a look at your code but since it is extensive and does a lot of things it won't be quick.
David Goodmanson
on 14 Feb 2018
One thing I had intended to annotate but forgot was the four numbers in the results (dBm), so I just updated the answer.
David Goodmanson
on 15 Feb 2018
Edited: David Goodmanson
on 15 Feb 2018
Hi Nathan,
I don't like overly long variable names, so I tend to overcompensate. I will send you an email later today with details on some of the variables (let me know back here if the email didn't not work) but I have a couple of comments here.
I am assuming that the input voltage runs from .0005 to .0053 and the output voltage from .108 to 1.04 and those are all Vrms. The various files you posted for data set 1 are all consistent with that.
The code I wrote uses Vrms all the way through except for the very end where variables are converted to dBm. Although it could have been done that way, there are never any explicit power calculations. I'm not adding noise so I think that obviates having to use power.
I tried to run your code but it lacks the 'nearestpoint' function, could you post it?
Yes it's dBW = 10*log10(Vrms^2/50) as long as you are using Vrms, but 10*log10((V^2/2)/50)) if it's voltage peak amplitude. You have to be careful which intermod frequency you use though.
David Goodmanson
on 27 Feb 2018
Hi Nathan, I got nearestpoint and I get the figures now but not the plots from 'vline' because that function is not around. Fig 103 shows for third order amplitude a line that drops for awhile and then rises, so there are problems there.
David Goodmanson
on 25 Mar 2018
Hi Nathan,
It looks like you are getting closer, but there are still some steps to go. I think that the most likely reason for the 6dB disagreement is the following. The fft of cos(2pi f t) has a peak at +f and a peak at -f, each of amplitude 1/2. So if you are looking at the positive frequency peaks only, those have to be doubled (except for the one at frequency 0) to get back to amplitude 1.
Whatever the reason, if you correct the linear peaks by a factor of 2, then to make the toi come out in the same spot the third order peaks will have to get larger by a factor of 8, so there is still work to do.
Suppose there is a test function (I won't call it a gain curve yet) such that
yout = C1 [ A cos(2pi f1 t) + A cos(2pi f2 t) ] % C1 is linear gain
+ C2 [ A cos(2pi f1 t) + A cos(2pi f2 t) ]^2
+ C3 [ A cos(2pi f1 t) + A cos(2pi f2 t) ]^3 % assume C3 <0 for compression
+ C4 [ A cos(2pi f1 t) + A cos(2pi f2 t) ]^4
etc
Then looking at C1 and C3 only,
yout =
C1 A [cos(2pi f1 t) + cos(2pi f2 t)]
+ C3 A^3 *
[ (9/4)(cos(2pi ( f1 ) t) + cos(2pi ( f2 ) t)) % fundamental
+ (3/4)(cos(2pi (2f1-f2) t) + cos(2pi (2f2-f1) t)) % low freq intermods
+ (3/4)(cos(2pi (2f1+f2) t) + cos(2pi (2f2+f1) t)) % high freq intermods
+ (1/4)(cos(2pi (3f1 ) t) + cos(2pi (3f2 ) t)) ] % triple freq
For the C3 part the first two lines are nearby to f1, f2 and the third and fourth lines are up around 3f1,3f2.
C3 contributes to the fundamentals f1,f2 but that comes in as A^3 and does not contribute to toi (it definitely contributes to the 1dB compression). Only the C3 term is responsible for toi. Since none of the other C terms come in as A^3 they might mess things up, but they can't possibly contribute to toi. I agree with you that doing a fit containing C4…C10 overcomplicates things and probably reduces the C3 term. In my code I even got rid of C2.
In this situation you can calculate toi which is (C3 being negative)
sqrt((4/3)*C1/(-C3)) % input
C1*sqrt((4/3)*C1/(-C3)) % output
I think it is a good idea to take a simple case where everything is in terms of peak amplitude in volts, such as
C1 = 200
C3 = -2e6
A = input amplitude, range from 1e-5 to 1e-1
and get the code to replicate the known answer
toi = 0.0115 % input
= 2.3094 % output
Categories
Find more on Measurements and Feature Extraction in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!