User Tools

Site Tools


from_gnuradio_to_cortxlab_pico

From A to Z: GNU Radio with CorteXlab using PicoSDRs

This tutorial goes through the process of executing an experiment on CorteXlab starting from an empty project on your computer (and is quite similar to this tutorial, but this time we are using PicoSDRs).

For practical purposes, we will use some GNU Radio examples instead of starting from a clean sheet, but it's exactly the same as if you had your own project you wanted to run on CorteXlab.

Setup

The purpose of this tutorial is to execute an OFDM transmission between two PicoSDR nodes. One node will be the transmitter and the other one will be the receiver. Instead of starting from an empty project, we are going to use a GNU Radio example. Copy the files tx_ofdm.grc and rx_ofdm.grc located in $path_to_gnuradio/examples/digital/ofdm to a new folder.

As you can guess tx_ofdm.grc will be used for the ofdm transmitter and rx_ofdm.grc for the ofdm receiver.

The file tree should look like that:

...
├── tuto_ofdm
│   ├── tx_ofdm.grc
│   └── rx_ofdm.grc
...

Editing the .grc files

Using GNU Radio Companion (GRC) we are going to open and edit the two .grc files in order to use them with PicoSDR nodes.

tx_ofdm.grc

Open tx_ofdm.grc with GRC. As you can see we have all the process from OFDM encoding to OFDM decoding, but the transmission and decoding parts are just a modelisation.

The first thing to do is to change the generate options in order to have a 'No GUI' project (the results will be stored in a file). Open the Options block (in the top left corner) and switch the Generate Options from QT GUI to No GUI. By doing this the blocks QT GUI Time Sink and QT GUI Frequency Sink can't be generated anymore (their names turn red with an error message if you open them) so we have to remove them from the graph.

Set the samp_rate variable to 5000000 (5 MHz) using the corresponding variable block located at the top of the flow graph.

Then we need to add some mandatory blocks in order to use a PicoSDR :

  • Carrier Perseus Board
    ID : nutaq_carrier_perseus_0
    IP address : 192.168.0.101
  • Radio420 RX (to set up RX radio front end)
    target ID : nutaq_carrier_perseus_0
    block priority : 1
    Card number : Card 1
    Enable : True
    Reference : Internal
    RX frequency : 2490000000
    Data rate : samp_rate*2
    Automatic Calibration : Enabled
    Band : High Band (1500 to 3800 MHz)
    Update Rate : 1
    RX LNA Gain : Medium gain
    RX VGA1 gain : 19dB
    RX gain 2 : 20
    RX gain 3 : 8
    RX Low Pass Filter Bandwith : 10 MHz
    RX Band-Pass Filter : No filter - bypass filter bank
    Reference Clock Control : Host
    Radio Frequency Control : Host
    RX Gain Control : Host
    PLL/CPLD Control : Host
  • Radio420 TX (to set up RX radio front end)
    target ID : nutaq_carrier_perseus_0
    block priority : 1
    Card number : Card 1
    Enable : True
    Reference : Internal
    TX frequency : 2490000000
    Data rate : samp_rate*2
    Automatic Calibration : Enabled
    Band : High Band (1500 to 3800 MHz)
    Update Rate : 1
    TX VGA1 gain : -10
    TX VGA2 gain 2 : 15
    TX gain 3 : 3
    TX Low Pass Filter Bandwith : 10 MHz
    Reference Clock Control : Host
    Radio Frequency Control : Host
    TX Gain Control : Host
    PLL/CPLD Control : Host
  • Custom register
    target ID : nutaq_carrier_perseus_0
    Block Priority : 6
    Register Index : 1
    Register Value : 6
    Update Rate : 1
  • Custom register
    target ID : nutaq_carrier_perseus_0
    Block Priority : 5
    Register Index : 4
    Register Value : 0
    Update Rate : 1
  • Custom register
    target ID : nutaq_carrier_perseus_0
    Block Priority : 5
    Register Index : 3
    Register Value : 0
    Update Rate : 1

The input of the last custom register must be connected with a Constant Source block set to 1. The constant source needs to output an int and to be connected with the custom register.

The next thing to do is to replace the transmission and decoding parts to put a RTDEX Sink block instead. The parameters of this block are :
Target ID : nutaq_carrier_perseus_0
Block priority : 3
Input Type : Short
Media Type : Ethernet
Packet Size : 8192
Number of Channels : 1
Channels : 1

You can remove the throttle, Channel Model, OFDM Receiver and Tag Debug blocks. The Throttle is not needed anymore because the RTDEX Sink block will cadence our graph. Instead of these blocks we have to put several blocks leading to a RTDEX Sink block because we have to send an I/Q signal using short instead of a complex signal. First we need a Complex to float block, with a Float to short block on each output (scale = 2047). Combine the two using an Interleave Block and finally connect it with a RTDEX Sink block.

