DVB-S2 transmission and reception with SDR

Last updated: May 31, 2019

The DVB-S2 standard for digital satellite video broadcast is extremely well engineered. You would be hard pressed to find a more refined standard to exchange lots of data with minimal errors. With many good features like multiple modulation modes and multiple code rates (using the very powerful LDPC type of FEC code) the standard is quite a beast. Since it has been implemented and used by open-source and amateur radio communities, it is possible to transmit video to yourself using software defined radios. How cool is that?

What you need:

I’m sure it can work on other versions, but at least this establishes one case. The forum post for markro92’s software is here:

and the actual software is here:

http://v.1337team.tk/dvb-s_gui_amsat.zip

Just unzip the folder and run it. Easy! ( I first used SDR# to listen to FM radio, and I also viewed the DVB-S2 signal on the waterfall. This probably set up the windows driver for RTLSDR)

Getting GNU radio working is often less easy, but just try apt install gnuradio. I’ll assume it’s working for you, it’s really a separate issue. Getting the PLUTO SDR drivers is also a separate issue, and the guide on the wiki worked for me. With the basic elements ready, lets set up GNU radio. Use your expert Google-fu to get your PLUTO able to receive and transmit.

In GNU radio just navigate to the examples folder typically found in /usr/share/gnuradio/examples/. In the dtv folder there is an example flow graph called dvbs2_tx.grc. Copy that file to your project folder and open it.

Delete the sinks and place a PLUTO SDR sink instead. Next we’ll have to change all the settings to something the Demodulator can handle. I used a code rate of 1/4 with QPSK modulation and a rolloff factor of 0.2. Make sure to check your filter taps on the FFT block. I used 96 taps.

firdes.root_raised_cosine(1.0, samp_rate, samp_rate/2, rolloff, taps)

On my SDR sink I put the LO at 917 MHz so that I’m in an ISM band, and set the attenuation to 13 dB to keep it quiet. Viewing the spectrum through SDR# I didn’t see any other activity, just to be sure. Keep in mind the PLUTO has a minimum sample rate, so if you want to use a low symbol rate you will have to change the overall sample rate of the flow graph. I used 1000k sps, making the sample rate 2M. Later I will be interested to see how I can narrow the bandwidth of the signal.

That should do it for the flow graph, except we need to point the file source to a transport stream to transmit. We need to build a transport stream file that matches the settings of the flow graph, and to do that we use ffmpeg. For this test I simply used a single frame, a jpeg picture. ffmpeg can convert to .mp4 with

ffpeg -framerate 25 -i picname.jpeg -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p output.mp4

and convert .mp4 to .ts with

ffmpeg -i output.mp4 -c:v copy -c:a copy -muxrate 478577 -f mpegts test1.ts

This muxrate is for the settings specified in the flow graph. You can get other transfer rates for different symbol rates using dtv-utils. Make sure your PLUTO sdr had adequate power and a stable USB connection, and start transmitting through the flow graph. You should be able to see the waterfall display on SDR# or the dvbs demodulator.

Set up VLC to receive a network stream from udp://@:8888.

It can take quite some time to get a carrier lock, so keep messing with the base band gain setting until you just barely see white on the waterfall. Sometimes during lock the symbol rate deviates from your setting, so I just toggle to 1001 and back to flush it.

I was only transmitting with the antennas that come with the SDR kits at about 2 feet distance. Next up there are many practical considerations before this is actually useful. But it was extremely cool to transmit a picture over the air with the use of GNU radio.

RTL-SDR for Ubuntu 20.04 LTS

Sometimes Google-fu isn’t enough and I actually have to use logic to solve problems. (wow!)

Setting up Ubuntu to use an RTL SDR usb dongle should be easy. It should be the standard steps you can find online right?

https://www.rtl-sdr.com/a-good-quickstart-guide-for-rtl-sdr-linux-users/

Well, not always. When I tried rtl_test -t I got an error message about needing to blacklist the kernel driver. Using lsmod I could see the names of modules, where I found that dvb_usb_rtl28xxu was in use. I thought I had already blacklisted the right ones based on advice from troubleshooting posts on reddit. Actually, I had to blacklist dvb_usb_rtl28xxu and not dvb_rtl28xxu. I guess wasting 2 hours doing this is just reward for relying on archived forum posts to do my dirty work. Here’s how to actually do it…

cd /etc/modprobe.d

sudo nano blacklist-rtl.conf

blacklist *rtl module you found using lsmod*

Setting up GNU Radio

Open source software can be a pain. To get the dependencies for compiling gnu radio, start with the list provided by Ettus Research.

For Ubuntu Bionic (18.04) it’s:

sudo apt-get -y install git swig cmake doxygen build-essential libboost-all-dev libtool libusb-1.0-0 libusb-1.0-0-dev libudev-dev libncurses5-dev libfftw3-bin libfftw3-dev libfftw3-doc libcppunit-1.14-0 libcppunit-dev libcppunit-doc ncurses-bin cpufrequtils python-numpy python-numpy-doc python-numpy-dbg python-scipy python-docutils qt4-bin-dbg qt4-default qt4-doc libqt4-dev libqt4-dev-bin python-qt4 python-qt4-dbg python-qt4-dev python-qt4-doc python-qt4-doc libqwt6abi1 libfftw3-bin libfftw3-dev libfftw3-doc ncurses-bin libncurses5 libncurses5-dev libncurses5-dbg libfontconfig1-dev libxrender-dev libpulse-dev swig g++ automake autoconf libtool python-dev libfftw3-dev libcppunit-dev libboost-all-dev libusb-dev libusb-1.0-0-dev fort77 libsdl1.2-dev python-wxgtk3.0 git libqt4-dev python-numpy ccache python-opengl libgsl-dev python-cheetah python-mako python-lxml doxygen qt4-default qt4-dev-tools libusb-1.0-0-dev libqwtplot3d-qt5-dev pyqt4-dev-tools python-qwt5-qt4 cmake git wget libxi-dev gtk2-engines-pixbuf r-base-dev python-tk liborc-0.4-0 liborc-0.4-dev libasound2-dev python-gtk2 libzmq3-dev libzmq5 python-requests python-sphinx libcomedi-dev python-zmq libqwt-dev libqwt6abi1 python-six libgps-dev libgps23 gpsd gpsd-clients python-gps python-setuptools

After that, I’m working on a bash script to automatically walk through the compile process. I was collecting dependencies, but later found the list above. So the compilation part looks like…

git clone https://github.com/nickhansenrf/gnuradio.git
cd ./gnuradio/
echo downloading volk
echo …
echo …
git clone https://github.com/gnuradio/volk.git
cd ./volk/
mkdir ./build
cd ./build/
echo configuring volk
cmake ../
echo compiling volk
make
make test
make install
ldconfig
cd ..
cd ..
mkdir ./build
cd ./build
echo configuring gr
cmake ../

Which is pretty much just taking my fork of the repo and compiling it. One thing is the VOLK repo is not my own fork, so I may want to change that.

Note: The official way is PYBOMBS which I should have tried first. Maintaining scripts like this is what PYBOMBS is for.

An LDPC Decoder

Error detecting and correcting codes have become integral to modern communication systems. Shannon provided a beautiful (and non-constructive) proof that tells us that codes exist that can achieve channel capacity. Unfortunately, the best codes have random structure which can make them hard to implement. LDPC codes are considered as good codes for next generation devices, beating out the turbo codes of the past.

I got to learn about LDPC codes and implement a decoder for a simple one… as it turns out these are not only theoretically good but simple to implement. High performance with low complexity is the engineers dream!

The decoder algorithm is the sum-product algorithm. It is an algorithm that can efficiently evaluate the probability that a single bit is correct within the LDPC structure. Since there are many long codewords it is more practical to perform decoding bitwise than by using entire codewords. The algorithm draws its name from the fact that it calculates sums and products for a number of iterations until a decision is made or the decoder fails. The expressions here are from “Efficient Implementations of the Sum-Product Algorithm for Decoding LDPC Codes” by XY Hu et. al., where the notation is also explained in greater detail.

1. The initial step for a received bit (or frame of 155 bits) is to calculate the intrinsic log likelihood ratio. For this we need to know something about the channel in use, which for this report is AWGN. Thus for equiprobable inputs over AWGN channel:

In this initialization step, each check node M(n) is passed intrinsic LLR according to its index position. This value is saved and also put into the messages. Variable nodes are initialized to 0.

2. The second step is to update the variable node messages. For the set N(m) excluding the nth variable node compute the LLRapp by the product equation given. Recall the set N(m) denotes the variable nodes connected to the check node m. For all the rows connected to column m by a 1 in H,

3. The third step is to update the check node messages. For the set M(n) excluding the mth check node calculate the sum as described.

4. The fourth step is to make a decision. This time sum across all the variable node messages and look at the sign of the result. If it is negative output 1, if it is positive output 0. If the resulting sequence passes the parity check, output it. Otherwise return to step 2. If too many iterations have passed and the sequence is still not valid we may declare that the decoder failed.

Since this code has a regular structure it is definitely not optimal. But it is easy to understand.

You could compare the performance I got against other codes and check. This structure is regular and thus the performance is limited.

I can share here the object I made to implement this decoder. Actually, this object could be used to build a decoder for any LDPC code because the structure is instantiated at run time. It’s a MATLAB object, so that makes it pretty easy to implement.

%The object for LDPC decoder. Written by Nicholas Hansen March 2018.
classdef pnode
  properties
     thisNode = 0;
     edge = [0 0 0 0 0];
     LLRint = 0;
     LLRapp = 0;
     sums = [0 0 0];
     products = [0 0 0 0 0];
  end
  methods
     function r = addEdge(obj, newedge)
        for i=1:1:5
           if obj.edge(i) == 0
               obj.edge(i) = newedge;
               break;
           end
        end
        r = obj.edge;
     end
     function r = getMess(obj, n)
        
        r = 0;
     end
     function r = getLLRint(obj, noise, SNR)
         variance = 1/(10^(SNR/10));
         r = (4*noise)/(variance^2);
         %here variance is actually No=2var^2
     end
     function r = getProduct(obj, checkNodes, j)
         product = 1;
         F = 0;
         for i=1:1:5 %this node's edges
           if i ~= j%excluding the current products edge  
             E=obj.edge(i);
             for k=1:1:3%among the sums for that node across the edge
               if checkNodes(E).edge(k) == obj.thisNode
                 %find the sum for this node
                 F = checkNodes(E).sums(k);
               end
             end
             product = product*tanh(F/2);
           end
         end
         product = 2*atanh(product);
         if product > 60 %clipping to avoid large numbers eating up memory
             product = 60;
         elseif product < -60
             product = -60;
         end
         r = product;
     end
     function r = getLLRsum(obj, varNodes, j)
         F=0;
         sum=0;
         for i=1:1:3
           if i ~= j
             E = obj.edge(i);
             for k=1:1:5%in the nodes accross the pond
               if varNodes(E).edge(k) == obj.thisNode
                 F = varNodes(E).products(k);
               end
             end
             sum = sum + F;
           end
         end
         r = obj.LLRint + sum;
     end
  end
end

Starting HFSS

In our lab, we use a Red Hat 6 running HFSS 19 to do some antenna simulations. Getting this thing to work can be difficult, especially for non linux people (most people). In the future hopefully they just put windows on this machine, it’s a Xeos with lots of power so the hardware is worth keeping around.

Anyway, from May until this November when the license expires, to get HFSS running you have to restart the license server first. In HFSS 19 this is a session that connects to the server through your browser. To trigger this, use in bash:

cd /

cd ./ansys_inc/shared_files/licensing/

(use su or sudo) ./start_lmcenter

At this point it will do something and get stuck… so use control+c to kill that process and try to start the license manager center again. This time it should open firefox and you can press start. If you have internet connection, it should be running.

Next you might want to set up VNC server. On this machine it’s

vncserver :8 -name nick -geometry 1440×900

where you can change the desktop number, name, and geometry variables.

to get in, connect a vnc client to

129.xxx.xx.xxx:8

or whatever your desktop number is. You might be prompted for the password.

purging raspian

linux is great but how do you manage what’s installed?

use:

sudo aptget remove –purge PROGRAMHERE

remember that bash supports wild card with *, so you can install the entire libreoffice with

sudo apt-get remove –purge libreoffice*

You can also use

sudo apt-get clean

sudo apt-get autoremove

to get rid of any temporary stuff

IRC commands

IRC is a weird global chatroom occupied by all kinds of groups. Using it can be a pain, since it’s old.

Using Google-fu, you can get your nickname registered. Once this is done, you still need to identify yourself once in awhile. Your client will try to use your nickname, to which the server will reply that it is already taken and you need to identify.

To do this, use:
/msg NickServ identify mysecretpassword

And then:

/join #yourgroup

http://www.ircbeginner.com/ircinfo/ircc-commands.html

Planar Antennas

There is a special class of antennas known as planar antennas. Sometimes these are called microstrip or patch antennas. The key feature of these is that they can conform to a flat plane, or even a curved plane. This is a fascinating realm of antenna design.

Say you wanted to design a durable antenna that is small and can conform to the cylindrical body of a mortar shell, and report telemetry back to the base.

You want to design a patch antenna!

The most critical design parameter for patch antennas is called relative dielectric permittivity, given like e sub r here, often called keff.

The material between your ground and antenna affects the end result greatly! Common types of filling are silica and teflon fibreglass.

Head on over to microwaves101 if you want to learn more!

Connect a raspberry pi to university enterprise network

Sometimes you just need to connect your linux mini computer to enterprise wifi. Unfortunately the GUI that comes with raspian OS can’t do it, so you need to take matters into your own hands.

It’s easy. Open a terminal and use the following commands to get to the wpa_supplicant.conf file.

  • ls (this will list the contents of your current directory)
  • cd / (this will take you to the top level directory)
  • cd ./next_directory (this will take you down into the next directory. Use tab autocompletion to look really smart! thanks bash)
  • sudo nano file_name (this will open the file in the text editor)

Now, add the following block at the bottom of wpa_supplicant.conf. No need to delete anything, just add this text!

network={

ssid=”Dal-WPA2″

key_mgmt=WPA-EAP

eap=PEAP

identity=”username”

password=”password”

}

All done! This works for Dalhousie University with a raspberry pi.

The Journey Begins

Thanks for joining me!

Good company in a journey makes the way seem shorter. — Izaak Walton

post

When you are a Bear of Very Little Brain, and you Think of Things, you find sometimes that a Thing which seemed very Thingish inside you is quite different when it gets out into the open and has other people looking at it.

A. A. Milne