- Distinguish physical header positions from BCM numbers.
- Wire a current-limited LED and a ground-switched button.
- Explain a pull-up input.
- Run and stop a GPIO Zero program.
- Test wiring separately from program behavior.
Before you begin
Run a Python file and understand voltage, resistance and ground. Use a Raspberry Pi 4 or 5 with Raspberry Pi OS and a 40-pin header, not a Pico.
A program can change a physical signal
A Python variable exists in memory. A GPIO output changes an electrical signal on a header pin. Connecting the two lets software switch an LED, but it also makes a mistaken instruction capable of affecting real hardware. Begin with an indicator, not a motor or household appliance.
A digital signal is interpreted as low or high. On this Pi circuit, high is approximately 3.3 V relative to ground; it is not an instruction to supply unlimited power. GPIO pins are signal connections with limited drive capability. Never feed 5 V into one or power a motor from one.
There are two numbering systems to keep separate. GPIO Zero uses BCM numbers when given plain integers. GPIO17 is physical pin 11, not physical pin 17. Write both names on your wiring plan and verify the board orientation against the official header diagram. Do not count from a photograph whose rotation is unknown.
Parts and complete connections
Shut down the Pi, disconnect its power and keep metal objects away from the board while assembling. This reference uses a red indicator LED and a 1 kΩ series resistor. The resistor limits current to a small value; the exact current depends on the LED’s forward voltage. LED brightness is not a measurement of GPIO safety.
Connect physical pin 11 (GPIO17) to the resistor, the resistor to the LED anode, and the LED cathode to physical pin 6 (ground). The longer lead is commonly the anode on an untrimmed LED; use the part’s marking or datasheet if uncertain. Reversing the LED usually prevents light, but removing the resistor is not a fix.
Connect one side of a normally-open momentary button to physical pin 13 (GPIO27), and the other side to pin 6 ground. A four-leg tactile button has two internally joined pairs: select opposite switch contacts, not two legs already joined. Check with an unpowered continuity test if you have a meter. Do not connect this button to the 5 V rail.
| Part | Purpose |
|---|---|
| Pi 4 or 5, configured OS and suitable supply | Runs Python and provides 3.3 V logic |
| Red LED and 1 kΩ resistor | Low-current output |
| Normally-open momentary button | Digital input |
| Breadboard and jumper wires | Temporary connections |
GPIO17 / pin 11 → 1 kΩ resistor → LED anode
LED cathode → GND / pin 6
GPIO27 / pin 13 → button → GND / pin 6Why the input does not float
An open button leaves a gap. Without a defined electrical path, the input could respond to noise instead of a deliberate press. A pull-up is a weak connection toward 3.3 V. GPIO Zero enables it here with pull_up=True, so the released input is high and pressing the button connects it to ground.
The convenient property is_pressed translates that electrical convention into a useful boolean: True means pressed even though the signal is low. This distinction explains why a circuit diagram and a program may use opposite-looking language without disagreeing.
Mechanical contacts can bounce, briefly opening and closing during one press. bounce_time suppresses rapid transitions. Debouncing helps an interface behave sensibly; it does not make a consumer button a certified emergency stop. Our polling loop deliberately waits between reads, so it does not consume a core doing unnecessary repeated checks.
Run the smallest complete program
On Raspberry Pi OS, install the packaged library with sudo apt update followed by sudo apt install python3-gpiozero python3-lgpio. Save this as button_light.py in your project directory, then run python3 button_light.py as your normal user. The supported pin backend depends on the board and installed OS; use current packages rather than copying old GPIO installation instructions.
GPIO Zero represents the LED and button as Python objects. The with statement closes them when the block exits. initial_value=False starts the LED off. The finally block requests off when you stop with Ctrl+C or an exception interrupts the loop. This is software cleanup, not protection against every possible power or hardware failure.
from gpiozero import LED, Button
from time import sleep
with LED(17, initial_value=False) as indicator, \
Button(27, pull_up=True, bounce_time=0.05) as button:
try:
while True:
indicator.value = button.is_pressed
sleep(0.02)
except KeyboardInterrupt:
pass
finally:
indicator.off()LED(17) selects BCM17. Button(27) selects BCM27, not header position 27. Assigning the boolean to indicator.value gives on while pressed and off while released. sleep leaves time for other work.
Expected result: No regular terminal output. The LED follows a held button; Ctrl+C exits. Unexpected behavior means stop and check before extending the circuit.
Prove one thing at a time
First inspect the unpowered circuit against the table. Check that the resistor is in series rather than accidentally bypassed by a breadboard row. Confirm that ground reaches both components. Breadboard power rails may be split in the middle; matching colors do not prove electrical continuity.
After powering up, test five short presses and one long press. Record whether the LED begins off, follows the input and goes off after release. Stop the program and check the final state. If it always stays on, inspect the button contact pairs before changing software.
An import error means the Python environment cannot find the library. A pin-factory or device-access error is different: the library loaded, but could not use GPIO. Confirm your Pi model, current OS packages and device permissions. Do not solve every error by running the program as administrator. A dark LED can still have valid code; distinguish software failures from connection or polarity faults.
The next useful modification is a toggle: one press changes state. It needs edge detection or a callback, otherwise a held button can toggle repeatedly. That change is a good way to see why inputs are events over time, not merely values you read once.
Important terms
- GPIO
- A configurable general-purpose electrical input or output.
- BCM number
- A GPIO signal identifier, distinct from its physical header position.
- Pull-up
- A weak connection that gives an otherwise-open input a high state.
- Debouncing
- Suppressing rapid switch-contact transitions during a press.
- Series resistor
- A resistor in the same current path as the LED.
Mini project: A reliable held-button indicator
- Label both pin numbering systems on a drawing.
- Wire the powered-off board exactly as specified.
- Run the program and record five presses and a held press.
- Stop with Ctrl+C and record the output state. Success means repeatable press/release behavior, not merely one flash.
Common mistakes and debugging
- Using physical pin 17 for LED(17): that position is a power pin, not BCM17. Recheck both labels.
- Connecting an LED without its resistor: disconnect power and add the series resistor.
- Choosing two permanently joined button legs: identify opposite contacts.
- Changing wiring with power applied: stop, shut down and unplug first.
Independent challenge
Design a toggle indicator on paper. Explain how you would recognize a new press instead of toggling every time the loop sees a held button.
Check your understanding: 10 questions
Which physical pin corresponds to GPIO17?
Is a Pi GPIO input 5 V tolerant?
Why include the LED resistor?
What does the pull-up do when the button is open?
Why can is_pressed be True when the voltage is low?
What causes switch bounce?
What is the purpose of sleep in the loop?
What does the finally block attempt?
What should you check if the LED never changes with the button?
Why is a toggle different from following a held button?
Quiz answers
Reveal all 10 answers after your attempt
- Physical pin 11 on the reference 40-pin header.
- No. Keep input signals within the supported 3.3 V logic range.
- It limits current through the LED and GPIO output.
- It gives the input a defined high state.
- The library translates the active-low wiring into a logical pressed state.
- Mechanical contacts briefly make and break contact during a transition.
- It limits polling frequency and avoids unnecessary busy work.
- Turning the indicator off before the device objects close.
- Pin numbers, button contact pairs, resistor path, polarity and common ground, with power removed before changes.
- A toggle must react once to a new press rather than repeatedly to the same held state.
Summary
You have connected a digital input to a limited electrical output. Correct pin numbering, current limiting and defined input states matter as much as the Python loop.
Continue learning
PI07 adds an analog-to-digital converter so the Pi can read a changing voltage, not only a button state.
- Connect Sensors to Raspberry Pi
- Read a Button and Control an LED
- Sensors, Actuators, Controllers, and Robot Software
Sources and further reading
Prepared 2026-09-19. Editorial draft. Primary documentation checked 19 September 2026. Code requires the stated Pi environment; no physical wiring, camera or performance test is claimed.
Extra reading & source documents
Optional reading alongside the lessons. These sources do not add to your course lesson count.
- Raspberry Pi: background and product familiesWikipedia reading