If your Raspberry Pi is not detecting your keyboard, the fix depends entirely on the physical interface. For standard USB keyboards, 90% of detection failures trace back to voltage sag on the 5V rail or a tripped USB polyfuse. For custom GPIO matrix keypads used in embedded kiosk projects, failures almost always stem from floating pin states, missing pull-up resistors, or matrix ghosting. This guide covers the exact diagnostic steps, kernel error strings, and Python code needed to get your input devices registering correctly on the Raspberry Pi 4 Model B and Raspberry Pi 5.

The First Three Things to Check When Detection Fails

Before swapping out hardware or rewriting code, perform these three baseline electrical and software checks to isolate the fault domain.

  1. Measure the 5V Rail Under Load: Set your multimeter to DC voltage. Probe Pin 2 (5V) and Pin 6 (Ground) on the GPIO header while the Pi is booted and the keyboard is plugged in. The reading must be >4.75V. If it drops below 4.65V, the Pi's USB controller will brownout and drop the device. This is incredibly common with mechanical keyboards featuring RGB lighting, which can draw 500mA+ on their own.
  2. Inspect Kernel Enumeration Logs: Open a terminal (or SSH in) and run sudo dmesg | grep -i usb. The Linux kernel will log the exact reason a device was rejected at the hardware level. Look for the specific error strings detailed in the table below.
  3. Verify GPIO Continuity (For Matrix Keypads): If you are using a bare membrane keypad wired to the GPIO header, power down the Pi. Use the continuity/beep function on your DMM to probe from the membrane tail connector to the physical GPIO pin header. Membrane ribbon cables frequently suffer micro-fractures at the bend radius.

Diagnosing USB Keyboard Failures (Exact Error Strings)

When a USB keyboard fails to initialize, the Pi's DWC2 (DesignWare) USB controller logs specific error codes to the kernel ring buffer. Here is the translation of those errors into actionable electrical fixes.

dmesg Error String Meaning Root Cause Hardware / Config Fix
device descriptor read/64, error -110 Timeout during enumeration Voltage sag on 5V rail, or Pi's USB current limiter throttling the port. Upgrade to an official 27W USB-C PSU. On Pi 4, add usb_max_current=0 to /boot/firmware/config.txt to remove the 1.2A software limit.
device descriptor read/8, error -71 Protocol / Data corruption EMI interference on unshielded cables, or damaged D+/D- differential pairs. Replace the keyboard cable with a shielded, ferrite-beaded USB cable. Route away from switching power supplies.
Over-current change on port X Short circuit detected The Pi's resettable PTC polyfuse on the USB port has tripped due to a >1.4A draw. Unplug the keyboard immediately. Wait 60 seconds for the PTC thermal reset. Check keyboard PCB for solder bridges.
new USB device found, idVendor=0000 Dead device response Unpowered USB hub, or the keyboard's internal microcontroller has locked up. Provide external 5V to the hub. Power cycle the keyboard by unplugging it from the wall/PC for 30 seconds.
Pro Tip for Pi 4 Users: The Raspberry Pi 4 defaults to limiting total USB port current to 1.2A to protect the board's PMIC. If you are using a high-draw keyboard, edit your boot config: sudo nano /boot/firmware/config.txt, add usb_max_current=0 at the bottom, and reboot. The Raspberry Pi 5 handles this natively with its upgraded Renesas DA9098 PMIC and does not require this software override.

Building & Debugging a GPIO Matrix Keypad

When USB ports are damaged, or you are building a rugged embedded kiosk where USB is a liability, a direct-wired GPIO matrix keypad is the standard fallback. However, 'not detecting' in this context usually means your Python script is reading floating pins or suffering from matrix ghosting.

Parts List & Board Variant

  • Board: Raspberry Pi 4 Model B (4GB) or Raspberry Pi 5
  • Keypad: 4x4 Membrane Matrix Keypad (e.g., Adafruit 3844 or generic equivalent)
  • Resistors: 10kΩ SIP resistor network (for external pull-ups, though internal pull-ups are used in the code below)
  • Wiring: 28 AWG solid core hookup wire or FFC jumper cables

Pin Mapping Table

