Example project · ESP32
Keypad door lock (keypad + OLED)
A real embedded project: an ESP32 scans a 4x4 matrix keypad and drives an OLED lock screen. Press keys to enter a code (default 1234), * to clear, # to submit; the display shows UNLOCKED or DENIED. Demonstrates matrix scanning, edge detection, and live display, all in MicroPython.

What's on the bench
- Battery
- ESP32-C3
- Keypad 4×4
- OLED 128×64
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(1024) fb = framebuf.FrameBuffer(buf, 128, 64, framebuf.MONO_VLSB) for c in b'\xae\xd5\x80\xa8\x3f\xd3\x00\x40\x8d\x14\x20\x00\xa1\xc8\xda\x12\x81\xcf\xd9\xf1\xdb\x40\xa4\xa6\xaf': i.writeto(0x3c, bytes([0, c])) def show(): i.writeto(0x3c, b'\x00\x21\x00\x7f\x22\x00\x07') i.writeto(0x3c, b'\x40' + buf) # 4x4 matrix keypad: rows drive, columns read (active-high scan). rows = [Pin(n, Pin.OUT) for n in (0, 1, 2, 3)] cols = [Pin(n, Pin.IN) for n in (4, 5, 6, 7)] KEYS = ['123A', '456B', '789C', '*0#D'] def scan(): pressed = set() for r in range(4): for x in range(4): rows[x].value(1 if x == r else 0) time.sleep_ms(2) # let the row drive settle before reading for c in range(4): if cols[c].value(): pressed.add(KEYS[r][c]) return pressed PIN = '1234' entry = '' msg = 'ENTER CODE' prev = set() def render(): fb.fill(0) fb.text('SECURE LOCK', 20, 2) fb.text('CODE: ' + '*' * len(entry), 8, 24) fb.text(msg, 8, 46) show() render() print('lock ready, enter code') while True: cur = scan() for k in cur - prev: # keys newly pressed since the last scan if k == '#': msg = 'UNLOCKED' if entry == PIN else 'DENIED' print('submit', entry, '->', msg) entry = '' elif k == '*': entry, msg = '', 'CLEARED' elif k in '0123456789': entry = (entry + k)[:8] msg = 'ENTER CODE' prev = cur render() time.sleep_ms(40)