# FMCW Radar - What's wrong with the transmitted signal model?

I am new to FMCW radar and trying to plot the transmit signal over time.

As you know, the transmitted signal is modelled as: $$s(t) = cos(2\pi f_c t + \pi S^2),$$ where $$S = BW/T_{chirp}$$ is the slope, $$BW$$ is the bandwidth and $$T_{chirp}$$ is the time duration of a chirp. The model can be found here: https://springerplus.springeropen.com/articles/10.1186/s40064-015-1583-5

My problem: I plot $$s(t)$$ using Matlab and end up with the following:

Unfortunately, the above figure is different from what I expect. In theory, the FMCW spectrogram in the freq-time domain has to look like this:

Thus I am really confused because the transmitted signal model is simple and I cannot find the errors in my Matlab code. The following is my code:

clear all; clc;

f0 = 77e9; % the starting chirp freq
BW = 150e6; % the bandwidth
T_active = (7+1/3)*1e-6; % the chirp duration
slope =  BW/T_active; % the chirp slope

fs = BW; % the sampling freq
samples = floor(T_active*fs); % number of samples
chirps = 1;

%% MY CODE IS HERE
t = linspace(0, chirps*T_active, samples*chirps);
a_BP = zeros(1,length(t));

for i=1:length(t)
if (0 <= t(i)) && (t(i) <= T_active)
a_BP(i) = cos(2*pi*f0*t(i) + pi*slope*t(i)^2);
else
a_BP(i) = 0;
end
end

figure;
subplot(211);
plot(0:1/fs:chirps*T_active-2/fs, real(a_BP));
ylabel('Amplitude (v)');
title('FMCW signal');
axis tight;
subplot(212);
spectrogram(a_BP,32,16,32,fs,'yaxis');
title('FMCW signal spectrogram');


Although Matlab has a built-in function to create the correct figure but I do not want to use it and it is encapsulated.

Questions: What is wrong with my code? It would be appreciated very much if you could help me to fix the code and give astute advice. Thanking you in advance.

• Do not include the $77(\mathrm{GHz})$ carrier frequency when plotting the waveform. Also, the sampling frequency should, as a general rule, by greater than the bandwidth by a factor of $1.2$ or so. Commented Jul 21, 2023 at 17:52
• @AnonSubmitter85: Thank you, I removed the term $2 \pi f_0 t_i$ and get a better picture for illustrating the signal. But, the spectrogram does not improve even when I change the sampling frequency to $1.2 \times BW$. Do you have any idea of how to get the correct spectrogram? I really need it to be fixed :( .
– pej
Commented Jul 21, 2023 at 19:48
• Actually, since your signal is real, the sampling frequency needs to be at least twice the highest frequency of the waveform. For how you have defined things, your waveform starts out at zero and goes to BW, so the sampling frequency should be something like fs = 1.2 * 2 * BW;. Commented Jul 21, 2023 at 20:04
• @pej Can you provide the code that produces the figures you expect? As AnonSubmitter85 said, your sample rate is under the required rate to not alias, which is what's happening. There's a discrepancy between what the "right" time-domain and frequency-domain plots show. If you simply increase the sample rate as suggested, you get what is expected. Commented Jul 21, 2023 at 20:44
• @Envidia Thank you for your comments. Even when I set the sampling freq fs = BW, using a built-in Matlab function, I still get the correct spectrogram. Thus, I am confused! Please see my updated code, where I insert a code snippet for generating the expected spectrogram.
– pej
Commented Jul 23, 2023 at 15:55

There are two things you want to change:

1. The frequency sweep you expect is at baseband so do not include the carrier as part of your signal.
2. The sample rate needs to be at least $$2B$$ of the chirp's bandwidth $$B$$. In practical implementations you want an even greater oversampling factor, but for this example, sampling at Nyquist works to show what's going on.

Taking one step at a time we see the following:

The signal no longer includes the carrier, but is still undersampled:

Increasing the sample rate to $$2B$$ we now see:

As I mentioned in my comment, I'm skeptical that the time-domain chirp you showed has the shown spectrogram given the parameters in the original code. If you can provide the code that generated it, that would be great.

## Follow-up

Some of the comments and answers have already addressed where the discrepancy is in what you expect. It comes down to if the signal you're analyzing is real or complex. The MATLAB built-in is using the complex version and that is why you see what you expect. Changing the sinusoud in your code to complex and leaving the sampling frequency at BW gives:

The modified code:

clear all; clc;

f0 = 77e9; % the starting chirp freq
BW = 150e6; % the bandwidth
T_active = (7+1/3)*1e-6; % the chirp duration
slope =  BW/T_active; % the chirp slope

% fs = 2*BW; % the sampling freq
fs = BW; % the sampling freq

samples = floor(T_active*fs); % number of samples
chirps = 1;

%% MY CODE IS HERE
t = linspace(0, chirps*T_active, samples*chirps);
% a_BP = zeros(1,length(t));

% for i=1:length(t)
%     if (0 <= t(i)) && (t(i) <= T_active)
%         a_BP(i) = cos(0*2*pi*f0*t(i) + pi*slope*t(i)^2);
%     else
%         a_BP(i) = 0;
%     end
% end

% a_BP = cos(pi*slope.*t.^2);

% No need for for loop and if-statements
a_BP = exp(1i.*pi*slope.*t.^2);

figure;
subplot(211);
plot(0:1/fs:chirps*T_active-2/fs, real(a_BP));
ylabel('Amplitude (v)');
title('FMCW signal');
axis tight;
subplot(212);
spectrogram(a_BP,32,16,32, fs,'yaxis');
title('FMCW signal spectrogram');


I'd like to update my code, where there are 2 code snippets for generating 2 different figures. The latter is what I expect, however, it relies on a built-in Matlab function, and as you can see, sig is a complex-valued signal.

clear all; clc;

f0 = 77e9; % the starting chirp freq
BW = 150e6; % the bandwidth
T_active = (7+1/3)*1e-6; % the chirp duration
slope =  BW/T_active; % the chirp slope

fs = BW; % I KNOW IT SHOULD BE 2 TIMES OF BW.
%However, let fs = 1 time of BW for now, you will see the second figure yields the correct spectrogram!

samples = floor(T_active*fs); % number of samples
chirps = 1;

%% MY CODE IS HERE
t = linspace(0, chirps*T_active, samples*chirps);
a_BP = zeros(1,length(t));

for i=1:length(t)
if (0 <= t(i)) && (t(i) <= T_active)
a_BP(i) = cos(2*pi*0*t(i) + pi*slope*t(i)^2); % f0=0 for plotting baseband signal
else
a_BP(i) = 0;
end
end

figure;
subplot(211);
plot(0:1/fs:chirps*T_active-2/fs, real(a_BP));
ylabel('Amplitude (v)');
title('FMCW signal');
axis tight;
subplot(212);
spectrogram(a_BP,32,16,32,fs,'yaxis');
title('FMCW signal spectrogram');

%% WHAT I EXPECT. Using a built-in matlab function
waveform = phased.FMCWWaveform('SweepTime', T_active, ...
'SweepBandwidth', BW, ...
'SampleRate', fs, ...
'NumSweeps', 1);

% sig is a complex-valued signal. I dont know how to get this!!!
% What is its mathematical expression?
sig = waveform();

% The following figure is what I expect.
figure;
subplot(211);
plot(0:1/fs:T_active-1/fs, real(sig));
xlabel('Time (s)');
ylabel('Amplitude (v)');
title('FMCW signal');
axis tight;
subplot(212);
spectrogram(sig,32,16,32,fs,'yaxis');
title('FMCW signal spectrogram');


The problem is that even when I set fs=BW, I still get the correct spectrogram using

spectrogram(sig,32,16,32,fs,'yaxis');

• If the signal is complex (and basebanded), then the sampling requirement is that $f_s \geq BW$. Commented Jul 24, 2023 at 17:56

See if the example code below helps you. It also looks like you are calling spectrogram wrong; the fourth argument should be a vector of the frequencies at which to compute the spectrogram. You are passing in the single value of 32, so I have no idea how you ever got the right answer.

Brf = 100e6;      % Bandwidth (Hz)
Tp = 10e-6;       % Waveform duration (s)
fs = 1.2 * Brf;   % Sampling frequency (Hz)

% Sample locations in time from complex version.
t = -Tp/2 : 1/fs : +Tp/2;

% Complex baseband representation of the waveform
% that goes from -Brf/2 to +Brf/2.
s = exp( 1j * pi * (Brf/Tp) * t.^2 );

% Create a real-valued version of the waveform that
% goes from 0 to Brf. Note that we double the sampling
% frequency.
u = 0 : 1/(2*fs) : Tp;
w = cos( pi * (Brf/Tp) * u.^2 );

% Spectrograms for both versions.
spectrogram( s, 32, 16, -fs/2 : 1e5 : fs/2,   fs, 'yaxis' );
spectrogram( w, 32, 16,     0 : 1e5 : fs,   2*fs, 'yaxis' );