It's easy to use the Adafruit I2C QT Rotary Encoder with CircuitPython using the Adafruit CircuitPython seesaw library. This library allows you to write Python code that reads encoder position (relative to the starting position) and, if applicable to your rotary encoder, button presses.
You can use this sensor with any CircuitPython microcontroller board or with a computer that has GPIO and Python thanks to Adafruit_Blinka, our CircuitPython-for-Python compatibility library.
CircuitPython Microcontroller Wiring
First wire up an I2C QT Rotary Encoder breakout to your board exactly as follows. The following is the breakout wired to a Feather using the STEMMA connector:
- Board 3V to breakout VIN (red wire)
- Board GND to breakout GND (black wire)
- Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
The following is the breakout wired to a Feather using a solderless breadboard:
- Board 3V to breakout VIN (red wire)
- Board GND to breakout GND (black wire)
- Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
Python Computer Wiring
Since there's dozens of Linux computers/boards you can use we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported.
Here's the Raspberry Pi wired with I2C using the STEMMA connector:
- Pi 3V to breakout VIN (red wire)
- Pi GND to breakout GND (black wire)
- Pi SCL to breakout SCL (yellow wire)
- Pi SDA to breakout SDA (blue wire)
Here's the Raspberry Pi wired with I2C using a solderless breadboard:
- Pi 3V to breakout VIN (red wire)
- Pi GND to breakout GND (black wire)
- Pi SCL to breakout SCL (yellow wire)
- Pi SDA to breakout SDA (blue wire)
Python Installation of seesaw Library
You'll need to install the Adafruit_Blinka library that provides the CircuitPython support in Python. This may also require enabling I2C on your platform and verifying you are running Python 3. Since each platform is a little different, and Linux changes often, please visit the CircuitPython on Linux guide to get your computer ready!
Once that's done, from your command line run the following command:
pip3 install adafruit-circuitpython-seesaw
If your default Python is version 3 you may need to run 'pip' instead. Just make sure you aren't trying to use CircuitPython on Python 2.x, it isn't supported!
CircuitPython & Python Usage
To demonstrate using this breakout with CircuitPython, you'll install the necessary library, update your code, and then connect to the serial console to see the information printed out.
To use the I2C QT Rotary Encoder breakout with CircuitPython, you need to first install the seesaw library into the lib folder on your CIRCUITPY drive.
Then you need to update code.py.
Click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, and copy the entire lib folder and the code.py file to your CIRCUITPY drive.
# SPDX-FileCopyrightText: 2021 John Furcean
# SPDX-License-Identifier: MIT
"""I2C rotary encoder simple test example."""
import board
from adafruit_seesaw import digitalio, rotaryio, seesaw
# For use with the STEMMA connector on QT Py RP2040
# import busio
# i2c = busio.I2C(board.SCL1, board.SDA1)
# seesaw = seesaw.Seesaw(i2c, 0x36)
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
seesaw = seesaw.Seesaw(i2c, addr=0x36)
seesaw_product = (seesaw.get_version() >> 16) & 0xFFFF
print(f"Found product {seesaw_product}")
if seesaw_product != 4991:
print("Wrong firmware loaded? Expected 4991")
# Configure seesaw pin used to read knob button presses
# The internal pull up is enabled to prevent floating input
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
button = digitalio.DigitalIO(seesaw, 24)
button_held = False
encoder = rotaryio.IncrementalEncoder(seesaw)
last_position = None
while True:
# negate the position to make clockwise rotation positive
position = -encoder.position
if position != last_position:
last_position = position
print(f"Position: {position}")
if not button.value and not button_held:
button_held = True
print("Button pressed")
if button.value and button_held:
button_held = False
print("Button released")
Your CIRCUITPY drive should resemble the image.
You should have in / of the CIRCUITPY drive:
- code.py
And in the lib folder on your CIRCUITPY drive:
- adafruit_seesaw/
Now, connect to the serial console. Try rotating the rotary encoder to see the position change, and, if applicable, press the button to see the button status printed out!
That's all there is to using the I2C QT Rotary Encoder with CircuitPython!
NeoPixel Color Picker Example
Update your code.py file to the following.
Click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, and copy the entire lib folder and the seesaw_rotary_neopixel.py file to your CIRCUITPY drive.
Rename seesaw_rotary_neopixel.py to code.py.
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT
"""I2C rotary encoder NeoPixel color picker and brightness setting example."""
import board
from rainbowio import colorwheel
from adafruit_seesaw import digitalio, neopixel, rotaryio, seesaw
# For use with the STEMMA connector on QT Py RP2040
# import busio
# i2c = busio.I2C(board.SCL1, board.SDA1)
# seesaw = seesaw.Seesaw(i2c, 0x36)
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
seesaw = seesaw.Seesaw(i2c, 0x36)
encoder = rotaryio.IncrementalEncoder(seesaw)
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
switch = digitalio.DigitalIO(seesaw, 24)
pixel = neopixel.NeoPixel(seesaw, 6, 1)
pixel.brightness = 0.5
last_position = -1
color = 0 # start at red
while True:
# negate the position to make clockwise rotation positive
position = -encoder.position
if position != last_position:
print(position)
if switch.value:
# Change the LED color.
if position > last_position: # Advance forward through the colorwheel.
color += 1
else:
color -= 1 # Advance backward through the colorwheel.
color = (color + 256) % 256 # wrap around to 0-256
pixel.fill(colorwheel(color))
elif position > last_position: # Increase the brightness.
pixel.brightness = min(1.0, pixel.brightness + 0.1)
else: # Decrease the brightness.
pixel.brightness = max(0, pixel.brightness - 0.1)
last_position = position
Rotate the rotary encoder to cycle through the NeoPixel rainbow. Press the rotary encoder switch and rotate while holding the switch to change the brightness.
That's all there is to using the NeoPixel with the rotary encoder using CircuitPython!
Multiple QT Rotary Encoder Example
Here's an example that uses multiple boards. The first board is in the default state, while the second board has it's A0 jumper bridged to set the I2C address to 0x37.
# SPDX-FileCopyrightText: 2021 John Park
# SPDX-License-Identifier: MIT
# I2C rotary encoder multiple test example.
# solder the A0 jumper on the second QT Rotary Encoder board
import board
from adafruit_seesaw import seesaw, rotaryio, digitalio, neopixel
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
qt_enc1 = seesaw.Seesaw(i2c, addr=0x36)
qt_enc2 = seesaw.Seesaw(i2c, addr=0x37)
qt_enc1.pin_mode(24, qt_enc1.INPUT_PULLUP)
button1 = digitalio.DigitalIO(qt_enc1, 24)
button_held1 = False
qt_enc2.pin_mode(24, qt_enc2.INPUT_PULLUP)
button2 = digitalio.DigitalIO(qt_enc2, 24)
button_held2 = False
encoder1 = rotaryio.IncrementalEncoder(qt_enc1)
last_position1 = None
encoder2 = rotaryio.IncrementalEncoder(qt_enc2)
last_position2 = None
pixel1 = neopixel.NeoPixel(qt_enc1, 6, 1)
pixel1.brightness = 0.2
pixel1.fill(0xff0000)
pixel2 = neopixel.NeoPixel(qt_enc2, 6, 1)
pixel2.brightness = 0.2
pixel2.fill(0x0000ff)
while True:
# negate the position to make clockwise rotation positive
position1 = -encoder1.position
position2 = -encoder2.position
if position1 != last_position1:
last_position1 = position1
print("Position 1: {}".format(position1))
if not button1.value and not button_held1:
button_held1 = True
pixel1.brightness = 0.5
print("Button 1 pressed")
if button1.value and button_held1:
button_held1 = False
pixel1.brightness = 0.2
print("Button 1 released")
if position2 != last_position2:
last_position2 = position2
print("Position 2: {}".format(position2))
if not button2.value and not button_held2:
button_held2 = True
pixel2.brightness = 0.5
print("Button 2 pressed")
if button2.value and button_held2:
button_held2 = False
pixel2.brightness = 0.2
print("Button 2 released")
Page last edited January 22, 2025
Text editor powered by tinymce.