Media Control Knob

Media Control Knob


Media Control Knob inspired by Mikolas Zuza design:

I’ve changed the enclosure, code and used digispark instead of arduino so it’s hard to call it a remix.

Because I’ve reached 100 subscribers on YouTube and I’m very happy about it you can win one of these, just enter the giveaway here:

What it can do?

By default pressing the knob is play/pause button, rotating changes the volume, and rotating the knob with button pressed changes the track.
You can modify the left() right() and click() functions to suit your needs.


Stuff I’ve used (affiliates links, you pay nothing extra, I get some change):
Encoder ($ 0.5)

Digispark – choose the blue one ($ 1.3)

USB cable.
3D printed lower and upper cover – about 27 grams of filament (3 hours with 0.2 layer).

The code

How to configure Arduino IDE for Digispark:

Add Trinket USB Keyboard library:

Uploading the code is easy but first you need to follow the instructions from digisaprk on how to add it to arduino IDE if you haven’t already.
After installing all what’s left is to hit upload button and plug the digisaprk using a USB cable.

After a while the multimedia knob is ready to use.

If you want to change the rotation direction just switch PIN_ENCODER_A and PIN_ENCODER_B in the code.


You will need:
wires, wire cutters, digispark, encoder, soldering iron, something to desolder pins from encoder, hot glue, a file, 3D printed parts, usb cable.

First prepare the wires cut 5 pieces to about 2,5 cm(1inch) length and cover the end with solder.
Desolder the pins from the encoder.
Round over the edges of digispark with a file, be careful not to damage the USB socket.
Now connect the encoder with the digispark in my case I’m using black wire for GND, red for 5V, these are really important, so be sure to connect them properly.
The next three wires are:
blue for switch,
green and yellow for encoder A and B outputs. These are not super important you can always change them in the software.
In any case there is the schematic if you need one.
You need to remove the LED.

It’s a good idea to add something non slippery to the bottom so you can rotate the knob easily.
Pure PLA just slides way to easy on the desk surface.

Print Settings

Printer brand: Prusa
Printer: I3 MK3S
Rafts: No
Supports: No
Resolution: 0,2
Infill: 30%
Filament_brand: Fiberlogy
Filament_color: White/Silver
Filament_material: Fibersilk PLA

You need to print: 1x LowerBodyBiggerHole_v4 1x UpperCoverBiggerSmooth_v4 or UpperCoverBiggerKnurling_v4 or UpperCoverBiggerVertCuts_v4 Print them flat side facing down.

Source code

#include “TrinketHidCombo.h” #define PIN_SWITCH 0 #define PIN_ENCODER_A 2 #define PIN_ENCODER_B 1 bool switchState = HIGH; bool encoderAState = HIGH; bool encoderBState = HIGH; bool previousSwitchState = HIGH; bool previousEncoderAState = HIGH; bool previousEncoderBState = HIGH; bool canClick = true; // the setup routine runs once when you press reset: void setup() { pinMode(PIN_SWITCH, INPUT); pinMode(PIN_ENCODER_A, INPUT); pinMode(PIN_ENCODER_B, INPUT); digitalWrite(PIN_SWITCH, HIGH); digitalWrite(PIN_ENCODER_A, HIGH); digitalWrite(PIN_ENCODER_B, HIGH); TrinketHidCombo.begin(); // start the USB device engine and enumerate encoderAState = digitalRead(PIN_ENCODER_A); encoderBState = digitalRead(PIN_ENCODER_B); previousSwitchState = switchState; previousEncoderAState = encoderAState; previousEncoderBState = encoderBState; } // the loop routine runs over and over again forever: void loop() { bool wasChanged = false; previousSwitchState = switchState; previousEncoderBState = encoderBState; previousEncoderAState = encoderAState; bool switchStateReading = digitalRead(PIN_SWITCH); bool encoderAStateReading = digitalRead(PIN_ENCODER_A); bool encoderBStateReading = digitalRead(PIN_ENCODER_B); delayMicroseconds(750); if(digitalRead(PIN_SWITCH) == switchStateReading && switchStateReading != switchState) { switchState = switchStateReading; wasChanged = true; if(switchState == LOW) { canClick = true; } } if(digitalRead(PIN_ENCODER_A) == encoderAStateReading && encoderAStateReading != encoderAState) { encoderAState = encoderAStateReading; wasChanged = true; } if(digitalRead(PIN_ENCODER_B) == encoderBStateReading && encoderBStateReading != encoderBState) { encoderBState = encoderBStateReading; wasChanged = true; } if(wasChanged == true) { if(encoderAState == LOW && encoderBState == LOW) { if(previousEncoderAState == HIGH && previousEncoderBState == LOW) left(switchState); if(previousEncoderAState == LOW && previousEncoderBState == HIGH) right(switchState); } if(encoderAState == HIGH && encoderBState == HIGH) { if(previousEncoderAState == LOW && previousEncoderBState == HIGH) left(switchState); if(previousEncoderAState == HIGH && previousEncoderBState == LOW) right(switchState); } if(switchState == HIGH && previousSwitchState == LOW) click(); } TrinketHidCombo.poll(); delayMicroseconds(1000); } void left(bool switchState){ canClick = false; if(switchState) TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_DOWN); else TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_PREV_TRACK); } void right(bool switchState){ canClick = false; if(switchState) TrinketHidCombo.pressMultimediaKey(MMKEY_VOL_UP); else TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK); } void click(){ if(canClick) TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE);//MMKEY_MUTE }



5/5 - (1 vote)

Download 3D models

File File size
zip Media+Control+Knob 2 MB

Leave a Reply

Your email address will not be published. Required fields are marked *