The Raspberry Pi 3 GPIO pin layout features a 40-pin (2x20) header that exposes 3.3V logic, 5V power, ground, and specialized communication buses. The most critical rule before you wire anything: the GPIO pins operate at strictly 3.3V logic. Feeding a 5V signal into an input pin will bypass the internal ESD diodes and permanently destroy the BCM2837 SoC. This guide breaks down the physical layout, provides a safe hardware PWM build, and details the exact debugging steps for the most common runtime errors.
Parts List & Board Variants
This guide and the accompanying code specifically target the Raspberry Pi 3 Model B+ (featuring the BCM2837B0 SoC and 1GB RAM). The physical 40-pin layout is identical across the Pi 3 Model B, Pi 3 B+, Pi 4, and Pi 5, though the underlying SoC and power delivery architectures differ.
| Component | Exact Variant / Specification | Estimated Cost (2026) |
|---|---|---|
| Microcomputer | Raspberry Pi 3 Model B+ (1GB) | $35 - $45 (used/surplus) |
| Breakout Board | Adafruit Pi Cobbler+ (40-pin T-Cobbler) | $11.50 |
| Ribbon Cable | 40-pin GPIO ribbon cable (6-inch) | $4.00 |
| LED | 5mm Red LED (Forward Voltage ~2.0V, 20mA max) | $0.10 |
| Resistor | 330Ω through-hole (1/4W, 5% tolerance) | $0.05 |
| Switch | 6x6mm Tactile Pushbutton (SPST-NO) | $0.15 |
| Prototyping | 830-point solderless breadboard & jumper wires | $8.00 |
The Raspberry Pi 3 GPIO Pin Layout Decoded
When reading the Raspberry Pi 3 GPIO pin layout, you must distinguish between the Physical Pin Number (1 through 40, counting from the 3.3V pin nearest the SD card slot) and the BCM GPIO Number (the internal Broadcom SoC pin designation used in Python). Always orient the board with the USB ports facing you; the 3.3V pin is Pin 1 on the top left.
| Physical Pin | BCM GPIO | Function / Notes | Direction |
|---|---|---|---|
| 1 | - | 3.3V Power (Max 50mA total draw across all 3.3V pins) | Power |
| 2 | - | 5V Power (Tied directly to USB input rail) | Power |
| 3 | 2 | SDA1 (I2C Data) - Includes 1.8kΩ pull-up | Input/Output |
| 5 | 3 | SCL1 (I2C Clock) - Includes 1.8kΩ pull-up | Input/Output |
| 6 | - | Ground | Ground |
| 11 | 17 | GPIO 17 (General Purpose) | Input/Output |
| 12 | 18 | GPIO 18 (Hardware PWM0) - Used in our build | Output |
| 16 | 23 | GPIO 23 (General Purpose) - Used in our build | Input |
| 39 | - | Ground | Ground |
| 40 | 21 | GPIO 21 (General Purpose) | Input/Output |
RPi.GPIO library will fall back to software PWM, which causes visible flickering in LEDs and audible buzzing in piezo transducers due to CPU scheduling jitter.
Project Build: Fading an LED with Hardware PWM
This build uses BCM 18 (Physical Pin 12) for hardware PWM to smoothly fade an LED, and BCM 23 (Physical Pin 16) as an input to trigger the fade sequence via a pushbutton.
Wiring Steps
- Power Down: Disconnect the Pi 3 from its 5V micro-USB power supply. Never wire a breadboard while the Pi is energized.
- Connect the Breakout: Plug the 40-pin ribbon cable into the Pi's GPIO header, ensuring the red stripe (Pin 1) aligns with the 3.3V pin closest to the SD card slot. Connect the other end to the Pi Cobbler+ on the breadboard.
- Wire the LED Circuit: Connect a male-to-female jumper from the Cobbler's G18 pin to a breadboard row. Insert the 330Ω resistor across the bridge. Connect the anode (long leg) of the red LED to the resistor, and the cathode (short leg) to a ground rail.
- Wire the Button: Place the tactile switch across the breadboard center trench. Connect one side to the Cobbler's GND pin, and the opposite side to the Cobbler's G23 pin. (We will use the Pi's internal pull-up resistor in software, so no external pull-up is needed).
- Verify: Use a multimeter in continuity mode to verify there is no short between the 3.3V rail and the G18 output line before applying power.
Complete Python Code
This script targets the Raspberry Pi 3 Model B+ using the RPi.GPIO library. It includes explicit pin definitions, hardware PWM initialization, and robust exception handling to ensure the GPIO pins are cleaned up even if the script crashes.
import RPi.GPIO as GPIO
import time
import sys
# --- Pin Definitions (BCM Numbering) ---
LED_PWM_PIN = 18 # Physical Pin 12 (Hardware PWM0)
BUTTON_PIN = 23 # Physical Pin 16
def setup_gpio():
"""Initialize GPIO pins with explicit modes and pull-up configurations."""
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False) # Suppress 'channel in use' warnings for clean logs
# Configure LED pin as output
GPIO.setup(LED_PWM_PIN, GPIO.OUT, initial=GPIO.LOW)
# Configure Button pin as input with internal 50k pull-up resistor
# When pressed, the button connects to GND, pulling the pin LOW
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def main():
try:
setup_gpio()
except RuntimeError as e:
print(f"Setup failed: {e}")
sys.exit(1)
# Initialize Hardware PWM: 1000Hz frequency, 0% initial duty cycle
pwm = GPIO.PWM(LED_PWM_PIN, 1000)
pwm.start(0)
print("System ready. Press and hold the button to fade the LED. Ctrl+C to exit.")
try:
while True:
# Active LOW logic due to PUD_UP configuration
if GPIO.input(BUTTON_PIN) == GPIO.LOW:
# Fade in
for dc in range(0, 101, 2):
pwm.ChangeDutyCycle(dc)
time.sleep(0.02)
# Fade out
for dc in range(100, -1, -2):
pwm.ChangeDutyCycle(dc)
time.sleep(0.02)
else:
# Ensure LED is fully off when button is released
pwm.ChangeDutyCycle(0)
time.sleep(0.05) # Debounce / CPU yield
except KeyboardInterrupt:
print("\nInterrupt received. Shutting down gracefully.")
except RuntimeError as e:
print(f"Runtime error during execution: {e}")
finally:
# Critical: Always clean up to release hardware resources
pwm.stop()
GPIO.cleanup()
print("GPIO cleanup complete. Pins reset to safe input mode.")
if __name__ == '__main__':
main()
Debugging: First Three Things to Check When It Fails
When working with the Raspberry Pi 3 GPIO pin layout, hardware and software faults often present identically (the LED simply doesn't light up). Follow this ranked decision path when the script fails to execute or the hardware misbehaves.
1. The Exact Error: "RuntimeError: No access to /dev/mem"
Exact Error String: RuntimeError: No access to /dev/mem. Try running as root!
Ranked Causes & Fixes:
- Missing Sudo Privileges: The
RPi.GPIOlibrary requires direct memory mapping to the Broadcom SoC registers. Fix: Run your script withsudo python3 your_script.py. - User Not in GPIO Group: On newer Raspberry Pi OS builds, root isn't strictly required if permissions are set correctly. Fix: Add your user to the gpio group via
sudo usermod -aG gpio $USER, then log out and back in. - SPI/I2C Interface Conflicts: If the OS is holding the memory bus for an active hardware interface. Fix: Run
sudo raspi-configand disable unused interfaces under Interface Options.
2. The Exact Error: "This channel is already in use"
Exact Error String: RuntimeError: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
Ranked Causes & Fixes:
- Unclean Exit from Previous Run: You hit Ctrl+C or the script crashed before
GPIO.cleanup()could execute, leaving the pin flagged as active in the kernel. Fix: The warning is safe to ignore if you are intentionally re-initializing, which is why our code includesGPIO.setwarnings(False). - Pin Conflict with Another Process: A background daemon (like a fan controller or home automation service) is actively using BCM 18. Fix: Run
sudo lsof | grep gpioor checksystemctlto find and stop the conflicting service.
3. Hardware Fault: LED Stays Dim or Flickers
Symptom: The script runs without errors, but the LED only glows faintly or strobes erratically.
Ranked Causes & Fixes:
- Wrong Pin Selected (Software PWM Jitter): You wired the LED to BCM 17 instead of BCM 18, forcing the CPU to bit-bang the PWM signal. Fix: Move the physical wire to Physical Pin 12 (BCM 18) to utilize the SoC's dedicated PWM hardware block.
- Insufficient Current / Wrong Resistor: You used a 1kΩ or 10kΩ resistor instead of 330Ω, limiting current below the LED's visible threshold. Fix: Swap to a 220Ω or 330Ω resistor.
- Floating Ground: The breadboard ground rail isn't actually connected to the Pi Cobbler's GND pin. Fix: Verify continuity from the LED cathode to Physical Pin 6 (GND) with a multimeter.
Extending and Simplifying the Build
Once you have the base circuit working, you can adapt the project to fit your specific prototyping needs.
RPi.GPIO, switch to the gpiozero library. It abstracts pin setup and cleanup. You can replace the entire setup and loop with from gpiozero import PWMLED, Button and use led.pulse() when button.is_pressed. Note that gpiozero defaults to BCM numbering, aligning perfectly with our pin definitions.
How to Extend: To make this a standalone diagnostic tool, add a 128x64 I2C OLED display. Wire the display's SDA to Physical Pin 3 (BCM 2) and SCL to Physical Pin 5 (BCM 3). Using the Adafruit_SSD1306 Python library, you can read the current pwm.ChangeDutyCycle() value and render a real-time bar graph on the screen, eliminating the need for an external HDMI monitor during bench testing.
Frequently Asked Questions
What is the difference between the Raspberry Pi 3 Model B and B+ GPIO pin layout?
The 40-pin GPIO header layout is physically and electrically identical between the Pi 3 Model B and the Pi 3 Model B+. The BCM pin mapping, 3.3V/5V power pins, and I2C/SPI buses are in the exact same locations. The primary differences on the B+ are on the board itself: it features a 5-pin PoE (Power over Ethernet) header near the top right, improved thermal management via a metal heat spreader on the SoC, and upgraded Gigabit Ethernet (though bottlenecked by the USB 2.0 bus). Any HAT or ribbon cable designed for the 3B will fit the 3B+ perfectly.
Can I use the Raspberry Pi 3 GPIO pin layout for 5V sensors?
No, you cannot connect 5V logic outputs directly to the Raspberry Pi 3 GPIO pins. The BCM2837 SoC operates strictly at 3.3V logic. Feeding 5V into a GPIO pin will forward-bias the internal protection diodes, dumping excess current into the 3.3V rail and eventually destroying the SoC. To interface 5V sensors (like the HC-SR04 ultrasonic sensor or standard 5V Arduino modules), you must use a bidirectional logic level converter (such as a BSS138 MOSFET-based module) or a simple voltage divider using a 1kΩ and 2kΩ resistor to step the 5V signal down to a safe ~3.3V.
Where are the I2C and SPI pins on the Raspberry Pi 3 GPIO layout?
For standard I2C communication (I2C1 bus), use Physical Pin 3 (SDA / BCM 2) and Physical Pin 5 (SCL / BCM 3). These pins include onboard 1.8kΩ pull-up resistors to 3.3V. For standard SPI communication (SPI0 bus), the pins are Physical Pin 19 (MOSI / BCM 10), Physical Pin 21 (MISO / BCM 9), Physical Pin 23 (SCLK / BCM 11), and Physical Pin 24 (CE0 / BCM 8). A second chip enable is available on Physical Pin 26 (CE1 / BCM 7).
Why did my Raspberry Pi 3 die after connecting a 5V sensor to a GPIO pin?
This is the most common fatal mistake when learning the Raspberry Pi 3 GPIO pin layout. When a 5V source is applied to a 3.3V input pin, the voltage exceeds the SoC's absolute maximum ratings. The internal ESD (Electrostatic Discharge) clamp diodes attempt to shunt the excess voltage to the 3.3V rail. If the 5V source can supply more current than the diode can handle (usually >5mA), the diode burns out, shorting the pin to the 3.3V rail. This overvoltage event cascades through the power management IC (PMIC) and permanently kills the Broadcom processor. Always verify sensor logic levels with a multimeter before wiring them to the Pi.






