I2C Hardware Setup

Learn how to properly wire I2C devices with pull-up resistors and make reliable connections

By Kevin McAleer,    8 Minutes


Wiring Your First I2C Device

Now that you understand what I2C is, let’s connect a real BME280 sensor to your Raspberry Pi Pico. This lesson covers everything you need to know about physical connections, power requirements, and the mysterious pull-up resistors.

Understanding the BME280 Sensor

The BME280 is a fantastic sensor that measures:

  • Temperature - Accurate to 1 degree Celsius
  • Humidity - Percentage relative humidity
  • Barometric Pressure - Atmospheric pressure

It communicates via I2C (or SPI), costs just a few dollars, and is perfect for weather stations, environmental monitoring, and learning I2C fundamentals.

Note: BME280 modules come on small breakout boards that handle the complicated stuff (voltage regulation, filtering) so you can focus on learning.

BME280 Pinout

Most BME280 breakout boards have 4 pins:

Pin Name Description
VCC Power 3.3V from Pico
GND Ground Common ground
SCL Serial Clock Connect to Pico GP9
SDA Serial Data Connect to Pico GP8

Important: Some BME280 boards can handle 5V power, but the Pico outputs 3.3V. Always use 3.3V to be safe.

The Essential Pull-up Resistors

Here’s something crucial about I2C: the SDA and SCL lines need pull-up resistors. Let me explain why.

Why Pull-up Resistors Matter

I2C uses β€œopen-drain” outputs. This means:

  • Devices can pull the line LOW (to ground)
  • Devices can release the line (let it float)
  • Devices cannot pull the line HIGH

Without pull-up resistors, the lines would float randomly when released. The resistors pull them HIGH so devices only need to pull them LOW. Think of it like gravity - the resistor naturally lifts the line up, and devices pull it down when needed.

Good News About Pull-ups

Most BME280 breakout boards already have pull-up resistors built in! Look at your board carefully:

  • Small resistors labeled β€œ103” (10kΞ©) or β€œ473” (47kΞ©) near SDA/SCL
  • Sometimes labeled β€œR1” and β€œR2”

If your board has these, you don’t need to add external resistors. If it doesn’t, you’ll need to add 4.7kΞ© or 10kΞ© resistors between SDA/SCL and 3.3V.

# You don't need to do anything in code for pull-ups
# They're purely hardware components
# Just know they must be present somewhere in the circuit

Wiring the BME280 to Raspberry Pi Pico

Here’s the complete wiring guide:

Step-by-Step Connections

  1. Power Connection
    • BME280 VCC β†’ Pico 3.3V (pin 36)
    • BME280 GND β†’ Pico GND (any GND pin)
  2. I2C Connection
    • BME280 SCL β†’ Pico GP9 (pin 12)
    • BME280 SDA β†’ Pico GP8 (pin 11)

Pico Pinout Reference

Raspberry Pi Pico Pinout (relevant pins):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  USB PORT               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 1  GP0              VBUSβ”‚ 40
β”‚ 2  GP1              VSYSβ”‚ 39
β”‚ 3  GND               GNDβ”‚ 38
β”‚ 4  GP2           3V3_EN β”‚ 37
β”‚ 5  GP3              3.3Vβ”‚ 36 ← Connect VCC here
β”‚ 6  GP4               REFβ”‚ 35
β”‚ 7  GP5              GP28β”‚ 34
β”‚ 8  GND               GNDβ”‚ 33 ← Connect GND here
β”‚ 9  GP6               GNDβ”‚ 32
β”‚10  GP7              GP27β”‚ 31
β”‚11  GP8 (SDA)        GP26β”‚ 30 ← Connect SDA here
β”‚12  GP9 (SCL)        RUN β”‚ 29 ← Connect SCL here
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Color Coding Tips

If you’re using jumper wires, consider this color scheme:

  • Red - Power (VCC to 3.3V)
  • Black - Ground (GND to GND)
  • Yellow - SCL (clock)
  • Blue - SDA (data)

This makes troubleshooting easier and keeps your projects organized.

Physical Connection Best Practices

Use a Breadboard

For prototyping, breadboards are perfect:

Breadboard Layout:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ + + + + + + + + + + + + +  β”‚ ← Power rail (connect to 3.3V)
β”‚ - - - - - - - - - - - - -  β”‚ ← Ground rail (connect to GND)
β”‚                            β”‚
β”‚  [BME280 Module]           β”‚
β”‚   VCC GND SCL SDA          β”‚
β”‚    β”‚   β”‚   β”‚   β”‚           β”‚
β”‚    └───┼───┼───┼──────┐    β”‚
β”‚        └───┼───┼──┐   β”‚    β”‚
β”‚            └───┼┐ β”‚   β”‚    β”‚
β”‚                β”‚β”‚ β”‚   β”‚    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”Όβ”€β”Όβ”€β”€β”€β”Όβ”€β”€β”€β”€β”˜
                 β”‚β”‚ β”‚   β”‚
              To Pico Pins

Wire Length Matters

  • Keep wires short - under 10cm if possible
  • Longer wires increase capacitance and can cause communication errors
  • If you need longer distances, consider I2C bus extenders

Secure Connections

  • Push wires firmly into breadboard holes
  • Check that pins are making contact
  • Wiggle wires gently - they shouldn’t come loose

Power Considerations

