Button press detection in Raspberry Pi - Time & Space Complexity
When detecting button presses on a Raspberry Pi, the program often waits and checks repeatedly for input.
We want to understand how the time the program takes grows as it keeps checking for button presses.
Analyze the time complexity of the following code snippet.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
if GPIO.input(18) == GPIO.LOW:
print("Button pressed!")
time.sleep(0.2) # debounce delay
This code continuously checks if a button connected to pin 18 is pressed and prints a message when it is.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that repeatedly reads the button state.
- How many times: It runs indefinitely, checking the button many times per second.
As time passes, the program keeps checking the button state over and over.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 (seconds) | Many repeated checks, about 5 per second, so ~50 checks |
| 100 (seconds) | About 500 checks |
| 1000 (seconds) | About 5000 checks |
Pattern observation: The number of checks grows directly with time passed, increasing steadily.
Time Complexity: O(n)
This means the program's work grows linearly with how long it runs, checking the button repeatedly.
[X] Wrong: "The button check only happens once, so time doesn't grow with input."
[OK] Correct: The code uses a loop that runs forever, so it keeps checking many times, making the work grow with time.
Understanding how repeated checks affect program time helps you explain how real devices respond to inputs over time.
What if we changed the code to use an interrupt instead of a loop? How would the time complexity change?
Practice
Solution
Step 1: Understand pull-up resistor behavior
A pull-up resistor keeps the input pin at a HIGH voltage level by default.Step 2: Detect button press effect on pin
When the button is pressed, it connects the pin to ground, making the input LOW.Final Answer:
It keeps the pin at HIGH until the button connects it to LOW when pressed. -> Option AQuick Check:
Pull-up resistor means default HIGH, press pulls LOW [OK]
- Thinking pull-up sets pin LOW by default
- Confusing input with output pin modes
- Assuming button press sets pin HIGH
Solution
Step 1: Identify pin mode for button input
Button pins must be set as input to read their state.Step 2: Add pull-up resistor parameter
Use pull_up_down=GPIO.PUD_UP to enable internal pull-up resistor.Final Answer:
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP) -> Option AQuick Check:
Input pin with pull-up resistor = GPIO.IN + PUD_UP [OK]
- Using GPIO.OUT instead of GPIO.IN
- Omitting pull_up_down parameter
- Setting pull-up resistor on output pin
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
if GPIO.input(18) == GPIO.LOW:
print("Button Pressed")
else:
print("Button Not Pressed")
Solution
Step 1: Understand pin setup and input reading
Pin 18 is set as input with pull-up resistor, so default is HIGH.Step 2: Check condition when button is pressed
Pressing button pulls pin LOW, so condition GPIO.input(18) == GPIO.LOW is True.Final Answer:
Button Pressed -> Option DQuick Check:
Pressed button pulls pin LOW, prints "Button Pressed" [OK]
- Assuming pressed button reads HIGH
- Confusing pull-up with pull-down resistor
- Expecting syntax or runtime errors
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
if GPIO.input(23) == GPIO.HIGH:
print("Button Pressed")
time.sleep(0.1)
Solution
Step 1: Review button wiring and logic
With pull-up resistor, button press pulls pin LOW, not HIGH.Step 2: Check condition in if statement
Code incorrectly checks for GPIO.HIGH to detect press; should check GPIO.LOW.Final Answer:
The code should check for GPIO.LOW to detect button press. -> Option CQuick Check:
Pull-up input reads LOW when pressed, so check GPIO.LOW [OK]
- Checking for HIGH instead of LOW on button press
- Forgetting pull_up_down parameter
- Misplacing sleep causing missed presses
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
pressed = False
while True:
if GPIO.input(21) == GPIO.LOW and not pressed:
print("Pressed")
pressed = True
elif GPIO.input(21) == GPIO.HIGH:
pressed = False
time.sleep(0.05)
Solution
Step 1: Understand the pressed flag usage
The variable 'pressed' tracks if the button press was already detected to avoid repeats.Step 2: Analyze the if-elif logic
When button is LOW and not pressed, it prints once and sets pressed True; when released (HIGH), resets pressed to False.Final Answer:
This code prints "Pressed" once per press and avoids repeats while held. -> Option BQuick Check:
pressed flag prevents multiple prints during hold [OK]
- Printing inside loop without flag causes repeated prints
- Not resetting flag on button release
- Syntax errors from missing colons or indentation
Ready to prove it?
Pass the test and this pattern moves unknown
