Problem with OFDM transmit-receive code

3 views (last 30 days)
John-Davis
John-Davis on 30 Sep 2024
Commented: John-Davis on 1 Oct 2024
Hello, I have a problem with my code. It's a basic ofdm transmitter and receiver implementation making use of BPSK. But when I increase the bps to 4 (i.e 16 QAM) and above, I don't get the desired BER curve. I need help with this Please.
% Parameters
bps = 1; % Bits per symbol (1 for BPSK)
M = 2^bps; % Modulation order
totalBandwidth = 20e6; % Total bandwidth (Hz)
subcarrierSpacing = 15e3; % Subcarrier spacing (Hz)
nFFT = ceil(totalBandwidth / subcarrierSpacing); % Number of FFT bins
EbNoVec = 1:1:10; % Eb/No values (dB)
% Noise power values
noisePower_dBW = -120; % AWGN noise power in dBW
noisePower_W = 10^(noisePower_dBW / 10); % Convert noise power to watts
impulseNoisePower_dBW = -113; % Impulse noise power in dBW
impulseNoisePower_W = 10^(impulseNoisePower_dBW / 10); % Convert impulse noise power to watts
% Initialize BER vectors
berEstAWGN = zeros(size(EbNoVec)); % BER for AWGN only
berEstImp = zeros(size(EbNoVec)); % BER for AWGN + impulse noise
snr_dB = convertSNR(EbNoVec, "ebno", "snr", BitsPerSymbol=bps); % Convert Eb/No to SNR
% Loop over SNR values
for n = 1:length(EbNoVec)
%snr_dB = EbNoVec(n) + 10*log10(bps); % Convert Eb/No to SNR
% Initialize error and bit counters
numErrsAWGN = 0;
numErrsImp = 0;
numBits = 0;
while numErrsAWGN < 200 && numBits < 1e6
% Generate random symbols and bits
txSymbols = randi([0 M-1], nFFT, 1);
txBits = int2bit(txSymbols, bps);
% OFDM Modulation
txGrid = qammod(txSymbols, M, 'UnitAveragePower', true);
txOut = ifft(txGrid, nFFT);
% Calculate signal power
signalPower_dBW = snr_dB(n) + noisePower_dBW;
signalPower_W = 10^(signalPower_dBW / 10);
scalingFactor = sqrt(signalPower_W / mean(abs(txOut).^2));
txOutScaled = txOut * scalingFactor;
% AWGN
noiseSignal_notscaled = randn(size(txOutScaled)) + 1j * randn(size(txOutScaled));
noiseAWGN = sqrt(noisePower_W / 2) * noiseSignal_notscaled;
% Impulse noise (bursty)
impulseNoise = zeros(size(txOutScaled)); % Initialize as zeros
burstPositions = rand(size(txOutScaled)) < 1; % 5% of the time noise bursts occur
impulseNoise(burstPositions) = sqrt(impulseNoisePower_W / 2) * ...
(randn(sum(burstPositions), 1) + 1j * randn(sum(burstPositions), 1));
% Received signal with AWGN only
rxInAWGN = txOutScaled + noiseAWGN;
% Received signal with AWGN + Impulse noise
rxInImp = txOutScaled + noiseAWGN + impulseNoise;
% OFDM Demodulation
rxGridAWGN = fft(rxInAWGN, nFFT);
rxGridImp = fft(rxInImp, nFFT);
% Demodulate symbols
rxSymbolsAWGN = qamdemod(rxGridAWGN, M, 'UnitAveragePower', true);
rxSymbolsImp = qamdemod(rxGridImp, M, 'UnitAveragePower', true);
% Convert symbols to bits
rxBitsAWGN = int2bit(rxSymbolsAWGN, bps);
rxBitsImp = int2bit(rxSymbolsImp, bps);
% Count bit errors
[bitErrorsAWGN, ~] = biterr(txBits, rxBitsAWGN);
[bitErrorsImp, ~] = biterr(txBits, rxBitsImp);
% Update error counters and transmitted bits
numErrsAWGN = numErrsAWGN + bitErrorsAWGN;
numErrsImp = numErrsImp + bitErrorsImp;
numBits = numBits + nFFT * bps;
end
% Calculate BER
berEstAWGN(n) = numErrsAWGN / numBits;
berEstImp(n) = numErrsImp / numBits;
end
% Plot BER results
figure;
semilogy(EbNoVec, berEstAWGN, 'b-o', 'LineWidth', 2); % AWGN only
hold on;
semilogy(EbNoVec, berEstImp, 'r--o', 'LineWidth', 2); % AWGN + Impulse noise
grid on;
title('OFDM BER for BPSK with AWGN and Impulse Noise');
xlabel('Eb/No (dB)');
ylabel('Bit Error Rate (BER)');
legend('AWGN Only', 'AWGN + Impulse Noise');
hold off;

Answers (1)

Suraj Kumar
Suraj Kumar on 1 Oct 2024
Hi John,
Based on my understanding, you are working on transitioning your OFDM system from BPSK to 16-QAM modulation and are facing some challenges.
To resolve the issues, you can refer the following steps:
1. Ensure the modulation order M is calculated based on the bps, i.e. for 16-QAM, bps = 4 and hence M=16.
bps = 4; % Bits per symbol (4 for 16-QAM)
M = 2^bps; % Modulation order
2. Model the noise accurately implementing AWGN and impulse noise, ensuring the noise is bursty.
noiseAWGN = sqrt(noisePower_W / 2) * (randn(size(txOutScaled)) + 1j * randn(size(txOutScaled)));
impulseNoise = zeros(size(txOutScaled));
burstPositions = rand(size(txOutScaled)) < 0.05;
impulseNoise(burstPositions) = sqrt(impulseNoisePower_W / 2) * ...
(randn(sum(burstPositions), 1) + 1j * randn(sum(burstPositions), 1));
rxInAWGN = txOutScaled + noiseAWGN;
rxInImp = txOutScaled + noiseAWGN + impulseNoise;
3. Use the biterrfunction in MATLAB to compute BER and plot the results.
[bitErrorsAWGN, ~] = biterr(txBits, rxBitsAWGN);
[bitErrorsImp, ~] = biterr(txBits, rxBitsImp);
numErrsAWGN = numErrsAWGN + bitErrorsAWGN;
numErrsImp = numErrsImp + bitErrorsImp;
You may refer to the output below for a clearer understanding:
To know more about the convertSNR or biterr function in MATLAB, kindly go through the following documentations:
Happy Coding!
  1 Comment
John-Davis
John-Davis on 1 Oct 2024
I have checked all of these, everything seems to be in order. But I don't know why increasing the bps to 4 and above gives a result different from the result in theory. For instance on the theoretical 16 QAM BER curve, Eb/No value of 8 should correspond to 10^(-1) BER. This is quite different in this case.

Sign in to comment.

Tags

Community Treasure Hunt

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

Start Hunting!