This mapping uses BCM (Broadcom) pin numbering. Rows are configured as Outputs (driven LOW to scan), and Columns are Inputs (pulled HIGH, reading LOW on keypress).

Matrix Line Function GPIO (BCM) Physical Pin (40-pin Header)
Row 1Output1711
Row 2Output2713
Row 3Output2215
Row 4Output529
Col 1Input (Pull-Up)631
Col 2Input (Pull-Up)1333
Col 3Input (Pull-Up)1935
Col 4Input (Pull-Up)2637

Complete Python Polling Code with Error Handling

The following script uses the gpiozero library to scan the matrix. It includes a 20ms software debounce to prevent mechanical contact bounce from registering as multiple keystrokes, and robust try/finally blocks to ensure GPIO states are safely cleaned up if the script crashes.

import time
from gpiozero import DigitalOutputDevice, Button
from signal import pause

# --- PIN DEFINITIONS (BCM Numbering) ---
ROW_PINS = [17, 27, 22, 5]
COL_PINS = [6, 13, 19, 26]

# Matrix character map
KEYS = [
    ['1', '2', '3', 'A'],
    ['4', '5', '6', 'B'],
    ['7', '8', '9', 'C'],
    ['*', '0', '#', 'D']
]

# Initialize Rows as Outputs (Active LOW)
rows = [DigitalOutputDevice(pin) for pin in ROW_PINS]
for row in rows:
    row.on()  # Start HIGH (inactive)

# Initialize Columns as Inputs with Internal Pull-Ups
cols = [Button(pin, pull_up=True, bounce_time=None) for pin in COL_PINS]

def scan_keypad():
    for r_idx, row in enumerate(rows):
        # Drive current row LOW
        row.off()
        time.sleep(0.005) # Allow voltage to settle
        
        for c_idx, col in enumerate(cols):
            # If button is pressed, it pulls the pin LOW (is_pressed == True)
            if col.is_pressed:
                # Software debounce
                time.sleep(0.02)
                if col.is_pressed:
                    key = KEYS[r_idx][c_idx]
                    print(f'Key Pressed: {key}')
                    # Wait for key release to prevent repeating
                    while col.is_pressed:
                        time.sleep(0.01)
        
        # Return row to HIGH
        row.on()

if __name__ == '__main__':
    print('Starting Keypad Scan... Press CTRL+C to exit.')
    try:
        while True:
            scan_keypad()
            time.sleep(0.05) # Main loop polling rate
    except KeyboardInterrupt:
        print('\nScan interrupted by user.')
    except Exception as e:
        print(f'An unexpected error occurred: {e}')
    finally:
        # Explicitly close gpiozero devices to release hardware pins
        for row in rows:
            row.close()
        for col in cols:
            col.close()
        print('GPIO resources cleaned up safely.')

Extending and Simplifying the Build

Depending on your project constraints, you may need to optimize this input method for pin count or reliability.

How to Simplify: Switch to I2C

Wiring 8 GPIO pins for a 4x4 matrix consumes a massive amount of the Pi's available headers. To simplify the physical build, use a PCF8574 I2C I/O Expander backpack (approx. $2-$4 on electronics marketplaces). This shifts the matrix scanning logic to the expander chip, reducing your Pi wiring to just four connections: VCC (5V), GND, SDA (GPIO 2), and SCL (GPIO 3). You can then poll the I2C bus using the smbus2 Python library, freeing up your GPIO pins for sensors or relays.

How to Extend: Anti-Ghosting Diodes

If your project requires simultaneous key presses (like a custom game controller or fast shortcut macros), a bare membrane matrix will suffer from 'ghosting'. Ghosting occurs when pressing three corners of a rectangle on the matrix causes the controller to falsely register the fourth corner as pressed, due to current backfeeding through the membrane traces.

The Fix: Solder a 1N4148 signal diode in series with every single row line, right at the membrane connector. Point the cathode (stripe) toward the membrane. This creates a hardware one-way valve for the current, completely eliminating ghosting and allowing true N-key rollover on the matrix. For a deep dive into Raspberry Pi hardware interfacing standards, refer to the official Raspberry Pi hardware documentation.