If you need to know what Raspberry Pi do I have right this second, open your terminal and type cat /proc/cpuinfo | grep Revision. You will see a hex code (like c03112 or d04170). Cross-reference that code with the official Raspberry Pi revision code table to find your exact model, RAM size, and manufacturer.

But if you are building a headless kiosk, an automated test jig, or a fleet of IoT nodes, manually checking terminal outputs is not scalable. You need a programmatic way to identify the board variant on boot and verify that the GPIO header is actually functional. In this guide, we will build a Python-based Pi Model Identifier and GPIO Hardware Tester that reads the silicon revision code, prints the exact hardware specs, and flashes an LED to confirm the pinout is intact.

Project Spec Sheet & Parts List

ParameterSpecification
Difficulty Rating2/5 (Beginner-Intermediate)
Estimated Time45 minutes
Target Board VariantRaspberry Pi 4 Model B (4GB) & Raspberry Pi 5 (8GB)
OS RequirementRaspberry Pi OS Bookworm (64-bit) or later
Python VersionPython 3.11+ (Pre-installed on Bookworm)

Required Hardware

  • Microcontroller: Raspberry Pi 4 Model B (any RAM variant) or Raspberry Pi 5. The code is backward compatible to the Pi 3B+.
  • Storage: SanDisk Extreme 32GB microSD card (A2 application performance class for faster random I/O during boot).
  • Power Supply: 5V 3A USB-C PSU for Pi 4, or an official 27W USB-C PD (5V 5A) PSU for Pi 5. Note: Using a standard 5V 3A phone charger on a Pi 5 will trigger a low-voltage warning and limit USB peripheral current to 600mA.
  • Component: 1x 5mm standard LED (any color, 20mA max forward current).
  • Resistor: 1x 330Ω through-hole resistor (1/4W).
  • Wiring: 2x Female-to-Male (F-M) jumper wires.

Pin Mapping & Hardware Setup

We are using BCM (Broadcom) pin numbering, which is the standard for modern Raspberry Pi OS environments. Do not use physical board pin numbers (1-40) in the software configuration.

Component LegBCM GPIO / PowerPhysical Pin #Wire Color (Suggested)
LED Anode (Long Leg)GPIO 18 (PWM capable)12Orange
Resistor (Inline)N/A (Series with Cathode)N/AN/A
LED Cathode (Short Leg)GND14Black
Bench Tip: Always place the current-limiting resistor on the cathode (negative) side of the LED when wiring to a Pi. While electrically it works on either side, keeping the anode direct to the GPIO pin makes it easier to troubleshoot with a multimeter if the pin fails to drive high.

Wiring Steps

  1. De-energize the board: Unplug the USB-C power cable from the Raspberry Pi before touching the GPIO header.
  2. Connect the GPIO pin: Plug the female end of your orange jumper wire into Physical Pin 12 (BCM GPIO 18). Connect the male end to the breadboard row containing the LED anode.
  3. Insert the resistor: Plug one leg of the 330Ω resistor into the same row as the LED cathode, and the other leg into an empty ground rail row.
  4. Connect Ground: Plug the female end of your black jumper wire into Physical Pin 14 (GND). Connect the male end to the breadboard ground rail sharing the resistor.
  5. Verify: Visually trace the circuit from GPIO 18 -> LED Anode -> LED Cathode -> Resistor -> GND. Ensure the LED is not inserted backward.
  6. Power up: Reconnect the USB-C PSU and boot into the Raspberry Pi OS desktop or SSH terminal.

The Identifier & GPIO Test Code

This script targets Raspberry Pi OS Bookworm and utilizes the gpiozero library, which is the recommended GPIO interface for modern Pi environments. It reads the raw hex revision code from /proc/cpuinfo, maps it to a human-readable model name, and pulses the LED to confirm hardware continuity.

import os
import sys
import time
from gpiozero import LED
from gpiozero.exc import GpioZeroError

# --- PIN DEFINITIONS ---
# Using BCM GPIO 18 (Physical Pin 12)
TEST_LED_PIN = 18
led = None

