Breadboard
docs
Example project · Displays & sensors

Encoder menu (big OLED)

A settings page on the 1.5″ 128×128 SH1107, driven by a rotary encoder decoded in MicroPython (gray code on two GPIOs with external pull-ups). Select the encoder and use its Inspector arrows to scroll; click the button to toggle an entry.

The Encoder menu (big OLED) circuit as rendered by the simulator

What's on the bench

  • 3× Resistor
  • Battery
  • Button
  • Encoder
  • ESP32-C3
  • OLED 1.5″ 128×128

The code

This MicroPython script runs on the emulated board every boot; edit it in the Code tab.

from machine import I2C, Pin
import framebuf, time
i = I2C(0, scl=Pin(9), sda=Pin(8))
buf = bytearray(2048)
fb = framebuf.FrameBuffer(buf, 128, 128, framebuf.MONO_VLSB)
for c in b'\xae\x20\xa8\x7f\xd3\x00\xdc\x00\x81\x4f\xad\x8a\xa4\xa6\xaf':
    i.writeto(0x3d, bytes([0, c]))
def show():
    for p in range(16):
        i.writeto(0x3d, bytes([0x00, 0xb0 + p, 0x00, 0x10]))
        i.writeto(0x3d, b'\x40' + buf[p*128:(p+1)*128])

a = Pin(0, Pin.IN)
b = Pin(1, Pin.IN)
btn = Pin(5, Pin.IN)
items = ['LED strip', 'Fan boost', 'Buzzer', 'Wi-Fi', 'Debug log', 'About']
on = [False] * len(items)
sel = 0
CODE = {(0, 0): 0, (1, 0): 1, (1, 1): 2, (0, 1): 3}
last = CODE[(a.value(), b.value())]
lastbtn = btn.value()
def draw():
    fb.fill(0)
    fb.text('Settings', 0, 0)
    fb.hline(0, 10, 128, 1)
    for i, name in enumerate(items):
        y = 18 + i * 14
        fb.text('>' if i == sel else ' ', 0, y)
        fb.text('[x]' if on[i] else '[ ]', 10, y)
        fb.text(name[:11], 38, y)
    show()
draw()
print('MENU')
while True:
    c = CODE[(a.value(), b.value())]
    if c != last:
        d = (c - last) % 4
        if d == 1:
            sel = (sel + 1) % len(items)
            print('SEL', sel)
        elif d == 3:
            sel = (sel - 1) % len(items)
            print('SEL', sel)
        last = c
        draw()
    v = btn.value()
    if v and not lastbtn:
        on[sel] = not on[sel]
        print('TOGGLE', sel, on[sel])
        draw()
    lastbtn = v
    time.sleep_ms(10)