DIY Air Transfer: Transmit and Receive data using GNU Radio and a Microphone
By: Dmitrii Eliuseev
Tags: DIY, Programming, Software Engineering, Electronics, Signal Processing

Photo by Alexey Ruban on Unsplash

Today, no one is surprised by the data transfer via WiFi or Bluetooth. But is it possible to send data directly by air? I will show how the data can be transmitted and received, for which we will create a simple modem implementation using OFDM and GNU Radio.

We will send the data literally by air — a speaker and a microphone will be enough for receiving and transmitting. If somebody is not familiar with GNU Radio, it makes sense to read or watch some tutorials before, like this or that. GNU Radio is cross-platform and can work on Windows, Linux and OSX.

So, our task is to make the simplest modem capable of transmitting data from point A to point B. There are many ways to modulate a digital signal, we will use OFDM — a method widely used in modern communication systems. In OFDM, a digital signal is converted to several parallel subcarriers using Fast Fourier Transform (FFT), which provides high speed and efficient use of the channel. OFDM is used a lot, from digital television and radio to LTE. Our audio channel is much narrower and more strict in terms of parameters so that the speeds will be lower, but basically the essence, in general, does not change. Strictly speaking, OFDM is not designed to transmit data over the air, although for small distances a conventional microphone and speaker will be quite enough.

OFDM in GNU Radio

The minimal connection graph is displayed on the image:

A plain text file is used as the data source (it can contain something like a “Hello World” string), then the data is divided into blocks that are fed to the OFDM Transmitter. OFDM is a rather complicated type of modulation, in the settings of the OFDM encoder we need to specify a lot of not obvious parameters.

A more detailed analysis of the values ​​can be found here. Of course, the parameters of the OFDM Receiver block must match the transmission parameters.

The Channel Model block is used to simulate the communication channel, the QT GUI Frequency Sink block is used to visualize the spectrum. It is also worth paying attention to the low sampling frequency (s/r=2400), this is specially done so that the signal occupies a small band of the spectrum suitable for the audio channel.

Unfortunately, I did not find a built-in unit for displaying received data in GNU Radio, so I have to use UDP. The UDP Sink block is used to output data. A small Python program is used to receive it:

import socket UDP_IP = "127.0.0.1"

UDP_PORT = 40868 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.bind((UDP_IP, UDP_PORT))

sock.settimeout(0.5) while True:

try:

data, addr = sock.recvfrom(128)

print("Msg:", data, 'Hex:', ' '.join('{:02x}'.format(x) for x in data))

except socket.timeout:

pass

This allows us to display the received data in the console, which is quite convenient. Perhaps there is an easier way to output to GNU Radio, if anyone knows, please write in the comments.

If everything was done correctly, we can run GNU Radio and a Python script for receiving, the result should look something like this:

It would seem that the topic can be done? No, all interesting is just beginning.

Go On-Air

In the above example, everything is pretty simple. But there is one “but” — GNU Radio works with the so-called “complex signal”, which is actually a pair of floating-point numbers shifted 90 degrees out of phase. This is convenient for computer processing, but we cannot just take and broadcast a complex number.

And there are two options. Owners of SDR Transmitters (HackRF, LimeSDR, USRP, etc.) may not read further, but simply take a ready-made block for GNU Radio, in which everything is done “out of the box”. But since we are going to transmit a signal using a sound card, we must do the conversion ourselves, for which we will use the approach, described in many DSP-related articles:

Here OFDM is our transmitter, Fc is a carrier frequency, we will set it to 4KHz so that the signal fits into the maximum sensitivity of the speakers and microphone. The block diagram of the graph for transmission is also accordingly complicated:

For ease of testing, I use the WAV File Sink so that the saved file can be recorded and played separately. We can also open the file and view its spectrum, we can make sure that the center frequency is really equal to 4KHz:

Receiving

And finally, the last step: we will create a connection graph for receiving a signal. Here, in fact, everything is the same, only in the reverse order.

We multiply the original signal by the phase-shifted reference signals, then with the help of LPF, we cut off the high-frequency components. The output is a complex signal that can be used for further processing.

The graph for a reception at GNU Radio is as follows:

Here we can see the Audio Source block for receiving data from a sound card, the QT GUI Frequency Sink block is used to visualize the received signal.

For testing, I recorded a WAV file on a smartphone, when I bring it to the microphone of a computer, the decoded text appears on the screen:

Conclusion

As we can see, receiving and transmitting signals using GNU Radio is quite interesting and visual. OFDM has a fairly large number of parameters, those who wish can experiment independently with the size of the FFT block, the number of carriers, the transmission frequency, etc.

Thanks for reading, and I wish you all successful experiments.