DEV Community

Hedy
Hedy

Posted on

How to connect sensors with Raspberry Pi GPIO?

Here’s a quick, practical guide to hooking sensors to a Raspberry Pi’s GPIO—covering digital, I²C, SPI, UART, and analog (via ADC), plus sample Python.

Golden rules (before you wire anything)

  • 3.3 V only. Pi GPIO is not 5 V tolerant. Use level shifters for 5 V sensors.
  • GND first. Always share ground between Pi and the sensor.
  • Use the right pins. Prefer the BCM numbering in code.
  • Pull-ups/downs. Inputs need a defined idle level (use Pi’s internal pulls or external resistors).
  • Power budget. Don’t draw big loads from 3.3 V pin; high-current sensors need external supply.

Pin essentials (BCM)

  • 3V3 power: Pin 1 (3V3), Pin 17 (3V3)
  • 5V power: Pins 2, 4 (avoid for logic)
  • Ground: Pins 6, 9, 14, 20, 25, 30, 34, 39
  • I²C: SDA1 = GPIO2 (Pin 3), SCL1 = GPIO3 (Pin 5)
  • SPI0: CE0 = GPIO8 (Pin 24), CE1 = GPIO7 (Pin 26), MOSI = GPIO10 (Pin 19), MISO = GPIO9 (Pin 21), SCLK = GPIO11 (Pin 23)
  • UART: TXD = GPIO14 (Pin 8), RXD = GPIO15 (Pin 10)
  • Any free GPIO for simple digital inputs/outputs

Common connection patterns
1) Simple digital input (e.g., button, PIR)

Wiring

  • One side → GPIO (e.g., GPIO17/Pin 11)
  • Other side → GND
  • Use Pi’s internal pull-up

Python (gpiozero)

from gpiozero import Button from signal import pause btn = Button(17, pull_up=True) # internal pull-up btn.when_pressed = lambda: print("Pressed") btn.when_released = lambda: print("Released") pause() 
Enter fullscreen mode Exit fullscreen mode

2) Digital output (e.g., LED via resistor)

Wiring

GPIO → resistor (220–1kΩ) → LED → GND

Python

from gpiozero import LED from time import sleep led = LED(18) while True: led.toggle() sleep(0.5) 
Enter fullscreen mode Exit fullscreen mode

3) I²C sensor (e.g., BME280, MPU6050)

Wiring

  • Sensor VCC → 3V3, GND → GND
  • SDA → GPIO2 (Pin 3), SCL → GPIO3 (Pin 5)
  • Most breakout boards include pull-ups; if not, add 4.7 kΩ to 3V3 on SDA/SCL

Enable & test

sudo raspi-config # Interface Options → I2C → Enable sudo apt update && sudo apt install -y i2c-tools python3-smbus i2cdetect -y 1 # should show the device address (e.g., 0x76) 
Enter fullscreen mode Exit fullscreen mode

Python (smbus2 + BME280 example)

import smbus2, time BUS = smbus2.SMBus(1) ADDR = 0x76 # Use a driver library for real projects; this is just a placeholder ping: chip_id = BUS.read_byte_data(ADDR, 0xD0) print("Chip ID:", hex(chip_id)) 
Enter fullscreen mode Exit fullscreen mode

4) SPI sensor (e.g., MCP3008 ADC, ADS795x, some IMUs)

Wiring (MCP3008 example)

  • VDD/VREF → 3V3, AGND/DGND → GND
  • CLK → GPIO11, DOUT → GPIO9 (MISO), DIN → GPIO10 (MOSI), CS/SHDN → GPIO8 (CE0)

Enable & test

sudo raspi-config # Interface Options → SPI → Enable sudo apt install -y python3-spidev 
Enter fullscreen mode Exit fullscreen mode

Python (read MCP3008 CH0)

import spidev spi = spidev.SpiDev(); spi.open(0,0); spi.max_speed_hz = 1_000_000 def read_ch0(): # MCP3008 protocol: start(1) single-ended(1) ch(3) + 5 dummy bits resp = spi.xfer2([0b00000001, 0b10000000, 0]) val = ((resp[1] & 0x03) << 8) | resp[2] return val # 0..1023 print(read_ch0()) 
Enter fullscreen mode Exit fullscreen mode

5) UART sensor/module (e.g., GPS, PM2.5)

Wiring

  • 3V3 logic only (use level shifter if module is 5 V)
  • Sensor TX → Pi RX (GPIO15), Sensor RX → Pi TX (GPIO14)
  • GND → GND

Enable UART (disable serial console)

sudo raspi-config # Interface Options → Serial: login shell? No; enable HW serial? Yes sudo apt install -y python3-serial 
Enter fullscreen mode Exit fullscreen mode

Python

import serial ser = serial.Serial('/dev/serial0', 9600, timeout=1) print(ser.readline().decode(errors='ignore')) 
Enter fullscreen mode Exit fullscreen mode

6) “Analog” sensors (pots, some gas/light sensors)

Pi has no built-in ADC, so use an external ADC (e.g., MCP3008 via SPI or ADS1115 via I²C).

ADS1115 (I²C) quick read (library-based)

# pip install adafruit-circuitpython-ads1x15 import board, busio from adafruit_ads1x15.analog_in import AnalogIn from adafruit_ads1x15.ads1115 import ADS1115 i2c = busio.I2C(board.SCL, board.SDA) ads = ADS1115(i2c) chan = AnalogIn(ads, 0) print(chan.voltage) 
Enter fullscreen mode Exit fullscreen mode

Troubleshooting checklist

  • i2cdetect shows nothing? Check power/ground, SDA/SCL swapped, pull-ups, enable I²C.
  • SPI returns zeros/noise? Wrong CS line, MISO/MOSI crossed, forgot to enable SPI, speed too high.
  • UART gibberish? Wrong baud/format, serial console still enabled, 5 V logic without shifter.
  • Random input flicker? Add/enable pull-ups/downs; debounce in software or RC network.
  • Sensor is 5 V-only? Use a level shifter and, if needed, a separate 5 V supply.

Quick safety add-ons

  • For inductive sensors/relays, add flyback diodes and keep them off logic rails.
  • For noisy environments, add series resistors (22–100 Ω) and RC filters on long lines.
  • Use separate grounds for high-current loads, tie to Pi ground at a single point.

Top comments (0)