How to connect sensors with Raspberry Pi GPIO?
Hedy

Hedy @carolineee

About: Publish some interesting electronic articles

Joined:
Dec 18, 2023

How to connect sensors with Raspberry Pi GPIO?

Publish Date: Aug 18
1 0

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.

Comments 0 total

    Add comment