From 93caa198aaebb1a9c0bfed622a274b865180aecb Mon Sep 17 00:00:00 2001 From: notforyou23 Date: Wed, 27 May 2026 10:00:53 -0400 Subject: [PATCH 1/2] docs: add i2c environmental sensor hat tutorial --- .../pi-hats/i2c-environmental-sensor-hat.mdx | 340 ++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx diff --git a/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx b/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx new file mode 100644 index 00000000..4e98d825 --- /dev/null +++ b/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx @@ -0,0 +1,340 @@ +--- +title: Building an I2C Environmental Sensor HAT +description: Build a Raspberry Pi HAT with a BME280 temperature, humidity, and pressure sensor using tscircuit. +--- + +import CircuitPreview from "@site/src/components/CircuitPreview" +import TscircuitIframe from "@site/src/components/TscircuitIframe" + +## Overview + +This tutorial walks through a compact Raspberry Pi HAT that reads temperature, +humidity, and barometric pressure with a BME280 sensor. The design uses the +Raspberry Pi I2C bus, includes the required pull-up resistors, and exposes an +optional OLED display header that can share the same bus. + + ( + + + + + + + + + + + + + + + + + + + + + + + + + + + +) +`} /> + +## Circuit Goals + +The HAT should: + +- Power the BME280 from the Raspberry Pi 3.3V rail +- Connect BME280 SDA and SCL to GPIO2 and GPIO3 +- Add 4.7k pull-up resistors on both I2C lines +- Add local decoupling near the sensor +- Provide a 4-pin expansion header for an optional I2C OLED display + +## Bill of Materials + +| Reference | Part | Value | Notes | +| --- | --- | --- | --- | +| U1 | BME280 environmental sensor | I2C mode, `0x76` address | Temperature, humidity, and pressure | +| R1, R2 | Pull-up resistors | 4.7k | SDA and SCL to 3.3V | +| C1 | Bypass capacitor | 100nF | Place close to U1 | +| C2 | Bulk capacitor | 1uF | Stabilizes the local 3.3V rail | +| J1 | Pin header | 1x4, 2.54mm | Optional OLED or external I2C device | + +## Step 1: Add the HAT and Sensor + +Start with the Raspberry Pi HAT template and place the BME280. The BME280 can +run in SPI mode, but this design ties it into I2C mode by using SDA and SCL. Tie +`CSB` high so the sensor uses I2C, then tie `SDO` low for address `0x76`. + + ( + + + +) +`} /> + +## Step 2: Wire Power and I2C + +Connect the sensor to the Raspberry Pi 3.3V rail, ground, and I2C pins. On the +40-pin Raspberry Pi header, GPIO2 is SDA and GPIO3 is SCL. + +```tsx + + + + + + +``` + +## Step 3: Add Pull-Up Resistors + +I2C uses open-drain signaling, so SDA and SCL need pull-ups. Use 4.7k resistors +for a short HAT trace length at standard 100 kHz or 400 kHz bus speeds. + + ( + + + + + + + + + +) +`} /> + +## Step 4: Add Decoupling + +Place the 100nF capacitor as close as possible to the BME280 power pins. The 1uF +capacitor can sit nearby on the 3.3V rail to absorb slower supply changes. + +## Step 5: Add an Optional OLED Header + +Many small SSD1306 OLED modules use the same four-pin I2C layout: VCC, GND, +SDA, and SCL. The header can share the same bus as long as every device has a +unique I2C address. + +```tsx + + + + + +``` + +## PCB Layout Guidance + +- Keep the BME280 away from Raspberry Pi heat sources and voltage regulators. +- Place C1 within a few millimeters of the BME280 VCC and GND pins. +- Route SDA and SCL as short, direct traces and keep them away from noisy power + switching areas. +- Put the optional OLED header near the edge of the HAT so a display cable can + leave the enclosure cleanly. +- Add silkscreen labels for `3V3`, `GND`, `SDA`, and `SCL` next to J1. + +## Raspberry Pi Setup + +Enable I2C on the Raspberry Pi: + +```bash +sudo raspi-config +``` + +Then choose `Interface Options`, enable `I2C`, and reboot if prompted. + +Install the common Python libraries: + +```bash +sudo apt update +sudo apt install -y python3-pip i2c-tools +pip3 install adafruit-circuitpython-bme280 +``` + +Confirm the sensor appears on the bus: + +```bash +i2cdetect -y 1 +``` + +Most BME280 breakouts use address `0x76` or `0x77`. + +## Firmware Examples + +Use the example that matches your host board. The same SDA, SCL, 3.3V, and GND +connections apply as long as the controller uses 3.3V I2C signaling. + +### Raspberry Pi Python + +```python +import time + +import board +import busio +from adafruit_bme280 import basic as adafruit_bme280 + +i2c = busio.I2C(board.SCL, board.SDA) +bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76) + +bme280.sea_level_pressure = 1013.25 + +while True: + print(f"Temperature: {bme280.temperature:.1f} C") + print(f"Humidity: {bme280.relative_humidity:.1f} %") + print(f"Pressure: {bme280.pressure:.1f} hPa") + print(f"Altitude estimate: {bme280.altitude:.1f} m") + print() + time.sleep(2) +``` + +If `0x76` does not work, rerun the script with `address=0x77`. + +### CircuitPython Microcontroller + +For a CircuitPython board such as a Raspberry Pi Pico, install the Adafruit +BME280 library bundle and save this as `code.py`: + +```python +import time + +import board +import busio +from adafruit_bme280 import basic as adafruit_bme280 + +i2c = busio.I2C(board.SCL, board.SDA) +bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) + +while True: + print("Temperature: {:.1f} C".format(bme280.temperature)) + print("Humidity: {:.1f} %".format(bme280.relative_humidity)) + print("Pressure: {:.1f} hPa".format(bme280.pressure)) + print() + time.sleep(2) +``` + +### Arduino or ESP32 + +Install the `Adafruit BME280 Library` and `Adafruit Unified Sensor` packages +from the Arduino Library Manager, then upload: + +```cpp +#include +#include + +Adafruit_BME280 bme; + +void setup() { + Serial.begin(115200); + Wire.begin(); + + if (!bme.begin(0x76)) { + Serial.println("BME280 not found, try address 0x77"); + while (true) delay(10); + } +} + +void loop() { + Serial.print("Temperature: "); + Serial.print(bme.readTemperature()); + Serial.println(" C"); + + Serial.print("Humidity: "); + Serial.print(bme.readHumidity()); + Serial.println(" %"); + + Serial.print("Pressure: "); + Serial.print(bme.readPressure() / 100.0F); + Serial.println(" hPa"); + + delay(2000); +} +``` + +## Testing Checklist + +Before mounting the HAT on a Raspberry Pi: + +1. Check for shorts between 3.3V and GND with a multimeter. +2. Confirm SDA and SCL each measure about 4.7k to 3.3V. +3. Inspect the BME280 orientation and solder joints under magnification. +4. Power the HAT from the Pi and run `i2cdetect -y 1`. +5. Run the Python script and compare readings against a known room thermometer. + +## Next Improvements + +You can extend this board with: + +- A small OLED display on J1 for local readings +- A second I2C header for daisy-chaining other sensors +- Mounting holes aligned with a weather-shield enclosure +- A vent cutout near the BME280 to improve airflow From a4955c86fad86edad730fd99c620c5384025ee15 Mon Sep 17 00:00:00 2001 From: notforyou23 Date: Wed, 27 May 2026 11:35:01 -0400 Subject: [PATCH 2/2] Fix BME280 tutorial pinout --- .../pi-hats/i2c-environmental-sensor-hat.mdx | 112 ++++++++++-------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx b/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx index 4e98d825..3bfd0fbc 100644 --- a/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx +++ b/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx @@ -21,20 +21,20 @@ export default () => ( ( pcbY={-8} /> - + + - - - + + + + - + - - + + - + - - + + ) `} /> @@ -78,8 +80,8 @@ export default () => ( The HAT should: -- Power the BME280 from the Raspberry Pi 3.3V rail -- Connect BME280 SDA and SCL to GPIO2 and GPIO3 +- Power the BME280 `VDD` and `VDDIO` pins from the Raspberry Pi 3.3V rail +- Connect BME280 `SDI` and `SCK` to GPIO2 and GPIO3 for I2C data and clock - Add 4.7k pull-up resistors on both I2C lines - Add local decoupling near the sensor - Provide a 4-pin expansion header for an optional I2C OLED display @@ -97,8 +99,9 @@ The HAT should: ## Step 1: Add the HAT and Sensor Start with the Raspberry Pi HAT template and place the BME280. The BME280 can -run in SPI mode, but this design ties it into I2C mode by using SDA and SCL. Tie -`CSB` high so the sensor uses I2C, then tie `SDO` low for address `0x76`. +run in SPI mode, but this design ties it into I2C mode by using `SDI` as SDA +and `SCK` as SCL. Tie `CSB` high so the sensor uses I2C, then tie `SDO` low for +address `0x76`. ( @@ -127,14 +130,17 @@ export default () => ( ## Step 2: Wire Power and I2C Connect the sensor to the Raspberry Pi 3.3V rail, ground, and I2C pins. On the -40-pin Raspberry Pi header, GPIO2 is SDA and GPIO3 is SCL. +40-pin Raspberry Pi header, GPIO2 is SDA and GPIO3 is SCL; on the BME280 those +signals land on `SDI` and `SCK`. ```tsx - + + - - - + + + + ``` @@ -151,28 +157,32 @@ export default () => ( - + - + ) `} /> ## Step 4: Add Decoupling -Place the 100nF capacitor as close as possible to the BME280 power pins. The 1uF -capacitor can sit nearby on the 3.3V rail to absorb slower supply changes. +Place the 100nF capacitor close to `VDDIO` and ground. The 1uF capacitor can sit +nearby between `VDD` and ground to absorb slower supply changes on the 3.3V rail. ## Step 5: Add an Optional OLED Header @@ -189,8 +199,8 @@ unique I2C address. /> - - + + ``` ## PCB Layout Guidance @@ -272,7 +282,7 @@ import busio from adafruit_bme280 import basic as adafruit_bme280 i2c = busio.I2C(board.SCL, board.SDA) -bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c) +bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76) while True: print("Temperature: {:.1f} C".format(bme280.temperature))