Voltage Levels

The Raspberry Pi Pico uses 3.3V logic:

  • Safe: 3.3V devices (like most BME280 boards)
  • Risky: 5V-only devices (need level shifters)
  • Never: Higher voltages - will damage your Pico

Warning: Double-check your sensor’s voltage requirements. Some sensors marked β€œ5V” actually mean β€œcan be powered by 5V” but use 3.3V logic. Read the datasheet to be sure.

Power Supply Current

The BME280 uses very little current:

  • Typical: 3.6ΞΌA (microamps) in sleep mode
  • Measuring: 714ΞΌA during readings
  • Pico can supply: Up to 300mA from 3.3V pin

This means you can power the BME280 directly from the Pico with no issues.

Testing Your Wiring

Once everything is connected, let’s verify the wiring with a simple test:

from machine import I2C, Pin
import time

# Initialize I2C
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=400000)

print("Testing I2C connection...")
print("If this runs without errors, wiring is likely correct")

# Try to scan for devices (we'll learn more about this in the next lesson)
devices = i2c.scan()

if devices:
    print(f"Found {len(devices)} device(s)!")
    for device in devices:
        print(f"  - Device at address: 0x{device:02X}")
else:
    print("No devices found - check your wiring")

What you should see:

Testing I2C connection...
If this runs without errors, wiring is likely correct
Found 1 device(s)!
  - Device at address: 0x76

or

Found 1 device(s)!
  - Device at address: 0x77

Note: BME280 sensors usually appear at address 0x76 or 0x77, depending on the manufacturer and whether they’ve connected the SDO pin to GND or VCC.

Try It Yourself

Let’s build confidence with your wiring:

  1. Wire your BME280 following the guide above
  2. Run the test code and verify your device appears
  3. Intentionally disconnect SDA - run the code again. You should see β€œNo devices found”
  4. Reconnect SDA - devices should reappear
  5. Try different GPIO pins - modify the code to use GP4 (SDA) and GP5 (SCL), rewire accordingly
# Using alternate pins
i2c = I2C(0, scl=Pin(5), sda=Pin(4), freq=400000)
devices = i2c.scan()
print(f"Devices on alternate pins: {devices}")

Common Wiring Issues

No Devices Found

Problem: Test code shows β€œNo devices found”

Possible causes:

  1. SDA or SCL wires not connected properly
  2. Power not connected (VCC or GND loose)
  3. Wrong pins in code vs physical wiring
  4. Faulty sensor or breadboard connection

Solution checklist:

  • Verify VCC connected to 3.3V pin
  • Verify GND connected to GND pin
  • Check SDA on GP8
  • Check SCL on GP9
  • Push all connections firmly
  • Try different breadboard holes

OSError or Bus Error

Problem: Error message like β€œOSError: [Errno 5] EIO” or β€œI2C bus error”

Possible causes:

  1. Missing pull-up resistors
  2. Short circuit between SDA and SCL
  3. Sensor damaged

Solutions:

  • Check that your BME280 board has pull-up resistors
  • Ensure SDA and SCL wires aren’t touching
  • Try a different sensor if available

Wrong Address

Problem: Device found but at unexpected address

This is usually fine! BME280 sensors can appear at either 0x76 or 0x77. Make note of your sensor’s address - you’ll need it for the next lesson.

# If your sensor is at 0x76 instead of 0x77, just use that
BME280_ADDRESS = 0x76  # or 0x77

Multiple I2C Devices

One of I2C’s superpowers is connecting multiple devices to the same bus. Here’s how:

Wiring Multiple Devices

All devices share the same SDA and SCL lines:

Pico GP8 (SDA) ──┬── Device 1 SDA
                 β”œβ”€β”€ Device 2 SDA
                 └── Device 3 SDA

Pico GP9 (SCL) ──┬── Device 1 SCL
                 β”œβ”€β”€ Device 2 SCL
                 └── Device 3 SCL

Pico 3.3V ───────┬── Device 1 VCC
                 β”œβ”€β”€ Device 2 VCC
                 └── Device 3 VCC

Pico GND ────────┬── Device 1 GND
                 β”œβ”€β”€ Device 2 GND
                 └── Device 3 GND

Each device gets its own power and ground, but they share the communication lines.

Remember: Each device needs a unique address. You can’t have two BME280s at 0x76 on the same bus.

What You’ve Learned

In this lesson, you mastered:

  • BME280 pinout and pin functions (VCC, GND, SCL, SDA)
  • Why I2C needs pull-up resistors and how to identify them
  • Proper wiring from BME280 to Raspberry Pi Pico
  • Best practices for breadboarding and wire management
  • Power requirements and voltage levels
  • Testing connections with scanning code
  • Troubleshooting common wiring problems
  • How to connect multiple I2C devices

Your BME280 is now physically connected and ready to communicate. You’ve verified it appears on the I2C bus with the test code.

What’s Next

Now that your sensor is wired and responding, let’s learn how to scan the I2C bus systematically, understand device addresses, and why that β€œ0x” notation keeps appearing. In the next lesson, we’ll explore I2C scanning in detail and prepare to read actual sensor data.

< Previous Next >

You can use the arrows  ← β†’ on your keyboard to navigate between lessons.


What are you looking for?
Watch Videos Get Ideas Learn Something Read a Review Read the Blog Search
... Z Z z