Archive

Archive for the ‘GNURadio and USRP’ Category

Intro to GNURadio and the USRP (part 5, simple transceiver)

April 26, 2011 7 comments

This is going to be a short and sweet lesson. You want to communicate data across two USRPs. You’ll need a transceiver. Below (and in the source repository) you’ll find the GnuRadio-Companion blocks.

This is a pretty basic setup. You have two UHD blocks (a source and sink), a number of parameters to control things from the command line, modulator and demodulator, etc. One thing that is different is that this graph is not complete. The message source and sink are each missing something. The nice thing is, GnuRadio-Companion will still compile this to a python file. Then you can do as we learned in part 4, and modify the python code to interact with those message queues. There are, however, a few other changes you will need to make in the source. The creation of the message sink is not complete, as the constructor expects a message queue. You can easily create one (self.sink_queue = gr.msg_queue()).

There is something else about this block diagram. What are the two probes (probe avg mag^2 and probe signal)? Probes are used to allow the program to access certain information. For example. lets say you want to implement a MAC protocol (say CSMA/CA). You could use the probe signal (which is giving you access to complex to mag^2) to see the instantaneous received signal strength. This could be a good way to do the carrier sensing (something like db_val = 10 * math.log10(self.raw_mag_sqrd_probe.level())). If db_val is below threshold, then the channel is clear. Using the probe avg mag^2, you could get an estimate of the last received packet (since it is an average over the last few received samples). This would work well for an RSSI value which could be stuffed into a packet header and passed up the networking stack.

There are many possibilities. Given the state of the current block diagram, I’d start by writing a send_pkt and recv_pkt function for the simple_transceiver class which puts a message in the source queue or removes a message from the sink queue respectively (note, in the code above all messages must be 512 bytes in length).

Enjoy!

Advertisements
Categories: GNURadio and USRP

Intro to GNURadio and the USRP (Part 4, message blocks)

April 19, 2011 9 comments

This week I started playing with the message source and sink blocks within GNURadio and found them quite useful. Especially for accessing (sending and receiving) data outside of the actual GNURadio code. Below is the code, but let me explain what is going on (you can get the code from the source repository, see part 0). I create a top block which has a message_source and a message_sink (and a queue for each). Then I created two functions in the top block, one for sending a packet, and the other for receiving. The code should be fairly simple.

Then in the main portion of the code, I show how this is used. You can interact directly with the queues or by using the two functions.

from gnuradio import gr
from time import sleep

class msg_blocks(gr.top_block):

    def __init__(self):
        gr.top_block.__init__(self, 'Message Blocks Test')

        # initialize the queues
        self.sink_queue = gr.msg_queue()
        self.source_queue = gr.msg_queue()

        # initialize the blocks
        self.msg_source = gr.message_source(gr.sizeof_char, self.source_queue)
        self.msg_sink = gr.message_sink(gr.sizeof_char, self.sink_queue, False)

        self.connect((self.msg_source, 0), (self.msg_sink, 0))

    def send_pkt(self, payload):
        self.source_queue.insert_tail(gr.message_from_string(payload))

    def recv_pkt(self):
        pkt = ""

        if self.sink_queue.count():
            pkt = self.sink_queue.delete_head().to_string()

        return pkt            

if __name__=="__main__":
    tb = msg_blocks()
    tb.start()

    # operate on queues directly
    print 'operating on the queues directly'
    print 'sink queue count:', tb.sink_queue.count()

    print 'inserting:', 'a'
    tb.source_queue.insert_tail(gr.message_from_string('a'))

    sleep(1) # sleep to yield to tb thread

    print 'sink queue count:', tb.sink_queue.count()

    print 'received:', tb.sink_queue.delete_head().to_string()

    # operate using methods
    print 'operating with fuctions supplied by the top block'
    print 'sending:', 'a'*512
    tb.send_pkt('a'*512)
    sleep(1)

    print 'received:', tb.recv_pkt()
Categories: GNURadio and USRP

Intro to GNURadio and the USRP (Part 3, UHD)

April 14, 2011 1 comment

UHD is the way of the future. Read about it here. Unfortunately, UHD is not in the Ubuntu packages. Furthermore, the gnuradio in Ubuntu packages does not support UHD. That said, there is a way to get it working. This script will install UHD and GNURadio from source. In my next post, I’ll be doing an example which uses UHD, so install it!

Categories: GNURadio and USRP

Intro to GNURadio and the USRP (Part 2, Visualizing the Waves)

January 29, 2011 3 comments

Ever wonder what data looks like as it propagates through space as a waveform? In this second part of my introduction to GNURadio and the USRP, we will find out. For this part, we will again build a simulated setup in gnuradio-companion. The basic setup will be as follows: source -> modulator -> amplifier -> channel model -> throttle -> sink. In the picture below you can see our setup. The actual setup is fairly complicated, but instructions to download the source can be found in part 0.

In this example I am using a random source to generate random blocks of size 512. The OFDM modulator automatically packetizes the data. The Multiply Const block will act as an amplifier, which will be controlled from the mult_const variable. The channel model is the same as in part 1, but I’ve added a noise_voltage slider to control the noise. The throttle block was added to slow things down. Last, the FFT sink is a graphical sink that plots the FFT of the signal. The FFT converts from the time domain to the frequency domain. If you want to see what things look like in the time domain, use the Scope  graphical sink.

