Andres Vahter

rust enthusiast

Read this first

Release Rust embedded firmware using Github Actions

Github Actions

Github Actions is a nice way to setup CI/CD pipelines for your Github projects. Let’s setup it for an embedded firmware project written in Rust.

Continuous integration script would run every time when new code is pushed to master branch and release script would run only if a new tag is pushed.

Release in Github looks like this:
release.jpg

Let’s get started. We need following files in project root:

.github/workflows/ci.yaml
.github/workflows/release.yaml

File names actually do not matter.

ci.yaml

It is assumed that your Cargo project is setup in such a way that you could just run cargo build --release in root directory and everything builds. This script is doing just that:

name: Continuous Integration

on:
  push:
    branches:
      - master

env:
  CARGO_TERM_COLOR: always

jobs:
  compile:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain:
...

Continue reading →


Passing messages between AWS IoT and SQS queue using Lambdas written in Rust

AWS IoT Core provides a convenient way to connect your IoT devices like ESP32 to the cloud. Typically MQTT protocol is used for that.

Let’s suppose everything is setup on AWS IoT side and you can see messages from IoT Test console. Next we would like to transfer those MQTT messages to some other service that can actually do something useful with them. AWS SQS queues can be used for that.
Let’s create a rule that triggers a Lambda function every time if something is sent to a topic floor/1/room/3/temperature. Actually let’s receive all temperatures from all floors and rooms.

Rule query statement for doing it looks like this:
SELECT *, topic() as topic FROM 'floor/+/room/+/temperature'.
We cannot just do
SELECT * FROM 'floor/+/room/+/temperature'
because then we lose information about topic which can be quite valuable.
Let’s say temperature message itself is like this:

