Intermodulation products (third order) from MATLAB and FFT are too low

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

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?
Hi, Yes the the transfer curve shows input power against output power.
To find the third order harmonics:
First I create two frequencies and sum them into a waveform over a time interval. The amplitude of the waveform is read and then changed to what it would be after amplification (by a look uptable method). Since the transfer curve is not linear at higher amplitudes, this should cause intermodulation. Unfortunately my intermoduation products I see after the fast fourier transform are not high enough according to Third Order Intecept theory.
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?
I uploaded plots for my description below. Figure 3 is the transfer curve.
No, I have a transfer curve of amplitude in against amplitude out and interpolated it into tiny segments.
Each instance in time (sample point) of the waveform is multiplied by a ratio of amplitude_out/amplitude_in to get its final amplified value at each point on the waveform, thus matching the transfer curve.
If I say it another way, I read the waveform amplitude and use a lookup table method. This is from the transfer curve, one array is amplitude_in and the second is amplitude_out. I read the waveform amplitude_in a for the length of the waveform, and find its matching amplitude_in from the transfer curve and do a ratio multiplication to get what it should be after going through a transfer curve amplification.
The time domain waveform looks perfect to me, its shows a zero gain when the amplitude is high because its in the saturated region of the transfer curve and it appears to shows the correct amplification in the linear section. I know from further analysis of third intercept point that my intermods are too low.
I uploaded plots. The first two plots are the waveform. Figure 3, far right is the transfer curve used in lookup table method.
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.
Please see attached full screenshot of all my graphs detailing quite a bit of data. You can somewhat see the intermods in the output frequency domain plot.
The central plots show dashed lines which are linear approximations. The linear approximations are the correct 3-1 ratio (approximately), with 1dB of gain on the waveform the intermods increase by approx 3dB. But their actual values of the intermods are not high enough. If they increase just a little, I assume my ratio will stay around 3-1 but the intercept will decrease (which it needs to in my model to match actual data).
The TOI here is not what the actual value is from the data sheet, I am expecting -7 dBW for TOI. My waveform is scaling correctly and has the EXACT gain it should, but my intermods are not high enough?
Have you tried using TOI in the Signal Processing Toolbox?
Don't have access to it, so Im going manual. Can you advise my issue please?
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.
Please do not close questions that have an answer.
@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.
Hello
Could you send me the code (or a link to it), please?

Sign in to comment.

Answers (3)

Hi,
Its attached.
  • It contains the controls at the start.
  • Then it has the transfer curve data, AM-AM and AM-PM.
  • This transfer curve is interpolated (cut up into small slices).
  • A waveform is generated from a sum of sinusoids. (or just one frequency). The amplified waveform doesn't have even order harmonics, only odd and I am also confused why.
  • Each point on the waveform is amplified by the transfer curve ratio of voltages. Basically whatever the voltage at each sample point is on the input waveform, the sample point is converted to the output voltage off transfer curve by a ratio multiplication.
  • A FFT is completed showing harmonics and Intermodulation.
The literature says the ratio of slopes, Intermodulation slope of input power vs third order intermodulation should be 3:1 against input vs Output slope. But I have looped my script and using different transfer curves, I get different ratio of slopes.
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
-

5 Comments

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.
One thing I had intended to annotate but forgot was the four numbers in the results (dBm), so I just updated the answer.
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.
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.
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

Sign in to comment.

Categories

Asked:

on 26 Jan 2018

Commented:

on 28 Jul 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!