PlutoSDR Wireless Communication System: QPSK Image Transmission

PlutoSDR Wireless Communication System: QPSK Image Transmission

PlutoSDR Wireless Communication: QPSK Image Transmission System

A complete hands‑on guide to building a wireless image transmission system using PlutoSDR and QPSK modulation — from UI design to transmitter/receiver implementation, frame synchronization, and image recovery.

System Overview & UI Design

A custom UI interface controls the image transmission system. The interface displays the system name and adjustable parameters:

  • Image selection: Dropdown menu for choosing the image file to transmit
  • Receiver gain: Adjustable for optimal signal detection
  • Carrier frequency: Configurable center frequency
  • Start transmission: Button to initiate the wireless transfer

(Refer to the original article for the UI screenshot)

Launch the interface by running GUI.m in MATLAB.

Transmitter & Receiver Configuration

The following code configures the basic PlutoSDR parameters:

fprintf('Preparing transmission, please wait...\n');
deviceNameSDR = 'Pluto';  % SDR device
Fs = 500e3;               % Sampling rate (Hz)
zc1_len = 500;            % ZC sequence length
zc_seq1 = creat_cazac(zc1_len);

% Transmitter configuration
sdrTransmitter = sdrtx(deviceNameSDR);
sdrTransmitter.RadioID = 'usb:0';
sdrTransmitter.BasebandSampleRate = Fs;
sdrTransmitter.CenterFrequency = sim_options.carrier * 1e9;
sdrTransmitter.ShowAdvancedProperties = true;
sdrTransmitter.Gain = 0;

% Receiver configuration
sdrReceiver = sdrrx(deviceNameSDR);
sdrReceiver.RadioID = 'usb:0';
sdrReceiver.BasebandSampleRate = sdrTransmitter.BasebandSampleRate;
sdrReceiver.CenterFrequency = sdrTransmitter.CenterFrequency;
sdrReceiver.GainSource = 'Manual';
sdrReceiver.Gain = sim_options.gain;
sdrReceiver.OutputDataType = 'double';
sdrReceiver.SamplesPerFrame = 200000;
Key parameters: Center frequency is read from the UI; transmitter gain is fixed; receiver gain is UI‑adjustable; output data type is double; samples per frame should be tuned based on your system requirements.

Transmitter Processing Chain

% Generate data bits from image
temp_bits = tx_bits((1:tx_len) + (nn-1)*tx_len);

% QPSK modulation
mod_syms = tx_modulate(temp_bits);

% Pulse shaping filter (root raised cosine)
mod_syms1 = usercos(mod_syms, 8, 21);
symbol_len = length(mod_syms1);

% Add preamble sequence
signal = [zc_seq1 zc_seq1 mod_syms1];

Processing steps:

  1. Bit generation: Extract image bits for transmission
  2. QPSK modulation: Phase changes represent information bits — the example uses QPSK, but higher‑order modulations (up to 128QAM) have been tested successfully on a single PlutoSDR. Modulation type can be made UI‑selectable.
  3. Pulse shaping: A root raised cosine filter reduces intersymbol interference (ISI).

(Refer to the original article for the waveform plot)
  1. Preamble insertion: A Constant Amplitude Zero Auto-Correlation (CAZAC) sequence is added before the data. CAZAC sequences have excellent autocorrelation properties, enabling reliable frame start detection at the receiver — critical because the receiver cannot distinguish noise from signal without a known reference.

(Refer to the original article for the transmitted signal plot)

Receiver Processing Chain

data = sdrReceiver();
rx_signal = data;

% Power normalization
rx_signal = rx_signal ./ sqrt(mean(abs(rx_signal).^2));

% Frame synchronization using preamble
data1 = sync_signal(rx_signal, search_len, zc_seq1, zc1_len, thread, symbol_len);

% Frequency offset estimation and correction
rx_equ = freq_equ(data1, zc1_len, Fs);

% Matched filtering
rx_data_pre = usercos_de(rx_equ(2*length(zc_seq1)+1:end), 8, 21);

% Carrier synchronization
rx_data_pre = carrier_sync(rx_data_pre);

% QPSK demodulation
rx_demodulate_bit = rx_demodulate(rx_data_pre);
de_bits = rx_demodulate_bit(1:tx_len);

Receiver processing steps:

  1. Signal acquisition: Capture the received signal from PlutoSDR
  2. Power normalization: Scale signal power for consistent processing
  3. Frame synchronization: Use the CAZAC preamble's autocorrelation property to locate the exact start of the data frame

(Refer to the original article for the received signal plot)

(Refer to the original article for the synchronization plot)
  1. Frequency offset estimation and compensation
  2. Matched filtering: Process the extracted data symbols through the matched filter
  3. Carrier synchronization

(Refer to the original article for the constellation diagram)
  1. QPSK demodulation to recover the original bitstream
  2. Image reconstruction from the recovered bits

(Refer to the original article for the received image)

UI Features & Visualization

The UI includes buttons that display intermediate signal waveforms at each processing stage — pulse shaping, frame synchronization, frequency offset correction, and constellation diagrams. These visualizations help in understanding the system behavior.


(Refer to the original article for the success dialog)
System capabilities: The PlutoSDR has been tested with modulations up to 128QAM. The UI can be extended to support selectable modulation schemes.

Project Files & Resources

The complete project files, including MATLAB code, UI design, and documentation, are available upon request.

Hardware Support

This system is designed for the PlutoSDR platform. For a ready‑to‑use PlutoSDR with full frequency support (70MHz–6GHz) and Gigabit Ethernet:



Previous post

Leave a comment