Skip to main content
Tutorials

Build an I2C Environmental Sensor Module

Overview

This tutorial walks through a compact I2C environmental sensor module built around the BME280. The board exposes power and I2C on a 4-pin header, includes the required pull-up resistors, adds local decoupling capacitors, and leaves an optional OLED header on the same I2C bus.

The finished module can report:

  • Temperature
  • Relative humidity
  • Barometric pressure

Parts

RefPartNotes
U1BME280Temperature, humidity, and pressure sensor. Use the I2C mode wiring shown below.
R1, R24.7k resistorsPull SDA and SCL up to 3.3V.
C1100nF capacitorPlace close to the sensor supply pins.
C21uF capacitorBulk decoupling for the module input.
J14-pin male headerMain host connection: VCC, GND, SDA, SCL.
J24-pin female headerOptional OLED display connection on the same I2C bus.

Design Goals

The module is intentionally simple:

  • Use 3.3V logic so it can connect directly to most modern microcontrollers.
  • Put the BME280 in I2C mode by tying CSB high.
  • Select address 0x76 by tying SDO low. Tie SDO high instead if you need address 0x77.
  • Keep pull-up resistors on the module so a host board can talk to it with only four wires.
  • Add an optional OLED connector because many sensor projects show readings on a small SSD1306 display.

Step 1: Add the Sensor

The BME280 has separate core and interface supply pins. For a simple 3.3V module, connect both VDD and VDDIO to the same 3.3V rail.

Schematic Circuit Preview

The important I2C-mode connections are:

  • SCK becomes SCL.
  • SDI becomes SDA.
  • CSB goes to 3.3V to select I2C instead of SPI.
  • SDO selects the I2C address.

Step 2: Add the Host Header

Most host boards expect a 4-pin sensor header. Use the same order on your silkscreen that you use in code so it is easy to cable the module correctly.

<pinheader
name="J1"
pinCount={4}
pitch="2.54mm"
gender="male"
footprint="pinrow4"
showSilkscreenPinLabels
pinLabels={["VCC", "GND", "SDA", "SCL"]}
connections={{
VCC: "net.V3_3",
GND: "net.GND",
SDA: "net.SDA",
SCL: "net.SCL",
}}
/>

If your host board already has I2C pull-ups, you can leave R1 and R2 unpopulated or use solder jumpers in a later revision. For a standalone module, populate them.

Step 3: Add I2C Pull-ups

I2C devices only pull the bus low. The bus idles high through pull-up resistors, so SDA and SCL each need a resistor to 3.3V.

Schematic Circuit Preview

4.7k is a good default for a short 3.3V cable. For very long wires or a bus with several modules, you may need to calculate the pull-up value from bus capacitance and rise-time requirements.

Step 4: Add Decoupling Capacitors

Place the 100nF capacitor as close as possible to the BME280 supply pins. The 1uF capacitor can sit near the incoming header to absorb slower supply changes.

<capacitor
name="C1"
footprint="0603"
capacitance="100nF"
connections={{ pos: "net.V3_3", neg: "net.GND" }}
/>
<capacitor
name="C2"
footprint="0603"
capacitance="1uF"
connections={{ pos: "net.V3_3", neg: "net.GND" }}
/>

Step 5: Add an Optional OLED Header

Many small displays use the same four I2C signals. Adding an optional OLED header lets the module become a tiny local readout board without changing the sensor circuit.

<pinheader
name="J2"
pinCount={4}
pitch="2.54mm"
gender="female"
footprint="pinrow4"
showSilkscreenPinLabels
pinLabels={["GND", "VCC", "SCL", "SDA"]}
connections={{
GND: "net.GND",
VCC: "net.V3_3",
SCL: "net.SCL",
SDA: "net.SDA",
}}
/>

Check the display module pinout before assembly. OLED breakout boards often use GND, VCC, SCL, SDA, but not all vendors keep the same order.

Layout Checklist

  • Put U1 away from hot regulators, LEDs, and microcontrollers so temperature readings are not biased by local heat.
  • Keep a small opening around the sensor so airflow can reach it.
  • Route SDA and SCL as short, direct traces and keep them away from noisy power switching nodes.
  • Place C1 near the BME280 supply pins before routing long traces elsewhere.
  • Label the header pins on silkscreen. Sensor boards are often wired by hand.
  • If the module might be used on a 5V host, add a regulator and I2C level shifting before connecting it directly.

Firmware Smoke Test

After assembly, run a quick I2C scan from your host. The module should appear at 0x76 with the default SDO-to-ground wiring.

// Pseudocode for a host board test.
const sensor = await i2c.openDevice(0x76)
const chipId = await sensor.readRegister(0xd0)

if (chipId !== 0x60) {
throw new Error("BME280 was not detected")
}

Once the chip responds, use a BME280 driver library for your host platform and verify that temperature, humidity, and pressure readings change when you breathe near the sensor or gently warm the board.