Running It and Experimentation

To run the code in gnuradio-companion, just generate the python code (F5) and execute it (F6). You should get something that looks like this:

This is what the random source looks like in the frequency domain. You can see the noise floor is about -30 dB and the bandwidth is about 7kHz. Using the GUI you can play with 2 variables. The noise voltage and the multiplication constant. Increasing the noise voltage should cause something like this:

As you can see, the noise floor goes up, but the level of the actual signal stays the same. This could make it hard for a decoder to be able to extract the data, we’d need to amplify the signal. That would look like this:

A signal like this should be much easier to decode.

Another interesting thing to play with is the “Occupied Tones” of the OFDM modulator. In the figure below, I’ve changed the tones from 200 to 50. You’ll need to stop the code, make the change, regenerate the python code, and run it (F7, F5, F6 are the hotkeys). What happened?

What now?

There is a lot to understand and play with here. Here are some things to look at.

  • Using the default parameters, what happens to the noise floor if you change the multiplier from 1 to 10? Why does this happen? (Checking Peak Hold can help you see exactly what is happening)
  • Try a few different modulators (change the Modulation Technique in the OFDM modulator, replace OFDM with something different and add a packet encoder if necessary). Does the view of signal change with different modulators?
Categories: GNURadio and USRP Tags: , ,

Intro to GNURadio and the USRP (Part 0, Code Repository)

January 29, 2011 5 comments

I’ve created a source code repository for the Intro to GNURadio and the USRP series of blog posts I’m doing. Check out the source at http://code.google.com/p/intro-to-gnuradio-and-usrp/ so you don’t have to worry about creating all the blocks yourself. Just go to the link above, click on the source tab, and follow the instructions to check the source out of the SVN repository.

Categories: GNURadio and USRP Tags: , ,

Intro to GNURadio and the USRP (Part 1, Simple Path)

January 19, 2011 17 comments

I’m starting to play with GNURadio and the USRP some. Coming from a Computer Science background, I do not have much experience with wireless communication systems. So, I thought I’d post my experiences to help others. In the first part of the series, we’ll design a very simple (simulated) communication system using gnuradio-companion (the GNURadio gui).

From the reading I’ve been doing on wireless communication system design, things can get pretty complicated very quickly. A basic simulated setup can be created fairly easily though. This requires no special hardware (e.g. a USRP) and has allowed me to do some tinkering.

The above figure (click to enlarge) shows our basic setup. GNURadio works by building paths from a source to a sink with (potentially) a number of intermediate blocks. Some example sources might be a file, a TCP socket, or a USRP radio. Sinks typically have a corresponding source (e.g. File Sink, TCP Sink, USRP Sink). In this case, I’m using a TCP Source and a TCP Sink. Any combination of source and sink will work (TCP Source with USRP Sink, USRP Source with File Sink, etc).

Simulated Setup

From the TCP Source, we go to the Packet Encoder (found under Synchronizers in grc). The encoder adds important information such as a preample and CRC32 checksum to each packet. Since I’ve left the payload length at 0, it will use the default 512. That means all packets will be 512 bytes (not including the bits that the encoder adds). This is important since that means all info sent to the TCP source must be a multiple of 512 bytes. The data is then modulated. Modulation converts the bits into something that a radio can actually transmit (complex numbers). Notice how the “in” link of the modulator is pink and the “out” is blue. That is because it is converting bytes to complex. After modulation, your data is ready to be placed into the air (via a USRP sink). Since I am only building a simulator, however, I’ve added a Channel Model block in there (found under filters).

The Channel Model block will simulate a wireless channel. You can configure various parameters (noise, etc). For now, I’m just leaving that alone.

After the channel comes the demodulation. If we were actually using USRP radios, our transmitter would be done, and we have to start designing a receiver in a new grc file. Since this is just a simulation, I’ve just hooked the channel model’s “out” to the demodulator’s “in”. The process is then reversed (to a packet decoder, then a TCP sink). So, does it work?

Running It

Now the code is ready to run. Press F5 to build the python code and then F6 to run it. Since I’m using a TCP source and sink, we can connect to the proper ports to send and receive data. Before sending, make sure you connect to the sink socket so you can see the data come through. The command I use is: nc localhost 9001. To send data I then use: perl -e “print ‘a’x1024” | nc localhost 9000. That will send the character ‘a’ 1024 times to port 9000. Here is the output:

What now?

Even with this simple setup, there are a number of things you can play with.

  • Change the parameters of the modulator and demodulator
  • Try out a different modulator/demodulator pair (OFDM which is used in 802.11a for example)
  • Change the noise voltage and see how high you can set it before the communications break
  • Once you break communications with noise, add an error correction block to fix it
  • Any other ideas?

UPDATES:

  1. After looking into the OFDM modulator code that GNURadio-Companion produces, it turns out that it automatically creates a Packet Encoder block for you. So if you are trying to use OFDM, remove the Packet Encoder from the path and change the modulator to OFDM.
  2. I recently compiled the grc file with the latest version of GnuRadio-Companion, and it didn’t work any more. After looking at the python code, I realized what happened. The latest version is creating the tcp source first. This blocks execution until something connects to the source. To fix this, just go into the py file and move the tcp sink creation to before the tcp source (or just use the py file from the repository).
Categories: GNURadio and USRP Tags: ,