Turn the receiver off between messages
To save power and cpu, I wanted to turn the RTL-SDR off between messages. Because the next message comes at a set interval, I can just turn the RTL-SDR off while I wait for it. It should lead to around 97% reduction in CPU and power usage. I changed the code to kill the gnuradio process after the message was decoded, and start it again before the next message came. Gnuradio takes some time to start, so I needed to measure exactly how long so it would be ready in time of the next message. On my platform, it takes around 1.8 seconds. The code to measure that:
It worked at first, but there was a problem somewhere. After around 1-2 days, it would fail. It would fail in such a way that the RTL-SDR would stop sending any data at all. The RTL-SDR module wouldn't even output for other tools like
rtl_fm. The only way to get it working again was to either unplug the RTL-SDR and plug it back in, or use sysfs to reset my whole USB controller (which would reset all the USB devices connected to it):
sudo sh -c 'echo 0000:00:1d.0 >unbind'
sudo sh -c 'echo 0000:00:1d.0 >bind'
I suspect there's a race condition with the RTL-SDR drivers, maybe it's the setup of the PLL is the part that is going wrong. It's not a problem when letting it run without stopping for weeks at a time, only when stopping and starting frequently. So I left it running all the time.
Include a measurement of signal strength and frequency
To estimate how strong the received signal is compared to the noise, I took the ratio of unexpected data to expected data in dB. This is roughly a month's worth of data.
sync messages SNR:
mean: 30 dB
std dev: 10
min: -16 dB
max: 36 dB
data messages SNR:
mean: 14 dB
std dev: 5
min: -1 dB
max: 21 dB
I wanted to try running this on a Raspberry Pi 3 B+ (1.4GHz). In theory, it should be significantly less power usage than the x86 server I have it running on now. The x86 server I have uses around 50 watts when it is idle. The Raspberry Pi 3 B+ uses under 2 watts when idle.
I put the latest raspbian on it, installed the gnuradio (version
184.108.40.206-2) and gr-osmosdr (version
0.1.4-12) packages, and tried running my decoder.
linux; GNU C++ version 6.2.0 20161010; Boost_106100; UHD_003.009.005-0-unknown
gr-osmosdr 0.1.4 (0.1.4) gnuradio 3.7.10
built-in source types: file osmosdr fcd rtl rtl_tcp uhd miri hackrf bladerf rfspace > airspy soapy redpitaya
*** Error in `python2': corrupted double-linked list: 0x01064620 ***
this does not work :(
Sidetrack: IO performance
Unrelated to all of this stuff, the SD card I'm using is pretty terrible:
Read 960Kb Written 640Kb Total transferred 1.5625Mb (71.566Kb/sec)
Writing 4kb and sync'ing it:
So I setup a network block device (nbd) so the Raspberry Pi could use the disks of a proper server. It's much faster:
Read 93.75Mb Written 62.5Mb Total transferred 156.25Mb (31.96Mb/sec). It's nice to see the new gigabit adapter resulting in faster IO.
4kb writes are also faster:
Testing version of Raspbian
Testing has newer package versions. Gnuradio version
220.127.116.11-1 and gr-osmosdr version
It works! It took a lot longer to start up compared to my x86 machine though, 1.8 seconds vs 7.1 seconds.
Let's see what happens when I run the full decoding system:
All those extra letter O's are a problem. They are from gnuradio, signaling that it's losing data (Overrun). It can still receive enough data to work, so it's not a total loss. But it is a sign that things aren't working as well as they could be.
Raspberry Pi CPU usage for gnuradio
From this, you can see core 2 is just at 100% usage. It's not keeping up. It's also a sign of the code not distributing the load over multiple cores, so it must not be threaded.
atop to verify the cpu frequency:
The average cpu frequency (avgf) is at 1.4GHz, so that looks fine.
However, I believe it's possible to do this work on as Raspberry Pi. As a comparison of CPU usage, I ran
rtl_fm -f 917.185MHz -s 22050 (receive 917.185MHz at 22050 samples per second).
And the CPU usage was around 3-5% of a core:
So I still have some work to do if I want to run this on a Pi3 B+.