Skip to content

Instantly share code, notes, and snippets.

@todbot
Last active July 30, 2025 21:10
Show Gist options
  • Save todbot/fe9bfb4eebbd52d4d2e5f000b01d46f7 to your computer and use it in GitHub Desktop.
Save todbot/fe9bfb4eebbd52d4d2e5f000b01d46f7 to your computer and use it in GitHub Desktop.
Use ADC and resistors to give you multiple buttons on single analog pin, for CircuitPython
# AnalogButtons - use ADC to give you multiple buttons
# 29 Jul 2025 - @todbot / Tod Kurt
# from an issue https://github.com/adafruit/circuitpython/issues/105272
# wiring is similar to https://www.instructables.com/How-to-Multiple-Buttons-on-1-Analog-Pin-Arduino-Tu/
import time
import board
import analogio
from collections import namedtuple
Event = namedtuple('Event', 'key_number pressed released')
class AnalogButtons:
"""
One analog pin to several buttons with resistors per button in a resistor ladder.
Each button produces a unique value on an analog input
:param analog_in: An object with a .value property, like analogio.AnalogIn()
:param levels: A tuple of values arranged lowest to highest that are about 10% lower
than that seen on analog_in.
"""
def __init__(self, analog_in, levels=()):
self.analog_in = analog_in
self.levels = levels
self.events = []
self.button_state = None
self.last_button = None
def events_get(self):
events = self.events
self.events = [] # reset event queue
return events
def update(self):
val = self.analog_in.value
# greater-than max level means no press or release
if val > max(self.levels):
if self.last_button is not None:
event = Event(self.last_button, False, True)
self.events.append(event)
self.last_button = None # done with button
# less than max means a press, start at lowest level first
else:
for i,level in enumerate(self.levels):
if val < level: # some button was pressed
if self.last_button is None: # no previous button pressed
self.last_button = i
event = Event(i, True, False) # push new button
self.events.append(event)
return
else: # previous button pressed
if self.last_button == i: # same button as before?
return # if so, do nothing
else: # else, new button
event = Event(self.last_button, False, True) # release last button
self.events.append(event)
event = Event(i, True, False) # push new button
self.events.append(event)
self.last_button = i # save new button
return
if __name__ == "__main__":
button_levels = (25000, 35000, 45000, 55000)
analog_buttons = AnalogButtons(analogio.AnalogIn(board.A0), button_levels)
while True:
time.sleep(0.2)
print('hi', time.monotonic())
analog_buttons.update()
events = analog_buttons.events_get()
if events:
print("events:",events)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment