Transferring a text file over the air with LimeSDR mini

Help us grow. Share with your friends!

We have seen the LimeSDR mini several times on this blog. So far, we have only seen how it can generate analog modulation to transmit voice and what not. Being an SDR capable to transmit practically anything, we can even transmit binary data. Speaking of binary, we will have to jump into digital modulation techniques. In this article, I will demonstrate how I used the LimeSDR mini to transmit a small CSV text file over the air. For this experiment, I will use three things. One of them is obviously the LimeSDR mini. The second one is our friend GNURadio and the third being an RTL-SDR to receive it on the other side.

The transmitter setup

The setup will be quite simple and I won’t go into too many technical details. My choice of modulation will be Binary Phase shift Keying (BPSK) and my GNU Radio flow graph will tell you how I did it.

bpsk tx limesdr

Transmit side flow graph

Here, we start with the File source that provides an output in byte format. The ‘Packet Encoder’ accepts the byte and encodes the data in ‘1 bit’ per symbol format. Further, the constellation modulator maps the bit to corresponding phase shifts known as symbols. In case of BPSK modulation, the phase shifts between two symbols are going to be \(180^o\) apart. If we were to use QPSK modulation, the packet encoder would have to provide ‘2 bits’ per symbol. Correspondingly, the Constellation modulator would map the symbols \(90^o\) apart. Remember, the modulated bits are simply mapped to their respective phases represented as either \(1 and -1[latex].

[caption id="attachment_6393" align="alignnone" width="800"] Phase vs. symbol. This is what we call a constellation diagram.[/caption]

I am sure you must have seen the QPSK constellation while downloading Meteor-M2 images with your RTL-SDR setup.

A little math

To understand this process better, imagine that you have a sine wave. Multiplying it with [latex]+1\) will result in,

\(+1 \times sin(2\pi ft) = sin(2\pi ft)\)

Whereas, multiplying it with \(-1\) will result in,

\(-1 \times sin(2\pi ft) = -sin(2\pi ft)\)

The negative sign on the sine indicates a \(180^o\) phase shift. Correspondingly, we would see the following waveform.

bpsk with limesdr

BPSK waveform

The phase shift or rather the symbols now need to be mounted on a carrier. To do that, we multiply the symbols with a 20kHz sine wave. It could be any frequency in the nyquist range. After doing do, we will change the sampling rate to match the sampling rate of the LimeSDR DAC. The rational resampler block interpolates the modulated signal by 20 times to achieve the LimeSDR sampling rate of 2.048MHz. I chose the sampling rate of the LimeSDR to be an integer multiple of the base band sampling rate to reduce the complications. Notice that the LimeSDR sink is set to up-conversion mode. We will be transmitting the data on 435MHz.

The receiver setup

On the receiving end, I am using an RTL-SDR with a sampling rate set to 1.024MHz. The gains are set to automatic and the RF value set to 435MHz. Again, on the receiving side, we decimate the data stream from RTL-SDR. Further, multiply it with a 20kHz source to center the constellation around DC. The received data could also contain unwanted signals which need to be filtered out. The low pass filter takes care of that. Furthermore, the polyphase clock sync block synchronizes the sampling time such that we get the maximum possible signal to noise ratio. The costas loop is meant for fine frequency correction which is necessary for correct demodulation of digital signals. An uncorrected frequency will result in the phase rotating constantly leading to no demodulation happening altogether. The costas loop basically locks onto the received signal’s carrier and outputs a good demodulated constellation.

bpsk limesdr file transfer

The receiver flowgraph for BPSK reception

After the Costas Loop, you can see the LMS DD Equalizer block. What this does is basically tries to compensate the multipath effects. In case you don’t know, whenever we transmit a signal, it will travel wherever it can and even bounce of multiple walls, objects, moving vehicles and so on before finally arriving at the receiving antenna. Correspondingly, all these paths vary in distance resulting in a shifted versions of the signal arriving at the receiver. The Equalizer block tries to minimize the effect of multipath propagation.

