Skip to content

chumicro-knobs

Rotary encoders and analog knobs, read as a number that holds still.

Turn a shaft and encoder.position counts the clicks. Turn a potentiometer and knob.value lands on a step and stays there. A fast spin arrives whole even when your loop was busy elsewhere, a parked wiper keeps reporting the same number, and the same code runs on CircuitPython, MicroPython, and your laptop.

Quick example

import board
from chumicro_knobs import Encoder
from chumicro_timing import ticks_ms

volume = Encoder(board.GP16, board.GP17, bounds=(0, 20))

while True:
    now = ticks_ms()
    volume.check(now)

    if volume.just_moved:
        print("volume", volume.position)

just_moved is true for exactly one pass of the loop, so you can read it as often as you like without it firing twice. bounds walks the number between 0 and 20 and stops it at both ends.

In a program with more going on, hand the loop to chumicro-runner and let the callback do the reading:

from chumicro_runner import Runner

volume.on_change = lambda detents: print("volume", volume.position)

runner = Runner()
runner.add(volume)

while True:
    now = runner.tick()
    runner.wait(now)

Every service in your program shares those same two lines.

Documentation

  • User Guide: wiring an encoder, bounds and wrap, reading a potentiometer, the deadband that holds it still, callbacks, and wiring into a runner
  • API Reference: every public class and method, generated from the source docstrings
  • Testing Helpers: turning a shaft and parking a wiper from a unit test