Main Menu --- Click to Unfold ---
HOMEDownloads
Skywave Linux 11/2020 Update
i3 Key Bindings
Neovim Key Bindings
Tmux Key Bindings
Bash Aliases
Source Code
Other Top Notch Linux Distros
Skywave Linux Hard Drive Installation
Skywave Linux USB Installation
WebSDRs in 2019
Programmatic RTL-SDR Calibration
Fixing Audio: Dell, HP, Compaq
Skywave Linux Tumblr Page
Gqrx Spyserver Linux Client
Best Internet SDR Servers
Quick Tune HFGCS List
Quick Tune VOLMET List
Programmatic RTL-SDR Calibration
RTL-SDRs are great devices. They are known for being small, inexpensive, light in power demand, operable from low frequencies through L band, and workable with numerous signal processing packages. They are NOT known for having precise and stable clock oscillators. Frequency errors of 30 to 50 parts per million are common. For users tuning VHF narrowband voice or digital modes, such an error is enough to cause signals to fall on the edge of the receiver passband. In some cases, signals may fall out of a narrow passband and be completely missed.
One solution is to only use RTL-SDRs sold with upgraded clock oscillators, such as the NESDR SMArt or RTL-SDR.com V3. Another way to put the RTL-SDR on frequency is to check it against a known signal and manually program the offset into applications controlling the dongle. That is often accurate enough, but still a broad approximation. A better solution, also applicable to upgraded devices, is to automate the process of checking against known signals and get a more precise measurement based on a time series of phase measurements. For that, there is a nifty application named Kalibrate-RTL.
Kalibrate-RTL uses mobile telephone calibration signals, which are derived
from GNSS signals
as a precise frequency and time reference. Also, it eliminates human factors in
measuring offsets. In fact it takes multiple readings and averages them to work
out a mean offset. That is good enough (quite good enough) for most users. For
critical applications needing top notch, minimal drift, precision tuning, an SDR
better than RTL dongles should be considered...
Given below is a bash script for running Kalibrate-RTL. It was developed on a modest Ubuntu Linux system, and tested on run of the mill RTL-SDR hardware. It can get the PPM offset, then save it along with a gain setting and SoapySDR device string for other applications to use. For example, OpenWebRX or Dump1090 can configured with the help of a short bit of code to read the offset and gain settings before bringing up the SDR for signal collection.
#!/bin/bash # Copyright (c) 2019 by Philip Collier, radio AB9IL# This script is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. There is NO warranty; not even for # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # Measure and save rtl-sdr calibration information using GSM base stations. # Edit the file referenced for gain setting by certain applications. # Save SoapySDR device string and key for other uses. Encoding=UTF-8 savedir="/usr/local/etc" get_offset(){ echo "Measuring ppm offset on channel "$best_channel offset=($(kal -c $best_channel 2>&1 | grep "absolute error" | grep -Po "\d*\." | awk '{printf "%.0f", $0}')) if [[ -z "$offset" ]]; then notifyerror fi echo $offset > $savedir/sdr_offset # save offset for general usage sed -i "s/corr_freq=.*/corr_freq=${offset}000000/g" ~/.config/gqrx/default.conf # save offset for gqrx WINDOW=$(zenity --info --height 100 --width 350 \ --title="Calibration and Gain" \ --text="An offset of $offset ppm has been written to file $savedir/sdr_offset."); } notifyerror(){ WINDOW=$(zenity --info --height 100 --width 350 \ --title="Calibration and Gain" \ --text="Something went wrong."); exit } scan_band(){ echo "Please stand by. Scanning for $band stations..." mapfile -t arr < <(kal -v -s $band -g 40 2>&1 | grep 'chan:' | awk '{printf $2" "$7"\n"}' | sort -nrk2) echo "Chan Strength" printf '%s\n' "${arr[@]}" set -- ${arr[0]} best_channel=$1 get_offset } set_device(){ OUTPUT=$(zenity --forms --title="SoapySDR Device Type" --width 400 --height 100 \ --text="Enter the SDR start-up parameters reported by \"SoapySDRUtil --find\"." \ --separator="," \ --add-entry="SoapySDR Device Driver (e.g. rtlsdr):" \ --add-entry="SoapySDR Device Key (e.g. rtl=0):" \ ); if [[ "$?" -ne "0" ]]; then notifyerror fi driver=$(awk -F, '{print $1}' <<<$OUTPUT) devkey=$(awk -F, '{print $2}' <<<$OUTPUT) # write device driver data to the reference file echo $driver > $savedir/sdr_driver # write device key to the reference file echo $devkey > $savedir/sdr_key WINDOW=$(zenity --info --height 100 --width 350 \ --title="SoapySDR Device Type" \ --text="Device driver $driver has been written to file $savedir/sdr_driver. Device key $devkey has been written to file $savedir/sdr_key."); } set_gain(){ OUTPUT=$(zenity --forms --title="Calibration and Gain" --width 400 --height 100 \ --text="Enter the desired SDR gain." \ --add-entry="Gain:"); if [[ "$?" -ne "0" || -z "$?" ]]; then exit fi gain=$(awk -F, '{print $1}' <<<$OUTPUT) # write gain setting to the reference file echo $gain > $savedir/sdr_gain WINDOW=$(zenity --info --height 100 --width 350 \ --title="Calibration and Gain" \ --text="A gain of $gain has been written to file $savedir/sdr_gain."); } set_offset(){ OUTPUT=$(zenity --forms --title="Calibration and Gain" --width 400 --height 100 \ --text="Enter the desired SDR offset (ppm)." \ --add-entry="Offset:"); if [[ "$?" -ne "0" || -z "$?" ]]; then exit fi offset=$(awk -F, '{print $1}' <<<$OUTPUT) echo $offset > $savedir/sdr_offset # save offset for general usage sed -i "s/corr_freq=.*/corr_freq=${offset}000000/g" ~/.config/gqrx/default.conf # save offset for gqrx WINDOW=$(zenity --info --height 100 --width 350 \ --title="Calibration and Gain" \ --text="An offset of $offset ppm has been written to file $savedir/sdr_offset."); } gui(){ ans=$(zenity --list --title "SDR Operating Parameters" --width=500 --height=290 \ --text "Manage RTL-SDR frequency calibration and gain. 1) Calibration uses measurements of GSM base stations. 2) Device gain is saved for reference by other applications." \ --radiolist --column "Pick" --column "Action" \ TRUE "Scan for GSM 850 MHz base stations." \ FALSE "Scan for GSM 900 MHz base stations." \ FALSE "Scan for E-GSM base stations." \ FALSE "Manually program the SDR offset." \ FALSE "Manually program the SDR gain." \ FALSE "Manually program the SoapySDR device data."); if [ "$ans" = "Scan for GSM 850 MHz base stations." ]; then band='GSM850' scan_band elif [ "$ans" = "Scan for GSM 900 MHz base stations." ]; then band='GSM900' scan_band elif [ "$ans" = "Scan for E-GSM base stations." ]; then band='EGSM' scan_band elif [ "$ans" = "Manually program the SDR offset." ]; then set_offset elif [ "$ans" = "Manually program the SDR gain." ]; then set_gain elif [ "$ans" = "Manually program the SoapySDR device data." ]; then set_device fi } case "$1" in gui) gui ;; gsm850) band='GSM850' scan_band ;; gsm900) band='GSM900' scan_band ;; egsm) band='EGSM' scan_band ;; offset) if [[ "$2" -ne "0" || -z "$2" ]]; then exit fi echo "$2" > $savedir/sdr_offset ;; gain) if [[ "$2" -ne "0" || -z "$2" ]]; then exit fi echo "$2" > $savedir/sdr_gain ;; device) if [[ "$2" -ne "0" || -z "$2" ]]; then exit fi echo "$2" > $savedir/sdr_driver if [[ "$3" -ne "0" || -z "$3" ]]; then exit fi echo "$3" > $savedir/sdr_key ;; *) echo "Usage: kal.sh gui Use the graphical interface to select a function. gsm850 Scan for GSM 850 MHz base stations. gsm900 Scan for GSM 900 MHz base stations. egsm Scan for E-GSM base stations. offset Manually program the SDR offset . gain Manually program the SDR gain . device Manually program the SoapySDR device data . " >&2 exit 3 ;; esac
It is a simple matter to calibrate a dedicated receiver at boot time, as the script can be executed from a system init script. Here is a snippet of code which would run from a launcher in /etc/xdg/autostart/ or the script /etc/init.d/rc.local:
# calibrate the rtl-sdr sh -c "kal.sh gsm850" &
The above example could also be run regularly as a cron job, but be aware that some scripting would be necessary to stop anther process which may be using the device, then start it up again after the calibration finishes. Calibration of SDR devices with very large offsets may fail, as the cell tower signals may fall outside of the receiver passband. In that case, use your favorite SDR application to manually find the strongest GSM signals, then invoke kal manually to tune one of them.
kal -v -fFor more scrpts and snippets useful for SDR operating, see the Skywave Linux Github repository.-g
Tags:Manual or automatic frequency calibration for RTL-SDR devices.
Contact Us, Privacy Policy and Affiliate Disclosure, XML Sitemap.