Furthermore, we demodulate the carrier and end up with bits. Remember, we have enabled differential encoding in the transmitter and we need to decode it to retrieve the original bit pattern. The differential decoder does that job and passes the data further to the packet decoder and then to the File sink. To elaborate, the File Sink block requires the data to be 8 bits in size. The Packet decoder block packs the 1 bit per symbol into 8 bits before sending it to the File sink.

If you wish to read more about this in detail, you can follow this link to GNURadio official guide.


While transmitting the file, the receiver often drops the initial few bytes of data. This happens because the receiver algorithms, especially the clock sync and the costas loop require time to converge. For testing the setup, I chose a small CSV file and transmitted it. Except for losing the initial couple of bytes, the transmission was flawless.

BPSK constellation while receiving on RTL SDR

I used an online tool to compare the transmitted and received files and here is the result below. We are able to receive correct data over the air and the comparison of two files prove it.

limesdr file transfer

Transmitted file on the right and received file on the left. A 99% match.

When trying this with QPSK, the packet encoder does not work correctly every time. It took me several tries to make it work. Apparently, the initial convergence time plays a significant role in QPSK transmission especially when you are using the packet encoder block which is known to be flawed. Perhaps, I will have to find an alternative to that. Finally, this is the link to the GRC file which contains both, the TX as well as the RX blocks. Simply enable or disable them as per your need.

If you don’t have a LimeSDR mini, you could try this setup on a PlutoSDR or even HackRF one. In case you have neither of those, go ahead and buy one from Aliexpress.

HackRF One

LimeSDR Mini


Incoming search terms:


Salil is an electronics enthusiast working on various RF and Microwave systems. In his free time he writes on the blog, talks over ham radio or builds circuits. He has Yaesu FT2900R VHF transceiver, FT450D HF transceiver and a TYT UV8000E Handheld transceiver.

You may also like...

19 Responses

  1. Neha says:

    Gr8 Salil….

  2. Bindu says:

    Hii.. This is bindu.. can i use the same code with 2 limesdr by changing the rtl-sdr source to limesuite source

  3. Bindu says:

    But i’m not receiving any data

  4. Samet says:

    Hi Dear,

    I downloaded your .grc file and I use HackRfone and Rtlsdr. It is working well but, it is not writing from input.txt file to output.txt file. Do you have any suggestion ?

  5. Grace says:

    Thank you for the detailed write-up! I’ve added a QT GUI Constellation Sink block right after the Rational Resampler and it’s showing me dots forming rounds and rounds in the centre. I wanted to see the constellation of BPSK modulation before transmission. May I know if that’s the correct way to do it?

  6. David John says:


    I tried your flowgraph with a B200 and a B210. There is no output to the receiver file. I am getting four clusters at the RX end constellation. Any suggestions to fix it?

  7. David John says:


    I just wanted to update my previous comment. I am getting the BPSK constellation in the plot after the LMS DD Equalizer, but I am not getting any written into file in the File sink. Any suggestions to fix this? What could be going wrong?

  8. David John says:

    Hi Salil,

    Any upate to my previous comment. I got the BPSK working. I works really fine. I am now trying to get the QPSK to work. Have you ever tried it before? I made some changes to the flowgraph, I am getting the QPSK constellation after the equalizer, but nothing gets written into to the file in the file sink. Any suggestion to fix it? I would really appreciate it.

  9. David John says:

    Hi Salil,

    Were you able to successfully transmit and receive the text file using QPSK? I have been trying to do it, but the packet encoder does not give out any output. I’m getting a clean QPSK constellation in the constellation plot. Any suggestions to fix it? How did you get it working? I would really appreciate your help. I’m kinda desperate to get it working.

    • nuclearrambo says:

      Hi David,
      I did try with QPSK but the GNU Radio’s packet encoded gave problems. The receiver did generate the QPSK constellation very well but I wasn’t able to get the bits written to file.

  10. Marut says:

    Hi Salil,

    I try to do it from limesdr to limesdr. It work very well but I have some problem. When I config repeat in file source = No I can’t receive anything. Can you help or advice me how to fix it ?
    2 How to fix number of repeat?

  11. Liam Daniel says:


    I have been looking at your code and I have some quick questions. Would it be possible to discuss it with you over email?

  12. bahari says:

    Hi salil, can I change a transmit and receive frequency to 1GHz?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.