# --- REVISION CODE LOOKUP TABLE ---
# Sourced from official Raspberry Pi documentation
REVISION_MAP = {
    'a03111': 'Raspberry Pi 4 Model B - 1GB',
    'b03111': 'Raspberry Pi 4 Model B - 2GB',
    'c03111': 'Raspberry Pi 4 Model B - 4GB',
    'c03112': 'Raspberry Pi 4 Model B - 4GB (Rev 1.2)',
    'd03114': 'Raspberry Pi 4 Model B - 8GB',
    'c04170': 'Raspberry Pi 5 - 4GB',
    'd04170': 'Raspberry Pi 5 - 8GB',
    'a22082': 'Raspberry Pi 3 Model B',
    'a020d3': 'Raspberry Pi 3 Model B+',
    '902120': 'Raspberry Pi Zero 2 W'
}

def get_pi_revision_code():
    try:
        with open('/proc/cpuinfo', 'r') as f:
            for line in f:
                if line.strip().startswith('Revision'):
                    return line.strip().split(':')[1].strip().lower()
    except FileNotFoundError:
        return None
    except PermissionError:
        return 'PERMISSION_DENIED'
    return 'UNKNOWN'

def identify_board():
    print('--- Raspberry Pi Hardware Identifier ---')
    rev_code = get_pi_revision_code()
    
    if rev_code == 'PERMISSION_DENIED':
        print('Error: Cannot read /proc/cpuinfo. Check file permissions.')
        return
    
    if rev_code and rev_code in REVISION_MAP:
        model_name = REVISION_MAP[rev_code]
        print(f'[SUCCESS] Hex Revision: {rev_code}')
        print(f'[SUCCESS] Identified Board: {model_name}')
    else:
        print(f'[WARNING] Hex Revision: {rev_code}')
        print('[WARNING] Board not in local lookup table. Check official docs.')

def test_gpio_hardware():
    global led
    print('\n--- GPIO Hardware Continuity Test ---')
    try:
        led = LED(TEST_LED_PIN)
        print(f'Initializing BCM GPIO {TEST_LED_PIN}...')
        
        # Pulse 3 times to verify physical connection
        for i in range(3):
            led.on()
            time.sleep(0.4)
            led.off()
            time.sleep(0.2)
            
        print('[SUCCESS] GPIO pin drove HIGH successfully. LED flashed 3 times.')
        print('Hardware header is functional.')
        
    except GpioZeroError as e:
        print(f'[FATAL] GPIO Initialization Failed: {e}')
        print('First 3 things to check:')
        print('1. Is the user in the gpio group? (Run: sudo usermod -aG gpio $USER)')
        print('2. Are you using an outdated RPi.GPIO library on Pi OS Bookworm?')
        print('3. Is the physical pin bent or shorted to the metal shield?')
    except ValueError as e:
        print(f'[FATAL] Invalid Pin Configuration: {e}')
    except Exception as e:
        print(f'[FATAL] Unexpected Error: {e}')

if __name__ == '__main__':
    try:
        identify_board()
        test_gpio_hardware()
    except KeyboardInterrupt:
        print('\nTest interrupted by user.')
    finally:
        if led is not None:
            led.close()
        print('\nCleanup complete. GPIO resources released.')

Debugging: Common GPIO & Identification Errors

When working with bare-metal hardware access on Linux, permissions and library transitions are the most common failure points. If your script crashes, look for these exact error strings.

Error 1: 'PermissionError: [Errno 13] Permission denied: /dev/gpiomem'

This is the most common error on Raspberry Pi OS Bookworm when a standard user attempts to access the GPIO memory registers without proper group assignments.

  • Cause 1 (Most Likely): Your current user is not in the gpio or dialout system groups. Fix: Run sudo usermod -aG gpio $USER and reboot the Pi.
  • Cause 2: You are running the script via a cron job or systemd service that defaults to the root or nobody user without inheriting the environment. Fix: Add User=pi (or your specific username) to your .service file.
  • Cause 3: You are using an ancient version of the RPi.GPIO library which attempts to access /dev/mem instead of the safer /dev/gpiomem. Fix: Uninstall RPi.GPIO and switch entirely to gpiozero with the lgpio backend.