In the end your graph should look like this :

rx_ofdm.grc

Open rx_ofdm.grc with GRC. As you can see it's quite similar to tx_ofdm, except this time the encoder part is a modelisation and the decoder part faithfully describes the decoding process.

The first thing to do is to change the generate options in order to have a 'No GUI' project (the results will be stored in a file). Open the Options block (in the top left corner) and switch the Generate Options from QT GUI to No GUI.

Set the samp_rate variable to 5000000 (5 MHz) using the corresponding variable block located at the top of the flow graph.

Then we need the same mandatory blocks as with tx_ofdm, which are Carrier Perseus Board, Radio420 RX, Radio420 TX and three Custom Register. We also use the same parameters as in tx_ofmd. (Pro tips : you can copy/paste a block from one graph to another).

We need to modify the frequency on the Tx block so as not to interfere with the transmitting node:

  • Radio420 RX (to set up RX radio front end)
    TX frequency : 2590000000

The next thing to do is to replace the encoding and transmission parts to put a RTDEX Source block instead. The parameters of this block are : → Target ID : nutaq_carrier_perseus_0
Block priority : 3
Input Type : Short
Media Type : Ethernet
Packet Size : 8192
Number of Channels : 1
Channels : 1

You can remove the Random Source, Stream to tagged stream, OFDM Transmitter, Channel Model and throttle blocks. The Throttle is not needed anymore because the RTDEX Source block will cadence our graph. Instead of these blocks we have to put a RTDEX Source block and several blocks in order to deinterleave the I/Q signal and get a complex signal. Starting with a RTDEX Source block, connect it with a Deinterleave block and then a Short to float block (scale = 2047) on each output. Combine the two using a Float to Complex block. Finally connect this block to the Schmidl & Cox OFDM sync and Delay blocks. Also, it is highly recommended to add a filter in the Tag Debug block in order to avoid printing a huge amount of useless data. Open the tag debug block and add the key filter “packet_num”.

In the end your graph should look like this :

Generate the python files

Last thing we need to do within GRC is to generate the two python files corresponding to the two .grc files. For both tx_ofdm.grc and rx_ofdm.grc press the generate flow graph button and that's it ! You now have the two python files tx_ofdm.py and rx_ofdm.py in the same folder as the .grc files.

Hint : the button is located near the play button and looks like this →

Create the scenario

The experiment description file called scenario.yaml will be looked for and read by the experiment scheduler to get which nodes and what software will be used during the experiment. It also gives the necessary startup scripts and parameters that the user provides for his experiment.

Here is a simple example of a scenario.yaml file:

# Example scenario description file
#
#   All lines starting with "#" and empty lines are ignored


# Scenario textual description
#   simple string (a one liner)
description: OFDM tx-rx example scenario for CorteXlab

# Experiment maximum duration
#   Time after which the experiment is forced to stop
#   integer (seconds)
duration: 120

# Node list
#
#   format:
#
#   nodes:
#     (machine):
#       command: (entry point script relative to the task root)

nodes:
  node29:
    command: ./rx_ofdm.py
  node31:
    command: ./tx_ofdm.py

This file uses the yaml syntax and is self-documented. Adapt this example to suit your needs.

Launch the experiment into CorteXlab

The file tree should now look like that:

...
├── tuto_ofdm
│   ├── tx_ofdm.py
│   ├── rx_ofdm.py
│   ├── scenario.yaml
│   ├── tx_ofdm.grc
│   └── rx_ofdm.grc
...

The .grc will not be used by CorteXlab but you can leave them in the same directory.

Upload the files on airlock

Upload the tuto_ofdm directory on Airlock. For example, for Linux, it will look like this :

you@your-pc:~$ scp -P 2269 -r path/to/tuto_ofdm username@gw.cortexlab.fr:~ 

Create the task

Connect to Airlock through ssh. For example, for Linux, it will look like this :

you@yourpc:~$ ssh -p 2269 username@gw.cortexlab.fr

You will find in your home directory the tuto_ofdm directory that we previously uploaded.

Now, use the Minus CLI to create the task file:

you@srvairlock:~$ minus task create tuto_ofdm

The success (or failure) of the creation will be printed on screen. The task file will be created at the same level and with the same name as the targeted experiment folder but with a .task suffix, in our case tuto_ofdm.task.

Note: You can get help on the Minus CLI at anytime with minus -h

Book the testbed with OAR

As explained here, we need to book the testbed with OAR in order to run our experiment. Once you have booked the platform, you will be the exclusive user of the testbed, avoiding experimentation interference.

A basic example to submit an OAR interactive job requesting all available nodes, for 30 minutes:

$ oarsub -I -l nodes=BEST,walltime=0:30:00

