DSPRelated.com
Forums

Matlab waveform generation with added AWGN for Deep learning classification.

Started by Samuelson 2 weeks ago2 replieslatest reply 2 weeks ago106 views

Hello,

I am generating WLAN 802.11n/ac waveforms with 4 different modulation schemes (BPSK, QPSK, 16-QAM, 256-QAM) and feed the I/Q data into my Deep learning model to classify. I am also adding AWGN so I get SNR values from -10 dB to 20 dB with a step of 2 dB. 

The results are very surprising, The model is performing very well at pretty low SNR.snr_dataset_v15_acc_64226.png

I tried to add comm.RicianChannel() function and it got only a little bit worse:
snr_dataset_v13_acc_82153.png

Is this possible? I was expecting for the model to have difficulties classifying 802.11n/ac waveforms. This is how I add AWGN:

for j = -10:2:20;

...

noise_ = 10^(-j/10);

noise = randn(size(Data))*sqrt(noise_/2)+1i*randn(size(Data))*sqrt(noise_/2);

Data= Data+ noise;

...

% Also adding a little phase offset and Amplitude imbalance

[ - ]
Reply by weetabixharryMay 3, 2024

You don't show how "Data" is calculated, so it's impossible to be certain, but I suspect your calculation is wrong (unless the signal power happens to be exactly 1).

SNR is defined as the ratio between the signal power and the noise power. In your code, it looks like you want "j" to mean SNR (in dB), because you wrote:

I am also adding AWGN so I get SNR values from -10 dB to 20 dB with a step of 2 dB.

In my opinion, it would be better to rename "j" to something more descriptive like "snr_db". Nonetheless, we're saying that j = 10log10(signal_power / noise_power).

It looks like you want "noise_" to mean noise power. Therefore, a much better variable name would be "noise_power". Nonetheless, we can rearrange j = 10log10(signal_power / noise_) to get:

noise_ = signal_power * 10^(-j/10)

Your calculation doesn't appear to account for the signal power.

[ - ]
Reply by SamuelsonMay 3, 2024

Hello and thanks for the answer! I actually saw my awgn adding method in a different post on this forum, wanted to switch from the awgn() function because I got even more accurate results with it. Here is my original code on generating 802.11n/ac scheme with 16-QAM modulation scheme:


clear variables

close all

clc

%% Generating Ricean channel

fs = 3.84e6;% Sample rate in Hz

pathDelays = [0 200 800 1200 2300 3700]*1e-9; % in seconds

avgPathGains = [0 -0.9 -4.9 -8 -7.8 -23.9];% dB

kfact = 10;% Rician K-factor

fD = 50;% Max Doppler shift in Hz

ricianChan = comm.RicianChannel( ...

SampleRate=fs, ...

PathDelays=pathDelays, ...

AveragePathGains=avgPathGains, ...

KFactor=kfact, ...

MaximumDopplerShift=fD);

%% Generating 802.11n/ac (OFDM) waveform

% 802.11n/ac (OFDM) configuration

vhtCfg = wlanVHTConfig('ChannelBandwidth', 'CBW80', ... % CBW80

'NumUsers', 1, ...

'NumTransmitAntennas', 1, ...

'NumSpaceTimeStreams', 1, ...

'SpatialMapping', 'Direct', ...

'STBC', false, ...

'MCS', 4, ... % setting 16-QAM

'ChannelCoding', 'BCC', ...

'APEPLength', 1024, ...

'GuardInterval', 'Long', ...

'GroupID', 63, ...

'PartialAID', 275);


numPackets = 1500; % Intended number of packets

desired_Length = 256; % Desired length of each packet in samples

%% Impairments parameters

SNRs = -10:2:20; % AWGN values

phase_offsets = [-pi/18, -pi/36, 0, pi/36, pi/18];% Possible phase offsets that can occur

amplitude_imbalances = [-10, -5, 0, 5, 10];% In [%]

amplitude_imbalances = 20*log10(1+amplitude_imbalances*0.01); % Converting to dB

for j = SNRs

waveform = [];

for i = 1:numPackets

% input bit source:

in = randi([0, 1], 100, 1);

packet_Waveform = wlanWaveformGenerator(in, vhtCfg, ...

'NumPackets', 1, ...

'IdleTime', 0, ...

'OversamplingFactor', 1, ...

'ScramblerInitialization', 93, ...

'WindowTransitionTime', 1e-07);

% Apply the Rician channel model to the waveform

packet_Waveform = ricianChan(packet_Waveform);

%% Downsample the waveform

%Definition of downsampling factor

downsamplingFactor = max(1, floor(length(packet_Waveform) / desired_Length));

downsampled_Waveform = downsample(packet_Waveform, downsamplingFactor);

downsampled_Waveform = downsampled_Waveform(1:min(desired_Length, end));

%% Adding Impairments

% Adding awgn

noise_ = 10^(-j/10);

noise = randn(size(downsampled_Waveform))*sqrt(noise_/2)+1i*randn(size(downsampled_Waveform))*sqrt(noise_/2);

downsampled_Waveform = downsampled_Waveform + noise;

% Adding Phase offset

downsampled_Waveform = downsampled_Waveform * exp(1i*phase_offsets(randi(numel(phase_offsets))));

% Adding IQ imbalance - Amplitude imbalance

downsampled_Waveform = iqimbal(downsampled_Waveform, amplitude_imbalances(randi(numel(amplitude_imbalances))));

%% Adding packets to waveform

waveform = [waveform; downsampled_Waveform];% Append packet's waveform

end

%% Visualize

constel = comm.ConstellationDiagram('ColorFading', true, ...

'ShowTrajectory', 0, ...

'ShowReferenceConstellation', false);

segmentIndex = 1; % Change this to visualize different segments

constel(waveform((segmentIndex-1)*desired_Length+1:segmentIndex*desired_Length));

constel.Title = sprintf('Constellation diagram of 802.11n/ac (QAM16) %d dB',j);

%% Save Waveform Data

waveStruct.waveform = waveform

filename = sprintf('WLANnacQAM16/WLANnacQAM16_%ddB',j);

save(filename,'waveStruct')


end



I'm generating packets but then downsampling them in this case to 256. In total I generate 1500 packets for every SNR value + randomly inserting different phase offsets and amplitude imbalances and also adding rician before. Question: What is the way to generate signal_power?