Python & GPIO: code meets circuit
420-302-VA · WEEK 4 · FALL 2026

Stage 4 of 6 · Theory, kit on the bench · about 20 minutes

GPIO, safely

This is the page where your electronics training takes over. A GPIO pin is a wire your code controls; everything you know about voltage, current and Ohm's law applies to it directly, including the ways to damage things. Learn the rules before touching the header.

What a pin is, electrically

Recall the 40-pin header from Week 2's hardware tour. Besides power (3.3 V, 5 V) and ground pins, most of them are GPIO: general-purpose pins the SoC can configure, per pin, in software, as either:

  • Output. The pin is driven to 3.3 V ("high", logic 1) or 0 V ("low", logic 0). It can source or sink a few milliamps: enough for an LED or a logic signal, nothing more. led.on() is, literally, "drive GPIO17 high".
  • Input. The pin measures the voltage applied to it and reports it to your code as 1 (near 3.3 V) or 0 (near 0 V). It draws essentially no current; it listens.

That is the whole interface between the semester's software and hardware halves: your Python sets or reads pin states; your circuits give those states meaning. Bigger loads (the relay switching a lamp in the project, motors) are never driven from a pin directly; the pin's few milliamps instead switch a transistor or relay module that carries the real current, exactly as a PLC output card does.

The hard rules

Five rules that protect the Pi and your grade

1. 3.3 V logic, never 5 V. The GPIO pins are not 5 V tolerant. The 5 V pins power external modules; 5 V on a GPIO pin can kill the pin or the SoC, and there is no fuse in between. 2. Every LED gets a series resistor. No exceptions; the math is below. 3. Respect the current budget. Treat roughly 8 mA per pin as the design norm, 16 mA as the ceiling, and about 50 mA across all GPIO pins combined. 4. Never short 3.3 V or 5 V to ground, including via a wire "just to test". 5. Rewire with outputs off. Stop the script (Ctrl+C) before changing the circuit; for anything beyond swapping a jumper, power down. The habit that catches most mistakes before they cost hardware: trace your circuit against the diagram once, aloud, before running code, the same discipline as pre-power checks in the automation lab.

The LED circuit, with the math

Schematic: GPIO17 drives a 330 ohm resistor in series with an LED whose cathode returns to ground. About 1.3 volts drop across the resistor gives roughly 4 milliamps. GPIO17 physical pin 11 3.3 V when on 330 Ω either leg is fine LED long leg (anode) toward the resistor GND physical pin 6 (or 9, 14, ...)
One pin, one resistor, one LED, ground. The resistor's position (before or after the LED) does not matter; series current is the same everywhere. The LED's orientation does: long leg toward the positive side.

The resistor exists because an LED is a diode, not a lamp: past its forward voltage it conducts almost without limit, and either the LED or the pin loses. The series resistor sets the current, and it is one line of Ohm's law:

Pin drives 3.3 V.  A red LED drops about V_f ≈ 2.0 V.  The resistor takes the rest:
V_R = 3.3 − 2.0 = 1.3 V
I = V_R / R = 1.3 V / 330 Ω ≈ 3.9 mA

About 4 mA: comfortably bright for a modern LED, comfortably inside the pin's budget. This is why the kit says 330 Ω, and why any value from 220 Ω (≈ 6 mA) to 1 kΩ (≈ 1.3 mA, dimmer) also works. Run the numbers once yourself for a 220 Ω resistor; the midterm may ask precisely this.

Inputs: floating pins and pull resistors

Outputs are simple; inputs have one trap. A push button is just a gap that closes. Wire it naively, pin to button to ground, and while the button is up the pin is connected to nothing: it floats, picking up whatever stray voltage the air and your hand offer, and reads random 0s and 1s. Every digital input needs a defined idle level, supplied by a pull resistor:

  • A pull-up ties the pin gently to 3.3 V: idle reads 1, pressing the button (to ground) reads 0.
  • A pull-down ties it gently to 0 V: idle reads 0, pressing (to 3.3 V) reads 1.

The Pi has both built in, selectable per pin in software, which is why your button needs no external resistor at all: gpiozero's Button(27) enables the internal pull-up and expects the button between GPIO27 and ground. Idle 1, pressed 0, and the library even flips the logic so is_pressed reads naturally. One more analog reality your training predicts: a mechanical contact bounces, closing and opening for a few milliseconds before settling. Naive code would count one press as several; gpiozero can debounce in software (bounce_time), and the next page shows it.

Two numbering systems

The most common wiring error this week is not electrical; it is administrative. Every pin has two names:

SystemWhat it countsExampleWho uses it
Physical (board)Position on the header: 1 to 40, pin 1 at the corner marked by the square padpin 11Your fingers, wiring diagrams
BCM (GPIO)The SoC's channel number printed as "GPIOxx"GPIO17 is physical pin 11gpiozero and this course's code

The pins this week, all near the top of the header: GPIO17 = physical 11 (LED), GPIO27 = physical 13 (button), ground at physical 6, 9 or 14, and 3.3 V at physical 1 (which you will not need today). Two references keep this straight at the bench: the interactive map at pinout.xyz, and the pinout command that gpiozero installs on the Pi, which draws your own board's header in the terminal. The authoritative electrical description lives in the official Raspberry Pi hardware documentation.

Checklist for this stage

Check yourself

Why is 5 V the one voltage that must never touch a GPIO pin?
The pins are 3.3 V logic and not 5 V tolerant; overvoltage can permanently damage the pin or the SoC, with no protective fuse in the path. The 5 V header pins exist only to power external modules.
Derive the LED current for a 220 Ω resistor and judge it.
I = (3.3 − 2.0) / 220 ≈ 5.9 mA. Brighter than 330 Ω's 3.9 mA and still well under the 16 mA ceiling: acceptable, and the reasoning is the answer, not the number.
Why does the button need no external resistor?
gpiozero's Button enables the Pi's internal pull-up on that pin, so it idles at a defined 1; pressing connects it to ground for a clean 0. The defined idle level is the whole job of a pull resistor.
Your code says LED(17) but you wired physical pin 17. What happens, and what was meant?
The code drives GPIO17, which is physical pin 11; physical 17 is a 3.3 V power pin, so the LED never blinks (and wiring an output to 3.3 V invites rule trouble). BCM in code, physical at the fingers, translated deliberately every time.
Why can the pin not drive the project's lamp relay coil directly, and what is the professional pattern?
A pin offers milliamps at 3.3 V; coils and motors want far more. The pin instead switches a driver, a transistor stage or a relay module with its own supply, exactly like a PLC output card switching field loads.