Potentiometers (often times shortened to the word pots, which are resistors varied by turning a knob) are a common peripheral on MIDI controllers. They also provide a greater sense of control than clicking and dragging when using a mouse with a DAW. In this example, you'll see how to update control change (CC) messages with pots.

Circuit Diagram

  • Pot 1
    • Pin 1 to QT Py RP2040 GND
    • Pin 2 to QT Py RP2040 A0
    • Pin 3 to QT Py RP2040 3V
  • Pot 2
    • Pin 1 to QT Py RP2040 GND
    • Pin 2 to QT Py RP2040 A1
    • Pin 3 to QT Py RP2040 3V
  • Pot 3
    • Pin 1 to QT Py RP2040 GND
    • Pin 2 to QT Py RP2040 A2
    • Pin 3 to QT Py RP2040 3V
  • Pot 4
    • Pin 1 to QT Py RP2040 GND
    • Pin 2 to QT Py RP2040 A3
    • Pin 3 to QT Py RP2040 3V

Setup the QT Py RP2040

For this example, you'll be using the QT Py RP2040. To make sure it is setup properly with CircuitPython, please follow the steps in the guide below.

CircuitPython Code

Once you've finished setting up your QT Py RP2040 with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT

import board
import usb_midi
import adafruit_midi
import simpleio
from analogio import AnalogIn
from adafruit_midi.control_change import ControlChange
from adafruit_midi.pitch_bend import PitchBend

#  midi setup
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0

#  potentiometer setup
mod_pot = AnalogIn(board.A0)
pitchDown_pot = AnalogIn(board.A1)
pitchUp_pot = AnalogIn(board.A2)
sus_pot = AnalogIn(board.A3)

#  function to read analog input
def val(pin):
    return pin.value

#  variables for last read value
#  defaults to 0
#  no pitchbend is 8192
mod_val2 = 0
pitchDown_val2 = 8192
pitchUp_val2 = 8192
sus_val2 = 0

while True:

    #  map range of analog input to midi values
    #  pitchbend range is 0 to 16383 with 8192 centered or no pitchbend
    mod_val1 = round(simpleio.map_range(val(mod_pot), 0, 65535, 0, 127))
    pitchDown_val1 = round(simpleio.map_range(val(pitchDown_pot), 0, 65535, 0, 8192))
    pitchUp_val1 = round(simpleio.map_range(val(pitchUp_pot), 0, 65535, 8192, 16383))
    sus_val1 = round(simpleio.map_range(val(sus_pot), 0, 65535, 0, 127))

    #  if modulation value is updated...
    if abs(mod_val1 - mod_val2) > 2:
        #  update mod_val2
        mod_val2 = mod_val1
        #  create integer
        modulation = int(mod_val2)
        #  create CC message
        modWheel = ControlChange(1, modulation)
        #  send CC message

    #  pitchbend down value is updated...
    if abs(pitchDown_val1 - pitchDown_val2) > 75:
        #  update pitchDown_val2
        pitchDown_val2 = pitchDown_val1
        #  create PitchBend message
        pitchDown = PitchBend(int(pitchDown_val2))
        #  send PitchBend message

    #  pitchbend up value is updated...
    if abs(pitchUp_val1 - pitchUp_val2) > 75:
        #  updated pitchUp_val2
        pitchUp_val2 = pitchUp_val1
        #  create PitchBend message
        pitchUp = PitchBend(int(pitchUp_val2))
        #  send PitchBend message

    #  sustain value is updated...
    if abs(sus_val1 - sus_val2) > 2:
        #  update sus_val2
        sus_val2 = sus_val1
        #  create integer
        sustain = int(sus_val2)
        #  create CC message
        sustainPedal = ControlChange(64, sustain)
        #  send CC message

Upload the Code and Libraries to the QT Py RP2040

After downloading the Project Bundle, plug your QT Py RP2040 into the computer's USB port. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the QT Py RP2040's CIRCUITPY drive. 

  • lib folder
  • code.py

Your QT Py RP2040 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

How the CircuitPython Code Works

The map_range() function is used to map the analog values from the potentiometers to MIDI values. The _val1 and _val2 variables are compared to each other for each pot to see if the pot has been turned. If it has, then an updated MIDI value is sent. 


You can connect your QT Py RP2040 via USB to either your computer or a USB MIDI host. Then, turn the knobs to affect modulation, sustain and pitch bend. This project works best with a software or hardware synth since the effects generally affect musical input happening in real time.

Going further, you could combine this project with the components and code from the MIDI keyboard example to create a larger MIDI interface.

This guide was first published on Mar 02, 2022. It was last updated on Jun 15, 2024.

This page (MIDI CC Control with Pots) was last updated on Jun 15, 2024.

Text editor powered by tinymce.