High BER for QAM

17 ビュー (過去 30 日間)
Muath
Muath 2024 年 9 月 8 日
編集済み: Muath 2024 年 9 月 9 日
I am facing a problem here. I tried to implement a simulation for QAM from the scratch without using qammod, but the error rate seems to be so high, to the point I think the received symbols is just random. Can someone help with the code:
% 16-QAM Modulation and Demodulation with carrier 1 GHz.
clear all
close all
clc
% QAM Parameters:
M = 16; % Order of Modulation "16-QAM"
bits_symbol = log2(M); % Number of Bits per Symbol
fc = 1e9; % Carrier frequency
fs = 10*fc; % Sampling rate at least 4 to 10 times fc
num_symbol = 250; % Number of Symbols to be transmitted
t = (0:1/fs:num_symbol*(1/fs)-1/fs); % Time vector
% Random Input Generation:
input = randi([0,1], num_symbol, bits_symbol);
% Constellation Mapping:
constellation = (-sqrt(M)+1:2:sqrt(M)-1); %Constellation [-3, -1, 1, 3]
% Map the symbols:
I = constellation(bi2de(input(:,1:bits_symbol/2),'left-msb')+1); % In-phase component
Q = constellation(bi2de(input(:, bits_symbol/2+1:end),'left-msb')+1); % Quadrature component
% Modulated signal:
Tx = I .* cos(2*pi*fc*t) + Q .* sin(2*pi*fc*t);
% Tx = awgn(Tx, 20, 'measured'); % Adding noise for testing
% Demodulation:
Rx_I = 2 * Tx .* cos(2*pi*fc*t); % In-phase demodulation
Rx_Q = 2 * Tx .* sin(2*pi*fc*t); % Quadrature demodulation
% Lowpass filter:
Rx_I_f = lowpass(Rx_I, fc/2, fs);
Rx_Q_f = lowpass(Rx_Q, fc/2, fs);
% Symbol decision (finding the closest constellation point):
I_org = zeros(num_symbol, 1);
Q_org = zeros(num_symbol, 1);
for x = 1:num_symbol
[~, I_org(x)] = min(abs(Rx_I_f(x) - constellation'));
[~, Q_org(x)] = min(abs(Rx_Q_f(x) - constellation'));
end
% Combine I_org and Q_org to get the original symbols:
output = [de2bi(I_org-1, bits_symbol/2, 'left-msb'), de2bi(Q_org-1, bits_symbol/2, 'left-msb')];
% Calculate the Bit Error Rate (BER):
[~, BER] = biterr(input, output);
fprintf('Bit Error Rate (BER): %f\n', BER);

採用された回答

Shashi Kiran
Shashi Kiran 2024 年 9 月 9 日
I understand that you are experiencing poor performance with the Bit Error Rate (BER) while implementing the 16-QAM modulation scheme.
After analysing your code, here are my observations and suggestions for improvement.
  • The time vector should cover the entire duration of all symbols, not just one symbol. You can correct it in the following way
symbol_duration = 1 / fc; % Duration of one symbol
t = (0:1/fs:(num_symbols * symbol_duration) - 1/fs);
  • The In-phase and Quadrature components should be applied individually to each symbol. I and Q should be applied to each symbol separately.
samples_per_symbol = fs * symbol_duration;
Tx = zeros(1, length(t));
for k = 1:num_symbols
start_index = (k - 1) * samples_per_symbol + 1;
end_index = k * samples_per_symbol;
Tx(start_index:end_index) = ...
I(k) * cos(2 * pi * fc * t(start_index:end_index)) + ...
Q(k) * sin(2 * pi * fc * t(start_index:end_index));
end
  • The demodulated values are sampled incorrectly, as they are directly indexed by x, which does not account for the samples per symbol.
for k = 1:num_symbols
sample_index = round((k - 0.5) * samples_per_symbol);
[~, I_org(k)] = min(abs(Rx_I_f(sample_index) - constellation'));
[~, Q_org(k)] = min(abs(Rx_Q_f(sample_index) - constellation'));
end
With these corrections, you can achieve the desired Bit Error Rate (BER) for 16-QAM, which means a BER of zero in the absence of noise and a waterfall curve as the Signal-to-Noise Ratio (SNR) increases.
Here is the full code after corrections with SNR of 8dB.
clear all
close all
clc
% QAM Parameters:
M = 16; % Order of Modulation "16-QAM"
bits_per_symbol = log2(M); % Number of Bits per Symbol
fc = 1e9; % Carrier frequency
fs = 10 * fc; % Sampling rate at least 4 to 10 times fc
num_symbols = 250; % Number of Symbols to be transmitted
symbol_duration = 1 / fc; % Duration of one symbol
samples_per_symbol = fs * symbol_duration; % Number of samples per symbol
t = (0:1/fs:(num_symbols * symbol_duration) - 1/fs); % Time vector
% Random Input Generation:
input = randi([0, 1], num_symbols, bits_per_symbol);
% Constellation Mapping:
constellation = (-sqrt(M) + 1:2:sqrt(M) - 1); % Constellation [-3, -1, 1, 3]
% Map the symbols:
I = constellation(bi2de(input(:, 1:bits_per_symbol/2), 'left-msb') + 1); % In-phase component
Q = constellation(bi2de(input(:, bits_per_symbol/2+1:end), 'left-msb') + 1); % Quadrature component
% Modulated signal:
Tx = zeros(1, length(t));
for k = 1:num_symbols
start_index = (k - 1) * samples_per_symbol + 1; % Start index for the k-th symbol
end_index = k * samples_per_symbol; % End index for the k-th symbol
Tx(start_index:end_index) = ...
I(k) * cos(2 * pi * fc * t(start_index:end_index)) + ...
Q(k) * sin(2 * pi * fc * t(start_index:end_index));
end
Tx = awgn(Tx, 8, 'measured'); % Uncomment to add noise for testing
% Demodulation:
Rx_I = 2 * Tx .* cos(2 * pi * fc * t); % In-phase demodulation
Rx_Q = 2 * Tx .* sin(2 * pi * fc * t); % Quadrature demodulation
% Lowpass filter:
Rx_I_f = lowpass(Rx_I, fc / 2, fs);
Rx_Q_f = lowpass(Rx_Q, fc / 2, fs);
% Symbol decision (finding the closest constellation point):
I_org = zeros(num_symbols, 1);
Q_org = zeros(num_symbols, 1);
for k = 1:num_symbols
sample_index = round((k - 0.5) * samples_per_symbol); % Sample in the middle of the symbol period
[~, I_org(k)] = min(abs(Rx_I_f(sample_index) - constellation'));
[~, Q_org(k)] = min(abs(Rx_Q_f(sample_index) - constellation'));
end
% Combine I_org and Q_org to get the original symbols:
output = [de2bi(I_org - 1, bits_per_symbol/2, 'left-msb'), de2bi(Q_org - 1, bits_per_symbol/2, 'left-msb')];
% Calculate the Bit Error Rate (BER):
[~, BER] = biterr(input, output);
fprintf('Bit Error Rate (BER): %f\n', BER);
Bit Error Rate (BER): 0.021000
  1 件のコメント
Muath
Muath 2024 年 9 月 9 日
編集済み: Muath 2024 年 9 月 9 日
The code works flawlessly. Thanks a lot!

サインインしてコメントする。

その他の回答 (1 件)

Ruchika Parag
Ruchika Parag 2024 年 9 月 9 日
Hi Muath, when developing a QAM (Quadrature Amplitude Modulation) simulation from scratch, it's crucial to focus on several key elements to ensure the modulation and demodulation processes are correctly executed. To achieve lower error rate, here are a few things that can be modified in your code :
  1. Increased SNR: The SNR can been set to 15 dB. You can adjust this value further based on your requirements. A higher SNR generally results in a lower BER.
  2. AWGN Noise Addition: The noise is added to the transmitted signal to simulate a more realistic communication channel.
  3. Improved Lowpass Filtering: The lowpass filter is retained but ensure that it effectively removes noise while preserving the signal.
Following is the modified code to achieve lower BER :
clear all;
close all;
clc;
% QAM Parameters:
M = 16; % Order of Modulation "16-QAM"
bits_symbol = log2(M); % Number of Bits per Symbol
fc = 1e9; % Carrier frequency
fs = 10 * fc; % Sampling rate at least 4 to 10 times fc
num_symbol = 250; % Number of Symbols to be transmitted
t = (0:1/fs:num_symbol*(1/fs)-1/fs); % Time vector
% Random Input Generation:
input = randi([0, 1], num_symbol, bits_symbol);
% Constellation Mapping:
constellation = (-3:2:3) + 1i * (-3:2:3)'; % Create a 4x4 grid for 16-QAM
constellation = constellation(:); % Reshape to a column vector
% Map the symbols:
I_bits = input(:, 1:bits_symbol/2); % In-phase bits
Q_bits = input(:, bits_symbol/2+1:end); % Quadrature bits
I_decimal = bi2de(I_bits, 'left-msb'); % Convert in-phase bits to decimal
Q_decimal = bi2de(Q_bits, 'left-msb'); % Convert quadrature bits to decimal
I = constellation(I_decimal + 1); % In-phase component
Q = constellation(Q_decimal + 1); % Quadrature component
% Modulated signal:
Tx = I .* cos(2 * pi * fc * t) - Q .* sin(2 * pi * fc * t);
% Add AWGN noise
SNR_dB = 15; % Increase SNR to reduce BER
Tx_power = mean(abs(Tx).^2);
noise_power = Tx_power / (10^(SNR_dB/10));
noise = sqrt(noise_power) * randn(size(Tx)); % Additive white Gaussian noise
Rx = Tx + noise; % Received signal
% Demodulation:
Rx_I = 2 * Rx .* cos(2 * pi * fc * t); % In-phase demodulation
Rx_Q = 2 * Rx .* sin(2 * pi * fc * t); % Quadrature demodulation
% Lowpass filter:
Rx_I_f = lowpass(Rx_I, fc/2, fs);
Rx_Q_f = lowpass(Rx_Q, fc/2, fs);
% Symbol decision (finding the closest constellation point):
I_org = zeros(num_symbol, 1);
Q_org = zeros(num_symbol, 1);
for x = 1:num_symbol
[~, I_org(x)] = min(abs(Rx_I_f(x) - real(constellation)));
[~, Q_org(x)] = min(abs(Rx_Q_f(x) - imag(constellation)));
end
% Combine I_org and Q_org to get the original symbols:
output_I = de2bi(I_org - 1, bits_symbol/2, 'left-msb'); % Convert in-phase to bits
output_Q = de2bi(Q_org - 1, bits_symbol/2, 'left-msb'); % Convert quadrature to bits
output = [output_I, output_Q]; % Combine in-phase and quadrature bits
% Calculate the Bit Error Rate (BER):
[~, BER] = biterr(input, output);
fprintf('Bit Error Rate (BER): %f\n', BER);
Bit Error Rate (BER): 0.480000
By increasing the SNR and ensuring that your modulation and demodulation processes are correctly implemented, you should see a reduction in the Bit Error Rate.
  1 件のコメント
Muath
Muath 2024 年 9 月 9 日
Hi Ruchika,
Thank you for your feedback. I considered removing the noise first and tried to implement the transmitting and receiving part correctly. That is why the noise is commented out in my code. So, the noise part is irrelevant for now.
Focusing on the implementation, I reviewed your modification to the code. However, I couldn’t understand the following part. You converted the constellation mapping to a 16x1 matrix which has the values:
-3-3j, -3-1j,…, 3+3j
which is fine. But when you divide the symbol between I and Q, it means 2 bits for each. The possible values for 2 bits are 0, 1, 2, 3, and by doing the adjustment to be used as an index, we add 1 which will make them 1, 2, 3, 4.
This means it will only use the first four values in the constellation map:
-3 - 3j, -3 - 1j, -3 + 1j, -3 + 3j
So, what is the point of having 16 mapping points when you are only going to use four of them? Nonetheless, I ran the code and it resulted in an error most of the time, exactly at line 58:
output_I = de2bi(I_org - 1, bits_symbol/2, 'left-msb'); % Convert in-phase to bits
And when it ran properly, the BER was high, similar to the run result you have shown above.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeModulation についてさらに検索

製品


リリース

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by