C-TCărpinișanAndreiPersonal Projects
10 March 2026
ArduinoHIDDIY3D Printing

Building a €11 USB Volume Knob in an Afternoon


I've always wanted a physical volume knob on my desk. The kind you just reach over and twist without touching the keyboard. They sell these for €30-60, which felt excessive for what is essentially a potentiometer and a microcontroller.


So I built one.


What you need


- Arduino Uno R3 - ~€6

- Arduino Potentiometer Module - ~€5

- USB cable

- Optional: 3D printed enclosure


How it works


The potentiometer outputs a value between 0 and 1023 depending on its position. The Arduino reads this, maps it to a volume range, and sends the appropriate HID media key commands to the OS.


This is the C++ Arduino code that first need to be uploaded to the Arduino:


// Pins for motor driver

const int ENA = 9;

const int IN1 = 8;

const int IN2 = 7;

const int IN3 = 6;

const int IN4 = 5;

const int ENB = 10;


void setup() {

pinMode(ENA, OUTPUT);

pinMode(ENB, OUTPUT);

pinMode(IN1, OUTPUT);

pinMode(IN2, OUTPUT);

pinMode(IN3, OUTPUT);

pinMode(IN4, OUTPUT);

stopMotors();

delay(5000);

}


void loop() {

moveForward();

delay(2000);

moveBackward();

delay(2000);

stopMotors();

delay(5000);

}


void moveForward() {

digitalWrite(IN1, HIGH);

digitalWrite(IN2, LOW);

digitalWrite(IN3, HIGH);

digitalWrite(IN4, LOW);

analogWrite(ENA, 200);

analogWrite(ENB, 200);

}


void moveBackward() {

digitalWrite(IN1, LOW);

digitalWrite(IN2, HIGH);

digitalWrite(IN3, LOW);

digitalWrite(IN4, HIGH);

analogWrite(ENA, 200);

analogWrite(ENB, 200);

}


void stopMotors() {

digitalWrite(IN1, LOW);

digitalWrite(IN2, LOW);

digitalWrite(IN3, LOW);

digitalWrite(IN4, LOW);

analogWrite(ENA, 0);

analogWrite(ENB, 0);

}


This, is the python code that needs to be ran:


from ctypes import cast, POINTER

from comtypes import CLSCTX_ALL

from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume

import serial


arduino_port = "COM10"

baud_rate = 9600


try:

ser = serial.Serial(arduino_port, baud_rate, timeout=0.05)

print("Serial connection established.")

except serial.SerialException as e:

print(f"Failed to connect: {e}")

exit(1)


devices = AudioUtilities.GetSpeakers()

interface = devices.Activate(

IAudioEndpointVolume._iid_, CLSCTX_ALL, None)

volume = cast(interface, POINTER(IAudioEndpointVolume))


previous_volume = 0.0

alpha = 0.1


while True:

if ser.in_waiting > 0:

try:

raw_data = ser.read_until().decode('utf-8').strip()

if raw_data.isdigit():

value = int(raw_data)

if 0 <= value <= 1023:

new_volume = value / 1023

smoothed_volume = alpha * new_volume + (1 - alpha) * previous_volume

previous_volume = smoothed_volume

volume.SetMasterVolumeLevelScalar(smoothed_volume, None)

except Exception as e:

print(f"Error: {e}")


The enclosure


I designed a cubical enclosure and a knob in SolidWorks, printed it in about 30 minutes. Press-fit the potentiometer into the top, tucked the Arduino inside, and threaded the USB cable out the back.


Currently, the python program needs to run for it to work, but I've set it to automatically run at windows start.


**Total cost: ~€11. Total time: one afternoon.**


These are my favourite kind of projects.

Discussion