Tutorial 4 - Button Input
Introduction
In many electronic projects, buttons are a common way to provide user input.
In this tutorial, we’ll learn how to use a button with the ESP32-S3 Pico microcontroller board.
We’ll write a MicroPython program that reads the button’s state connected to one of the GPIO pins and prints a message when it is pressed.
YouTube Video
Components Needed
| Component | Quantity |
|---|---|
| ESP32-S3 Pico | 1 |
| USB-C Cable | 1 |
| Breadboard | 1 |
| Jumper Wires | Several |
| Push Button | 1 |
Fritzing Diagram - Active High

Code (Active High)
from machine import Pin
import utime
button = Pin(40, Pin.IN, Pin.PULL_DOWN)
while True:
if button.value() == 1:
print("You pressed the button!")
utime.sleep(1)
Fritzing Diagram - Active Low

Code (Active Low)
from machine import Pin
import utime
button = Pin(40, Pin.IN, Pin.PULL_UP)
while True:
if button.value() == 0:
print("You pressed the button!")
utime.sleep(1)
Code Explanation
from machine import Pin
import utime
We import the Pin class from the machine module to control the GPIO pins on the ESP32-S3 Pico,
and the utime module to add delays in the program.
button = Pin(40, Pin.IN, Pin.PULL_UP or Pin.PULL_DOWN)
This sets up Pin 40 as an input.
Pin.INmeans the pin is configured as an input.Pin.PULL_DOWNmeans the pin defaults to 0 (LOW) until pressed.Pin.PULL_UPmeans the pin defaults to 1 (HIGH) until pressed.
You can choose either setup depending on your circuit wiring.
while True:
if button.value() == 1:
print("You pressed the button!")
utime.sleep(1)
This infinite loop checks the button state:
- With PULL_DOWN, the button reads
1when pressed. - With PULL_UP, the button reads
0when pressed.
When pressed, it prints "You pressed the button!" and waits one second before checking again.
✅ The program will continuously monitor the button and react whenever you press it.
Knight Rider Code (Button Update)
In the previous tutorial, we built the Knight Rider / LiDAR Scanner effect using a row of LEDs that sweep left and right. Now, we’ll make it more interactive by adding two buttons that let us control the speed of the LED movement.

from machine import Pin
import utime
# LED pins left → right
LED_PINS = [33, 34, 35, 36, 37, 38, 39, 40]
# Delay between steps (starting value)
STEP_DELAY = 0.05
# Setup LEDs
leds = [Pin(p, Pin.OUT) for p in LED_PINS]
n = len(leds)
# Setup buttons (active-low with pull-ups)
btn_slower = Pin(17, Pin.IN, Pin.PULL_UP) # Button makes STEP_DELAY larger
btn_faster = Pin(18, Pin.IN, Pin.PULL_UP) # Button makes STEP_DELAY smaller
# Speed limits
MIN_DELAY = 0.01
MAX_DELAY = 0.3
STEP_CHANGE = 0.01 # amount to change per button press
def all_off():
for led in leds:
led.value(0)
def check_buttons():
global STEP_DELAY
if btn_slower.value() == 0: # pressed
STEP_DELAY = min(STEP_DELAY + STEP_CHANGE, MAX_DELAY)
utime.sleep(0.2) # debounce delay
if btn_faster.value() == 0: # pressed
STEP_DELAY = max(STEP_DELAY - STEP_CHANGE, MIN_DELAY)
utime.sleep(0.2) # debounce delay
while True:
# Left to right
for i in range(n):
check_buttons() # check before each step
all_off()
leds[i].value(1)
if i > 0:
leds[i-1].value(1)
utime.sleep(STEP_DELAY)
# Right to left
for i in range(n-1, -1, -1):
check_buttons()
all_off()
leds[i].value(1)
if i < n-1:
leds[i+1].value(1)
utime.sleep(STEP_DELAY)