Submit the task

Now, we have booked the testbed and we have a .task file containing our experiment. In order to run it, we need to submit it to the testbed scheduler.

For now, the scheduler is a simple FIFO queue, but a more advanced scheduling mechanism will be implemented in upcoming versions of CorteXlab.

To submit a task to the scheduler, use the Minus CLI:

you@srvairlock:~$ minus task submit tuto_ofdm.task

On screen will be prompted the id of your task in the scheduler. Note it down so that you can easily retrieve your results or monitor the progress of the experiment.

Observe the result

You can check the status of your experiment through the testbed scheduler. To do so, use the Minus CLI:

you@srvairlock:~$ minus testbed status
num total tasks:   2540
num tasks waiting: 0
num tasks running: 0
tasks currently running:
  (none)

The information given by this command enables you to deduce your experiment status. It's quite self-explanatory.

Once it's finished (we have set the duration to 2 minutes), Minus will take care of copying the results and output messages back to your home folder in srvairlock, such that you can analyse it.

All results are stored by task number in the results folder, inside your home folder.

Go in this folder :

you@srvairlock:~/tuto_ofdm$ cd ~/results
you@srvairlock:~/results$ ls
task_15
you@srvairlock:~/results$ cd task_15
you@srvairlock:~/results/task_15$ ls
node29.tgz  node31.tgz

So we see that we have a folder for each task and inside each folder one compressed file per participant node. Let's extract one of those files and see what's inside:

you@srvairlock:~/results/task_15$ tar -zxf node29.tgz
you@srvairlock:~/results/task_15$ ls 
node29  node29.tgz  node31.tgz
you@srvairlock:~/results/task_15$ cd node29
you@srvairlock:~/results/task_15/node29$ ls
rx_ofdm.grc  scenario.yaml  stdout.txt   tx_ofdm.py
rx_ofdm.py   stderr.txt     tx_ofdm.grc

We see that all of the files we used to create the task are inside. The other two are:

  • stdout.txt: all output messages from your GNU Radio python script are written here. These include GNU Radio messages as well as all “print”s you include in your code. Seeing the contents of this file is useful to assert its correct operation.
  • stderr.txt: all error messages are printed here. If you see strange things on the stdout.txt or nothing at all, it might be interesting to take a look at the stderr.txt to debug your code.

Let's take a look inside stdout.txt:

you@srvairlock:~/results/task_15/node29$ less stdout.txt

You should get a long file that looks more or less like this:

nutaq_carrier_perseus_0 connected to 192.168.0.101
Registering carrier nutaq_carrier_perseus_0
Using Volk machine: avx_64_mmx_orc
Global init begin
radio420_tx::InitRadio420x: 1
Press Enter to quit:     Powering up hardware
    Resetting hardware
    Configuring PLL
      - Reference frequency 30720000 Hz from internal oscillator
      - Acquisition frequency 10000000 Hz
      - Lime frequency 30720000 Hz 
    PLL is locked
    Configuring Gains
    Automatic calibration
radio420_rx::InitRadio420x: 1
    Automatic calibration
rx ended
rtdex_source: Init 
rtdex_source: Device MAC Address: 00:d0:cc:0a:01:9a
rtdex_source: Host MAC Address: 78:d0:04:20:74:6f
Global init end successfully
custom_register: started
rtdex_source: End Good

----------------------------------------------------------------------
Tag Debug: Rx Bytes
Input Stream: 00
  Offset: 0  Source: n/a     Key: packet_num   Value: 4029
----------------------------------------------------------------------

----------------------------------------------------------------------
Tag Debug: Rx Bytes
Input Stream: 00
  Offset: 96  Source: n/a     Key: packet_num   Value: 4031
----------------------------------------------------------------------

----------------------------------------------------------------------
Tag Debug: Rx Bytes
Input Stream: 00
  Offset: 192  Source: n/a     Key: packet_num   Value: 4035
----------------------------------------------------------------------

----------------------------------------------------------------------
Tag Debug: Rx Bytes
Input Stream: 00
  Offset: 288  Source: n/a     Key: packet_num   Value: 4036
----------------------------------------------------------------------

----------------------------------------------------------------------
Tag Debug: Rx Bytes
Input Stream: 00
  Offset: 384  Source: n/a     Key: packet_num   Value: 4040
----------------------------------------------------------------------

What's next ?

We have seen through this tutorial how to run an experiment in CorteXlab starting from a local example on your computer. Now you know all the basics in order to run your own experiment in CorteXlab between two PicoSDR nodes.

If you have followed the same tutorial using USRPs, you are now able to establish a communication between an USRP node and a PicoSDR node !

from_gnuradio_to_cortxlab_pico.txt · Last modified: 2017/11/15 16:19 by onicolas