{
...

Continue reading →


Parsing line-based protocol using Rust and nom part 1

Let’s suppose we have some kind of line protocol and we would like to parse it in Rust. Here is an example how this protocol might look like:

"MEAS_NUM;voltage;20.1;V\n"
"MEAS_TEXT;serial;CAFEBABE\n"
"INPUT;Is it broken?;YES,NO,MAYBE\n"

As you can see there are different messages that must be parsed. Let’s create some structs to describe their payloads:

// "MEAS_NUM;voltage;20.1;V"
struct Num {
    name: String,
    value: f32,
    unit: String
}

// "MEAS_TEXT;serial;CAFEBABE"
struct Str {
    name: String,
    value: String,
}

// "INPUT;Is it broken?;YES,NO,MAYBE"
struct Input {
    message: String,
    variants: Vec<String>
}

We also need a Message type to combine all these possible messages:

enum Message {
    Number(Num),
    Text(Str),
    Input(Input),
}

This allows us to define a parser function that takes in a line and outputs a Message:

fn parser(line: &str) ->
...

Continue reading →


Convert subprocess stdout stream into non-blocking iterator in Rust

In one of my programs I had to interact with another subprocess. This subprocess took data from stdin and wrote result to stdout. It wasn’t just simple reading and writing - it took constant data stream from stdin and somewhere in the middle writes something to stdout. I had to capture this something as soon as possible and take actions according this response.

The main would look like this:

    fn main() {
        let process = Process::new();

        loop {
            let data = get_some_data();
            process.push(data);

            for response in proc.responses() {
                // do something based on response
            }
        }
    }

Blocking iterator

Firstly I just tried to read lines from process stdout. However I discovered that this BufReader is blocking. Code for the blocking stdout iterator is below. Because it is blocking we cannot put it into loop...

Continue reading →


Examples of creating Rust bindings

Couple of months ago I developed two SDR tools called doppler and demod. These tools were using unix pipe to transfer IQ data stream from one process to another and they were written in C that time.

I have read a lot of blog posts about Rust from the beginning of the year 2015 and I decided to give it a try. The best way to learn a new language is to use it, therefore I decided to rewrite those tools in Rust. This post mostly shows how to use Foreign Function interface - FFI to create Rust bindings.

Doppler

Firstly libgpredict was improved to use cmake for building and installing proper library. It is much easier to deal with Rust FFI if library is used instead of just bunch of C files. For example C version of doppler statically linked needed files from git submodule, which was fine for C version.

I could not use rust-bindgen for generating Rust functions from C because it did not...

Continue reading →


Doppler correction tool for SDR

Doppler is the last tool that is missing for receiving data from satellites using software defined radio (SDR) in a UNIX fashion:

Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

– Doug McIlroy

As I mentioned in my earlier post there exists many GUI based SDR tools for doing doppler correction and demodulation. However there aren’t tools available for doing this:

rtl_sdr | doppler | demod | multimon-ng

Some readers might already know that rtl_sdr is used for getting IQ data out of simple SDR dongles and multimon-ng is a tool that decodes actual packets from demodulated audio. Demod is a new tool that I wrote for demodulating IQ stream. Currently it supports only FM modulation, however it is quite easy to add more demodulators that are supported by liquid-dsp library.
...

Continue reading →


Liquid-dsp based command line FM demodulator

In my last post I wrote about how I hacked Google radioreceiver into command line based FM demodulator that can be used to pipe demodulated audio into multimon-ng for AX.25 packet decoding. However it had some significant flaws. For example as far as I know it only worked reliably if input sample rate was 1024 kHz and output 48 kHz. I did not look too much into problem because I wanted to rewrite it anyway to make it more universal for supporting more modulations beside FM and AM.

I am follower of www.rtl-sdr.com and recently there was a post about new SDR software called CubicSDR. What makes it interesting for me is that it uses library called liquid-dsp for doing signal processing. I tried to find decent signal processing library that is intended for SDR, but I ended up forking Google radioreceiver out of frustation. I did not have any luck finding such library until I stumbled upon...

Continue reading →


Pipe SDR IQ data through FM demodulator for FSK9600 AX25 reception

Problem

I thought that RTL-SDR and its command line tools are so common in these days that software for decoding everything and especially simple FSK9600 definitely exists. I was kind of right…except there are some corner cases. I looked for command line tools because decoding should work on BeagleBoneBlack which is not the most powerful computer.

There is rtl_fm that uses RTL-SDR dongle to receive actual signal from air and it also demodulates signal on the fly. Demodulated audio signal can then be piped to multimon-ng that decodes FSK9600 AX25 packets.

rtl_fm -f 437.505M -M fm -s 1024000 -r 22050 | multimon-ng -t raw -a FSK9600 /dev/stdin

Actually I have not tested this command in real situation, but it should work with strong signals. Narrow band FM uses +- 2.5 kHz deviation, but some nano satellites are using deviation around +- 3.5 kHz, therefore rtl_fm’s demodulation process...

Continue reading →


Using GNU Radio to show I/Q wav file on waterfall plot

Installing GNU Radio

Finally I managed to get GNU Radio working on Mac OS X. Firstly I used Homebrew repository from here https://github.com/robotastic/homebrew-hackrf to install GNU Radio and HackRF tools. However it did not went well. Gnuradio-companion always crashed with the following error:

  Warning: Block with key "xmlrpc_server" already exists.
  Ignoring: /usr/local/Cellar/gnuradio/3.6.5.1/share/gnuradio/grc/blocks/xmlrpc_server.xml
  Fatal Python error: PyThreadState_Get: no current thread
  Abort trap: 6

It turned out that some of the libraries were still using Mac OS X system’s Python instead of Python installed using Homebrew. I got it to work after renaming system’s Python and rebuilding boost libraries.

sudo mv /System/Library/Frameworks/Python.framework/ /System/Library/Frameworks/Backup.Python.framework
brew reinstall boost

Moreover robotastic fork uses old GNU...

Continue reading →


Turning Losi 1/24 short course truck into autonomos folk racer [part 1]

This year’s Robotex is not far away. It takes place from 29 - 30 november. This time it will be special because I decided to participate. Actually I decided it last December after Robotex 2013 when I saw Folkrace competition. It is entry level competition where 5 autonomos cars race against each other. Robot that is fastest in completing 3 laps is declared as winner. Check a video from last year’s competition. They are rather slow, we can do much better!

Chassis

My teammate Elmo suggested that we should use ready made RC car with brushless motor. Building mechanincs without proper tools is nightmare, therefore RC car platform is very reasonable choice for getting started as quickly as possible. We decided to use Losi 1/24 short course truck. It fits within 15x20 cm dimensions and it has brushless motor. We did not know at this time what else to look for.
First thing was to replace NIMH...

Continue reading →