The 40-Pin Header: Reading the Raspberry Pi Pins Diagram for the Pi 5
When you look at a raspberry pi pins diagram, you are looking at a 40-pin header that contains 26 general-purpose I/O (GPIO) pins, 4 power pins (two 5V, two 3.3V), and 8 ground pins. For this guide, we are targeting the Raspberry Pi 5 (8GB variant). The physical 40-pin layout is backward-compatible with the Pi 4, but the underlying silicon has changed: the Pi 5 uses the custom RP1 southbridge chip. This means legacy libraries like RPi.GPIO are deprecated and will throw module errors. You must use gpiozero for modern Pi 5 development.
Below is the specific pin mapping we will use for our I2C sensor and GPIO status indicator project. Always count pins starting from the top-left (Pin 1, 3.3V) with the USB ports facing you.
| Physical Pin | BCM GPIO | Function | Wire Color (Standard) |
|---|---|---|---|
| 1 | N/A | 3.3V Power (Sensor VCC) | Red |
| 3 | GPIO 2 | I2C1 SDA (Sensor Data) | Blue |
| 5 | GPIO 3 | I2C1 SCL (Sensor Clock) | Yellow |
| 6 | N/A | Ground (Sensor GND) | Black |
| 11 | GPIO 17 | Status LED Output | Green |
| 13 | GPIO 27 | Tactile Button Input | Orange |
| 9 | N/A | Ground (Button/LED GND) | Black |
Project Build: I2C BME280 Sensor with GPIO Status Indicator
Instead of just memorizing a chart, the best way to understand the diagram is to wire a circuit. We are building an I2C bus scanner that verifies a BME280 environmental sensor's connection and signals success or failure via an LED.
Parts List
- Board: Raspberry Pi 5 (8GB)
- Sensor: BME280 I2C breakout module (Adafruit 2652 or generic equivalent)
- Indicator: 5mm Red LED with a 330Ω current-limiting resistor
- Input: 6x6mm tactile pushbutton switch
- Wiring: Female-to-female and male-to-female jumper wires (24 AWG)
Wiring Steps
- De-energize: Ensure the Pi 5 is powered off and unplugged from the USB-C supply.
- Power the Sensor: Connect Physical Pin 1 (3.3V) to the BME280
VINorVCC. Connect Physical Pin 6 (GND) to the BME280GND. - I2C Data Lines: Connect Physical Pin 3 (SDA) to BME280
SDI/SDA. Connect Physical Pin 5 (SCL) to BME280SCK/SCL. - LED Circuit: Connect Physical Pin 11 (GPIO 17) to the anode (long leg) of the LED. Connect the cathode to the 330Ω resistor, and the other end of the resistor to Physical Pin 9 (GND).
- Button Circuit: Connect one leg of the tactile switch to Physical Pin 13 (GPIO 27). Connect the opposite diagonal leg to Physical Pin 6 or 9 (GND). Note: The Pi's internal pull-up resistor will be enabled in software, so no external pull-up is needed.
Complete Python Code
This script uses gpiozero (the modern standard for Pi 5) and smbus2 to read the BME280's hardware ID register. Install dependencies via terminal: sudo apt install python3-gpiozero python3-smbus2 i2c-tools.
import smbus2
import time
from gpiozero import LED, Button
from signal import pause
# --- PIN DEFINITIONS (BCM Numbering) ---
LED_PIN = 17
BUTTON_PIN = 27
I2C_BUS = 1
BME280_ADDR = 0x76 # Check your module; some default to 0x77
BME280_CHIP_ID_REG = 0xD0
EXPECTED_CHIP_ID = 0x60
# --- HARDWARE SETUP ---
status_led = LED(LED_PIN)
trigger_button = Button(BUTTON_PIN, pull_up=True)
bus = smbus2.SMBus(I2C_BUS)
def verify_sensor_connection():
"""Reads the BME280 Chip ID register to verify I2C wiring."""
try:
chip_id = bus.read_byte_data(BME280_ADDR, BME280_CHIP_ID_REG)
if chip_id == EXPECTED_CHIP_ID:
print(f"[SUCCESS] BME280 detected on bus {I2C_BUS}. Chip ID: {hex(chip_id)}")
status_led.blink(0.5, 0.5, 3) # Blink 3 times for success
else:
print(f"[WARNING] Device found at {hex(BME280_ADDR)} but returned wrong ID: {hex(chip_id)}")
status_led.on() # Solid on for wrong chip
except OSError as e:
# This catches the exact I2C failure string
print(f"[CRITICAL ERROR] {e}")
print("Action required: Check SDA/SCL wiring and run 'i2cdetect -y 1'")
status_led.blink(0.1, 0.1) # Fast strobe for hardware fault
# Bind the function to the button press
trigger_button.when_pressed = verify_sensor_connection
print("System initialized. Press the tactile button to scan the I2C bus...")
try:
pause() # Keep script running efficiently
except KeyboardInterrupt:
print("\nExiting safely.")
status_led.off()
bus.close()
Debugging: When Your Wiring Doesn't Match the Diagram
If your physical wiring deviates even slightly from the raspberry pi pins diagram, I2C will fail silently at the hardware level and throw an exception in Python. The most common failure you will encounter is:
OSError: [Errno 121] Remote I/O error
This exact string means the Pi's I2C controller sent a clock signal and address, but received no acknowledgment (ACK) bit back from the sensor. Here are the ranked causes and how to fix them:
- Swapped SDA and SCL Lines: I2C is not bidirectional on a single wire. SDA (Data) must go to SDA, and SCL (Clock) to SCL. Swap the blue and yellow jumper wires on the breadboard.
- Wrong I2C Address: Generic BME280 modules often have an
SDOpin. If pulled high, the address is0x76. If pulled low, it's0x77. Change theBME280_ADDRvariable in the code to match your board. - Missing Pull-Up Resistors: I2C requires pull-up resistors on SDA and SCL. Most breakout boards include 4.7kΩ onboard, but if you are using a bare sensor chip, you must add them to the 3.3V rail.
- Using the Wrong I2C Bus: The Pi has multiple I2C buses. Bus 1 (Pins 3 & 5) is the default for user space. Ensure
I2C_BUS = 1in your code.
The First Three Things to Check When It Fails
Before rewriting code, run this physical and terminal checklist:
- Run the bus scan: Open terminal and type
i2cdetect -y 1. If you see a grid of dashes with no numbers (like76or77), your wiring is physically broken or the sensor is dead. - Verify Power Rail Continuity: Use a multimeter in DC voltage mode. Place the black probe on Pin 6 (GND) and the red probe on the sensor's VCC pin. You must read between 3.2V and 3.4V. If you read 0V, your jumper wire is internally snapped.
- Check I2C Interface Enablement: On Pi 5, I2C is usually enabled by default, but if
i2cdetectreturns "No such file or directory", runsudo raspi-config, navigate to Interface Options > I2C, and enable it.
Extending and Simplifying the Build
Once you have verified the raspberry pi pins diagram mapping and the I2C bus is stable, you can scale this project.
How to Simplify
If you only need headless data logging, strip out the gpiozero LED and Button imports. Replace the button trigger with a simple while True: loop with a time.sleep(60) to log the sensor's raw ID or temperature data to a CSV file every minute. This reduces the component count to just the Pi and the sensor.
How to Extend
To add a visual display without using more GPIO pins, daisy-chain an I2C OLED screen (like the SSD1306 128x64). Because I2C is a bus protocol, you can wire the OLED's SDA and SCL to the exact same Physical Pins 3 and 5. The Pi will differentiate them by their unique hex addresses (the SSD1306 is typically 0x3C). You will need to update the official Raspberry Pi hardware documentation to confirm bus capacitance limits if you chain more than three devices.
Frequently Asked Questions About the Raspberry Pi Pinout
Are the Raspberry Pi 5 pins the same as the Pi 4 diagram?
Physically, yes. The 40-pin header layout, physical pin numbers, and BCM GPIO assignments for basic I/O and I2C1 are identical between the Pi 4 and Pi 5. However, the Pi 5's RP1 chip handles the GPIO routing differently at the silicon level. While the diagram looks the same, software written for the Pi 4 using the legacy RPi.GPIO library will fail on the Pi 5. Always use gpiozero for cross-compatibility.
Which pins on the Raspberry Pi diagram are safe for 5V logic?
None of the GPIO pins are 5V tolerant. The Raspberry Pi operates on a strict 3.3V logic level for all data, I2C, SPI, and UART pins. The only pins that carry 5V are Physical Pins 2 and 4 (the 5V power rail), which are used to power the board or draw current for high-draw peripherals, not for logic communication. If you need to interface a 5V sensor (like an HC-SR04 ultrasonic sensor), you must use a logic level converter or a voltage divider on the Pi's RX line.
Why does my Raspberry Pi pins diagram show two different numbering schemes?
You will see "Physical" (Board) numbering and "BCM" (Broadcom) numbering. Physical numbering simply counts 1 through 40 sequentially down the header. BCM numbering refers to the internal GPIO channel numbers mapped by the silicon (e.g., Physical Pin 3 is BCM GPIO 2). In Python, gpiozero defaults to BCM numbering. Always write your code using BCM numbers, but use Physical numbers when physically plugging in wires to avoid frying the board.






