PSK31 Demodulation (Kurt & Michael): Difference between revisions

From Class Wiki
Jump to navigation Jump to search
Line 17: Line 17:
# We read in the signal from a wav file and generate utility variables and matrices.
# We read in the signal from a wav file and generate utility variables and matrices.
# We run the signal through an FFT and take an average over the range of the FFT spike to obtain a carrier frequency guess.
# We run the signal through an FFT and take an average over the range of the FFT spike to obtain a carrier frequency guess.
# A PID controller was implemented to help offset the fact that a carrier frequency derived from the FFT produces an inaccurate carrier frequency. An offset in the carrier frequency causes the constellation diagram to rotate in a circle. The PID tries to compensate for this by adding to or subtracting from the phase of the signal while trying to drive the Q-component of the signal to zero. The feedback loop is described by the code below.
# PID stuff '''''(Do you want to go into detail here Kurt?)'''''
% PID controller constants
Kp = 25;
Ki = 50;
Kd = 1;
output = zeros(1, length(v)); % Init
setpoint = 0; % Sets the feedback point to control to.
previous_error = 0; % In this case, you want to set yt to 0.
integral = 0;
xt_filt = [];
yt_filt = [];
for k=51:length(v)
xt(k) = v(k)*cos(2*pi*u_fc*t(k)+output(k));
yt(k) = v(k)*sin(2*pi*u_fc*t(k)+output(k));
xt_filt(k:-1:k-50) = filter(b, a, xt(k:-1:k-50));
yt_filt(k:-1:k-50) = filter(b, a, yt(k:-1:k-50));
if(sign(xt(k)) == sign(yt(k)))
error = setpoint - yt_filt(k);
else
error = setpoint + yt_filt(k);
end
% PID Feedback Controller compensates for inaccurate fc guess.
% error = setpoint - yt_filt(k);
integral = integral + error*10;
derivative = (error - previous_error)/10;
output(k+1) = Kp*error + Ki*integral + Kd*derivative;
previous_error = error;
end
# We multiply the signal with a cosine wave at our guess frequency. This splits the signal into two parts: a high frequency component (with frequency equal to the sum of the ''actual'' carrier frequency and our ''guess'' frequency) and a low frequency component (due to the difference of the two frequencies).
# We multiply the signal with a cosine wave at our guess frequency. This splits the signal into two parts: a high frequency component (with frequency equal to the sum of the ''actual'' carrier frequency and our ''guess'' frequency) and a low frequency component (due to the difference of the two frequencies).
# We filter the multiplied signal through a butterworth filter with a 75Hz cutoff frequency to remove the high frequency component.
# We filter the multiplied signal through a butterworth filter with a 75Hz cutoff frequency to remove the high frequency component.

Revision as of 21:10, 12 December 2012

Project Description

The goal of this project is to design and code a Matlab script that will encode and decode a PSK31 signal including signals with noise. The receiver should be able to read in signals (as a wav file) from other sources as well.


PSK31 is a audible text encoding that can be sent over the air by amateur radio operators. A computer's sound card can be used to send and receive the signal since the signal is audible. For more information regarding PSK31 see the Wikipedia article.[1]

Our Approach

Code Overview

Transmitter

Our code creates a PSK31 signal given an input carrier frequency and message. For testing our receiver code, the transmitter is setup to generate a random carrier frequency and phase. It also adds random noise to the signal before writing it to a wav file.

Receiver

Our receiver is split into several steps:

  1. We read in the signal from a wav file and generate utility variables and matrices.
  2. We run the signal through an FFT and take an average over the range of the FFT spike to obtain a carrier frequency guess.
  3. A PID controller was implemented to help offset the fact that a carrier frequency derived from the FFT produces an inaccurate carrier frequency. An offset in the carrier frequency causes the constellation diagram to rotate in a circle. The PID tries to compensate for this by adding to or subtracting from the phase of the signal while trying to drive the Q-component of the signal to zero. The feedback loop is described by the code below.
% PID controller constants
Kp = 25;
Ki = 50;
Kd = 1;
output = zeros(1, length(v));    % Init
setpoint = 0;                    % Sets the feedback point to control to.
previous_error = 0;                % In this case, you want to set yt to 0.
integral = 0;
xt_filt = [];
yt_filt = [];
for k=51:length(v)
   xt(k) = v(k)*cos(2*pi*u_fc*t(k)+output(k));
   yt(k) = v(k)*sin(2*pi*u_fc*t(k)+output(k));
  
   xt_filt(k:-1:k-50) = filter(b, a, xt(k:-1:k-50));
   yt_filt(k:-1:k-50) = filter(b, a, yt(k:-1:k-50));
  
   if(sign(xt(k)) == sign(yt(k)))
       error = setpoint - yt_filt(k);
   else
       error = setpoint + yt_filt(k);
   end
  
   % PID Feedback Controller compensates for inaccurate fc guess.
   % error = setpoint - yt_filt(k);
   integral = integral + error*10;
   derivative = (error - previous_error)/10;
   output(k+1) = Kp*error + Ki*integral + Kd*derivative;
   previous_error = error;
end
  1. We multiply the signal with a cosine wave at our guess frequency. This splits the signal into two parts: a high frequency component (with frequency equal to the sum of the actual carrier frequency and our guess frequency) and a low frequency component (due to the difference of the two frequencies).
  2. We filter the multiplied signal through a butterworth filter with a 75Hz cutoff frequency to remove the high frequency component.
  3. We mark the locations where the filtered signal changes sign

Code

Results/Problems