Error 2: 'ValueError: A physical pin is not a valid GPIO pin'

This error occurs when the pin factory receives a number it cannot map to the Broadcom SOC GPIO matrix.

  • Cause 1 (Most Likely): You passed a physical board pin number (e.g., 12 for physical pin 12) but the library expects the BCM number (which is 18 for physical pin 12). Fix: Ensure you are using BCM numbering. Physical pin 12 = BCM GPIO 18.
  • Cause 2: You are trying to use a power pin (like Physical Pin 1 / 3V3) as a programmable GPIO output. Fix: Only use pins designated as GPIO in the pinout diagram.

Extending and Simplifying the Build

How to Extend: Add an I2C OLED Display

If you are building a headless node and want to display the Pi model and IP address without SSH-ing in, extend this build by adding a 128x64 SSD1306 I2C OLED display. Wire the display's VCC to 3V3 (Physical Pin 1), GND to GND (Physical Pin 6), SDA to GPIO 2 (Physical Pin 3), and SCL to GPIO 3 (Physical Pin 5). Install the adafruit-circuitpython-ssd1306 library via pip, and modify the identify_board() function to push the model_name string to the display buffer instead of just printing to the console.

How to Simplify: The Bash-Only Approach

If you do not need the GPIO hardware test and only want to identify the board in a startup script, strip out the Python code entirely. Use the native vcgencmd tool or standard shell parsing:

#!/bin/bash
# Simple Pi Identifier
REVISION=$(cat /proc/cpuinfo | grep 'Revision' | awk '{print $3}')
echo 'Board Hex Revision: '$REVISION
cat /proc/device-tree/model
echo ''

This bash snippet reads the device tree model string directly, which outputs human-readable text like 'Raspberry Pi 5 Model B Rev 1.0' without needing a Python dictionary lookup.

Frequently Asked Questions

How can I tell what Raspberry Pi I have without turning it on?

Look at the physical board layout and silkscreen text. If the board has blue USB ports, it is a Raspberry Pi 4. If it has a large metal shield over the CPU, a PCIe connector on the bottom left, and a small J5 connector for an RTC battery, it is a Raspberry Pi 5. If it has yellow composite video (RCA) jacks and black USB ports, it is a Pi 3B+ or older. Finally, check the white silkscreen text near the GPIO header; it usually explicitly states 'Raspberry Pi 4 Model B' or similar.

What Raspberry Pi do I have if the board has no markings or the silkscreen is faded?

Count the RAM chips on the top or bottom of the board and check the main processor silkscreen. A Pi 1 has 26 GPIO pins (early models) or 40 pins with a Broadcom BCM2835. A Pi Zero is half the size with a single micro-USB port. If you have a bare compute module (CM4), look for the two high-density board-to-board connectors on the back. When in doubt, power it up with a monitor attached; the boot splash screen will display the exact RAM and model variant.

Why does my Pi 5 show up as a generic BCM2712 in older scripts?

The Raspberry Pi 5 uses the new BCM2712 silicon, which features a completely different southbridge architecture (RP1 chip) compared to the BCM2711 in the Pi 4. Older Python libraries like RPi.GPIO were hardcoded to look for BCM283x/2711 memory addresses. When they fail to find the expected registers, they either crash or fallback to generic identifiers. Always use gpiozero with the lgpio backend on a Pi 5 to ensure the RP1 chip is addressed correctly via the standard Linux libgpiod API.

How do I check my Raspberry Pi model in Windows IoT or Ubuntu Server?

On Ubuntu Server, the cat /proc/cpuinfo command works exactly as it does on Raspberry Pi OS. On Windows IoT Core, open PowerShell and run Get-ComputerInfo | Select-Object CsModel, or check the 'Device Portal' web interface by navigating to the Pi's IP address on port 8080 in your browser. Note that Windows IoT is largely deprecated for newer Pi models, and Ubuntu Server is the recommended alternative for non-Raspbian Linux environments.