AB9IL.net

Programmatic RTL-SDR Frequency Claibration

Disclosure: AB9IL.net is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program such that this site earns advertising fees by linking to Amazon.com. If you make a qualifying purchase after clicking a link on this website, the associate affiliated with this site may earn a comission at no cost to you.


#Advert: Great scenes deserve a great LG monitor.

New Features: Global Quick Tune Internet SDR List Improve Your Radio Knowledge at "YouTube SDR School"
Article Index --- click here to unfold ---
Newest Pages NEW: Trumpists Kicking the Hornets Nest
NEW: Introduction to Catbird Linux
NEW: Skywave Linux Updated to ver 4.1
NEW: i3wm: Using i3-ipc to Float Windows
How to Record from WebSDR and OpenWebRX Sites
Programmatic RTL-SDR Frequency Claibration
Public KiwiSDR Lists
Malaysia Airlines Flight MH17: Simply Mass Murder
The Anonymous Cathay Pacific Employee Letter to Hong Kong
For For Cathay Crews Crossing Borders With Electronics
Photo Gallery 9: The New Life Movement in China, 1944
E Pluribus Unum: From Many, One, Dammit
HFGCS Quick Tune SDR List
The Robert Mueller Iron Triangle Speech
A Rant About One Party Rule
Best OpenWebRX and WebSDR Servers
SDR School via YouTube
ADALM-PlutoSDR on Linux Systems
MOFO Linux: Defeating State Censorship and Surveillance
Linux: Distros, Code, and Nifty Software NEW: Introduction to Catbird Linux
NEW: Skywave Linux Updated to ver 4.1
NEW: i3wm: Using i3-ipc to Float Windows
Skywave Linux: HPSDR, WebSDR, and RTL-SDR ready to run.
Siduction Linux with the Cinnamon Desktop
Siduction Linux with the LXQT Desktop
Andy's Ham Radio Linux 15 and QtRadio
Booting Multiple Linux Disc Images with Grub2
Porteus Linux Hard Drive Installation
UPDATED: MOFO Linux - For Unrestricted Internet
Aptosid with LXDE
Asus EeePC 1215N with Linux
Autostart Tweaks for KDE3 and KDE4
Broadband Speed Tweaks For Linux
Fixing the Firefox 3 Rendering Bug
Linux on Solid State Drives
Linux Wireless Interface Driver Updates
Setting Polkit to Automount USB Devices
Sidux with LXDE
Fixing Skype Inverted Video
SLAX Remix - kernel upgrades
Flash Drive Linux - Introduction
Flash Drive Knoppix 5.3 - Part 1
Flash Drive Knoppix 5.3 - Part 2
Flash Drive Knoppix 6.0 - Part 1
Flash Drive Knoppix 6.0 - Part 2
Flash Drive SLAX - Part 1
Flash Drive SLAX - Part 2
Flash Drive Bluewhite64 - Part 1
Flash Drive Bluewhite64 - Part 2
Flash Drive Linux - Basic Customization
SLAX Customization - Part 1
SLAX Customization - Part 2
Bluewhite64 Customization - Part 1
Bluewhite64 Customization - Part 2
Long Range Wi-Fi Basics of Long Range Wireless Networking
Linear Focus Parabolic Wi Fi Antenna
High Gain Wi Fi Dish Antenna
High Gain Helical Wi Fi Antenna
High Gain Yagi Wi Fi Antenna
High Power Wireless Adapters
Wi Fi Extender Antenna for Routers
Belkin F5D7050 External Wi Fi Antenna
Linksys WUSB54GC External Antenna Mod
Compat Wireless Linux Drivers
Installing WPA_Supplicant for Wi-Fi Security
Linux Wireless Interface Driver Updates
Linux Wireless Interface Driver Support
NetworkManager and Consolekit
RT73 Wireless Drivers for Linux Kernel 2.6.27+
RT2860 Wireless Drivers for Linux Kernel 2.6.27+
Radio: Amateur Radio, Aero Radio, Shortwave, etc NEW: Programmatic RTL-SDR Frequency Claibration
NEW: Public KiwiSDR Lists
NEW: GHFS Quick Tune SDR List
UPDATED: Best OpenWebRX and WebSDR Servers
UPDATED: Skywave Linux: HPSDR, WebSDR, and RTL-SDR ready to run.
CubicSDR on Debian, Ubuntu, and Linux Mint
Dump1090 for Linux Mint 17.1 and Siduction 2014.1
Software Defined Radio - An Introduction
QS1R Direct Sampling SDR
Chaining SDR Audio Interfaces
FLEX-6000 Direct Sampling SDR
UPDATED: RTL2832 Software Defined Radio
WebSDR Digimode Reception
Enabling FLASH in Jack Audio
Realtime Software Audio Processing
Liberation Technology MOFO Linux - For Unrestricted Internet
Veracrypt Encryption for Linux
Veracrypt Encryption for Windows
Using Google Within China
Popcorn Time and Flixtor for Uncensored Streaming Media
DNS Encryption using DNSCrypt
Galaxy Nexus Privacy and Robustness Enhancements
Galaxy SIII Privacy and Robustness Enhancements
Flash Drive Encryption for Linux
Flash Drive Encryption for Windows
Multihop VPN Connections for Strong Internet Privacy
Open and Free DNS Server List
OpenVPN Cloaking against Deep Packet Inspection The Serval Mesh Phone Project
Skype's Robust Security
Man in the Middle Wireless Security Risks
Wireless Security and Surveillance
Digital Audio Adjusting Audio Dynamics in VLC
Backing Track Prep Guide
Ipod Music Processing Guide
How To Record Record Live Music Performances
Realtime Software Audio Processing
Chaining SDR Audio Interfaces
Aerospace Radio, Aviation, Pontification, and Opinion NEW: Trumpists Kicking the Hornets Nest
NEW: The Anonymous Cathay Pacific Employee Letter to Hong Kong
NEW: For For Cathay Crews Crossing Borders With Electronics
NEW: E Pluribus Unum: From Many, One, Dammit
NEW: HFGCS Quick Tune SDR List
NEW: The Robert Mueller Iron Triangle Speech
NEW: A Rant About One Party Rule
Captains Authority Versus Autocratic Airline Management
Malaysia Airlines Flight MH17: Simply Mass Murder
Malaysia Airlines Flight MH370 - A Media Circus
High Gain Air Band Antennas
Apollo Unified S Band Communications
Chinese Anti-Stealth VHF Radar
Oceanic Communications - Procedures, Equipment, Voice and HFDL
Boeing 737NG Radio Equipment
Boeing 767 Radio Equipment
NAOC-TACAMO Monitoring
My Flight on 9/11
Joshua Chamberlain's Leadership Tips
Special Operations Forces Truths
TWA 800: Just Give Me Some Truth
Photo Gallery Aviation Photo Gallery 1: Snapshots From My Journeys
Aviation Photo Gallery 2: On the Road With ATA Airlines
Aviation Photo Gallery 3: More ATA Airlines
Aviation Photo Gallery 4: Southwest Airlines is the Borg Empire
Aviation Photo Gallery 5: Starting Over, Moving On...
Aviation Photo Gallery 6: More Viva Macau
Aviation Photo Gallery 7: Mainland China Airline Flying
Aviation Photo Gallery 8: Chinese Smog and Fog
NEW: Photo Gallery 9: The New Life Movement in China, 1944
Broadcasting BBC Radio Blooper - Adolf Merckle
TV DXing the World Trade Center
New York TV after 9/11
Live Music Recording Adjusting Audio Dynamics in VLC
Backing Track Prep Guide
Ipod Music Processing Guide
How To Record Record Live Music Performances
Radio Poetry and Arts In Distress, by David Wagoner
Just A Radio Operator, by Robert A. Wallace
Radio Circuit Modifications ATS-909 Modifications
ATS-909 Manuals
ATS-909 Alignment Procedure
ATS-909 Alignment Spectrograms
Very Low Frequency (VLF) Radio Internet Based VLF Radio Listening
Windows Tips Windows Performance Enhancement Tips
A Faster Windows 7
Windows 7 SSD Setup

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...

#Advert: Get your CPUs, GPUs, and Motherboards from GigaParts.

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, GQRX, OpenWebRX, or Dump1090 can configured with the help of a wrapper script to read the offset and gain 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 -f  -g 

For more scrpts and snippets useful for SDR operating, see the Skywave Linux Github repository.



Tags: RTL-SDR Frequency Calibration, RTL-SDR PPM, RTL-SDR Clock Error, Kalibrate-RTL

©2005 - 2020 AB9IL, All Rights Reserved.
About, Contact, Privacy Policy and Affiliate Disclosure, XML Sitemap.