Have some fun tuning in radio stations with your RTL Software Defined Radio setup by using a real, physical tuning knob! You can make one with just a potentiometer and a Gemma M0, plus some screws to connect the two.

The Gemma M0 can act like a USB HID keyboard, so it’s great for sending key commands. Code it in CircuitPython to send keyboard shortcuts to CubicSDR software, or customize it for other uses!

1 x Gemma M0
Small, HID capable microcontroller board
1 x 10k Potentiometer
Panel mount style
1 x Potentiometer Knob
Soft Touch T18 - Red
1 x USB Cable
6" A/Micro B

Additionally, you'll need two M3x8mm screws and nuts to secure the potentiometer to the Gemma M0. (Alternatively, you can use alligator clip leads if you have some handy.)

Build the Tuner Knob

With some careful bending of the legs, you can get the the potentiometer to connect to three pads on the Gemma M0. You feed the center leg into pad A2 which will measure the analog voltage of the potentiometer, and then you’ll bend the outer legs to contact pins D2 and 3V.

In software we’ll set pin D2 to a ground level, so the potentiometer will be able to reference that ground and the 3V as the wiper turns and changes the resistance value output to the center leg.

First, bend the outer legs on an angle to widen their reach as shown.

Bend the center leg down just a bit so it will be able to dive down into A2.

Then, use the screws and nuts to secure the outer legs to their respective pads — the center leg will contact the A2 pad securely without the need for a screw.

Next, you can add the knob -- try turning the shaft fully to the left first and putting the knob on at the six o'clock position as shown.

Now, plug the USB cable into the Gemma M0 and your computer, and get ready to program it!

Code It

Follow this guide https://learn.adafruit.com/adafruit-gemma-m0/circuitpython to get started with coding the Gemma M0 in CircuitPython. Install the latest release version of CircuitPython on the board. 

Also make sure you install the latest release version of the adafruit_hid library as shown here. Note: there will already be a previous version of the adafruit_hid library in the lib folder on your Gemma M0, but it may not be the version that goes with the latest release of CircuitPython that you just installed. So go ahead and replace the old library with the new! You can do this by downloading the latest release bundle, unzipping it, and then dragging just the adafruit_hid library to the Gemma M0’s CIRCUITPY/lib directory.

You may also want to install the Mu editor https://learn.adafruit.com/adafruit-gemma-m0/installing-mu-editor for your coding needs.

Once you can successfully code in Mu and upload to the board, return here.

The Gemma M0 Radio Tuning Knob software will read the voltage on pin A2. When the potentiometer it is at the midway point, the on-board LED will light up to indicate the center detent. In this position, no key commands will be sent.

In CubicSDR, pressing the bracket keys in the tuning window nudges the tuned frequency up or down, depending on which bracket is pressed.

Turn to the right and the Gemma M0 will send ‘]’ right bracket  keys  — the farther to the right you turn the knob the faster it will send them. Turning to the left does the same, but with the ‘[‘ left bracket. 

These happen to be the tuning key commands in CubicSDR software, but you can try out other commands for any software that accepts key commands, even overall system Volume commands if you want!

Here’s the code for the Radio Tuning Knob. Go ahead and copy it, paste it into Mu, and then save it as main.py to your Gemma M0.

# Gemma Radio Tuning Knob
# for fine tuning Software Defined Radio CubicSDR software
# 10k pot hooked to 3v, A2, and D2 acting as GND

import time

import board
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from analogio import AnalogIn
from digitalio import DigitalInOut, Direction

d2_ground = DigitalInOut(board.D2)
d2_ground.direction = Direction.OUTPUT
d2_ground.value = False
analog2in = AnalogIn(board.A2)

led = DigitalInOut(board.D13)
led.direction = Direction.OUTPUT

pot_max = 3.29
pot_min = 0.00
step = (pot_max - pot_min) / 10.0
last_knob = 0

def steps(x):
    return round((x - pot_min) / step)

def getVoltage(pin):
    return (pin.value * 3.3) / 65536

def spamKey(code):
    knobkeys = [Keycode.RIGHT_BRACKET, Keycode.RIGHT_BRACKET,
                Keycode.RIGHT_BRACKET, Keycode.RIGHT_BRACKET,
                Keycode.RIGHT_BRACKET, Keycode.SPACE,
                Keycode.LEFT_BRACKET, Keycode.LEFT_BRACKET,
                Keycode.LEFT_BRACKET, Keycode.LEFT_BRACKET,
    spamRate = [0.01, 0.05, 0.125, 0.25, 0.5,
                0.5, 0.5, 0.25, 0.125, 0.05, 0.01]
    kbd = Keyboard(usb_hid.devices)
    kbd.press(knobkeys[code])  # which keycode is entered
    time.sleep(spamRate[code])  # how fast the key is spammed

while True:
    knob = (getVoltage(analog2in))
    if steps(knob) == 5:  # the center position is active
        led.value = True
    elif steps(knob) != 5:
        led.value = False
Wherever your cursor is is where the Radio Tuning Knob will send its keyboard output! Center the knob to stop all output if you’re in the wrong place to send lots of ‘[‘ and ‘]’ keys!
This guide was first published on Mar 20, 2018. It was last updated on Mar 20, 2018.
This page (SDR Tuning Knob) was last updated on Oct 25, 2020.