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
Bench Tip: Only BCM 18 and BCM 19 support true hardware PWM on the Pi 3. If you attempt hardware PWM on other pins, the 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

  1. Power Down: Disconnect the Pi 3 from its 5V micro-USB power supply. Never wire a breadboard while the Pi is energized.
  2. 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.
  3. 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.
  4. 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).
  5. 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:

  1. Missing Sudo Privileges: The RPi.GPIO library requires direct memory mapping to the Broadcom SoC registers. Fix: Run your script with sudo python3 your_script.py.
  2. 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.
  3. SPI/I2C Interface Conflicts: If the OS is holding the memory bus for an active hardware interface. Fix: Run sudo raspi-config and 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:

  1. 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 includes GPIO.setwarnings(False).
  2. 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 gpio or check systemctl to 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:

  1. 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.
  2. 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.
  3. 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.

How to Simplify: If you want to eliminate the boilerplate of 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.