Controlling Volume via Rotary Encoder


Good morning all

First I’d like to thank you for the work on PiMusicBox. I was stoked when I found it and got it up and running with my local files and the ability to browse spotify, it’s fantastic.

I have an old Pi B+ that I was doing nothing, so I have taken it upon myself to start a new project with an old bush AC2 radio to remove all the old innards and replace with up to date kit; as many others have done before me.

I have the TtsGpio working ok with buttons to control the volume up and down, but I’d like to use a rotary encoder to control the volume and to pause the music. If I connect the SW pin on the encoder to the button mapped to Main on TTS GPIO, it works as a button. I can’t seem to get the volume working with the rotation of the shaft though.

I’ve read about plenty of people getting this working, but with no details on how they managed to do so. I am a system engineer and worked in IT for the past 20 years with some coding experience, but a complete noob to python so any help people could offer would be absolutely fantastic.

I came across this one last night but upon attempting to install, I was greeted with unable to locate package.

Thank you in advance


I should add that this is a Keyes rotary encoder.


Hi @goll420!

In my experience (and also recommended by mopidy devs, it is not a good idea to use an extension to directly manage the GPIO rotary encoder. The way python works, code for the GPIO management and for Mopidy itself will be running on the same process, and the latency it introduces (specially on a RPi B) it’s too much to properly decode the signal edges and decide which way the knob has moved to.

There is a proper linux driver to manage rotary encoders ( You can configure it using a device tree overlay on the /boot/config.txt file, and it will generate an input device on /dev/input

Name:   rotary-encoder
Info:   Overlay for GPIO connected rotary encoder.
Load:   dtoverlay=rotary-encoder,<param>=<val>
Params: rotary0_pin_a           GPIO connected to rotary encoder channel A
                                              (default 4).
        rotary0_pin_b           GPIO connected to rotary encoder channel B
                                        (default 17).

If configured ok, there will be a new input device (check /dev/input/by-platform) which generates an event of type <EV_REL>, <REL_X>, and values +1 (moving the rotary clockwise) or -1 (CCW)
You can test if this works with the evtest comand on the input device.

Now, to control the mopidy volume you will need a script to listen to the events on this device, and generate the commands. There are two possibilities here: use the MPD protocol, or either websocket interface.

If you are willing to take this approach and have reached this further I can also help you with the script. Sorry if this solution is more complex than what you were looking for, but after having messing with some others is the one I found more responsive and satisfying.


Hi ismailof!

Thanks for the reply, I did actually manage to get it working but using a pythong script that contols ALSA mixer directly, so the volume control remains the same on the web portal in pimusicbox.

I’ve not noticed any latency as such per se, but only had it rigged up in a test bed so far. I’ll have a look at your method when I’m at home and have more time to digest it properly. Thank you for your advice though, it’s greatly appreciated.


If your soundcard provides a hardware mixer you can configure Mopidy to use that, in which case volume changes will be reflected in the web portal.


I’m waiting on delivery for a hifiberry AMP2, do you know if this provides a hardware mixer?


I believe that it does


Got it working, all good so far! Thanks for your help! :smile: