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..2a37ff04 --- /dev/null +++ b/docs/tutorials/pi-hats/i2c-environmental-sensor-hat.mdx @@ -0,0 +1,312 @@ +--- +title: Building an I2C Environmental Sensor HAT +description: >- + This tutorial walks through an I2C environmental sensor HAT built around a + BME280 breakout, with pull-up resistors, an optional OLED header, and layout + guidance for a clean Raspberry Pi accessory board. +--- + +## Overview + +This tutorial shows how to build a compact Raspberry Pi HAT for monitoring +temperature, humidity, and pressure. The board keeps the wiring simple: + +- A BME280 sensor breakout on the I2C bus +- 4.7k pull-up resistors on SDA and SCL +- Decoupling for a quiet 3.3V rail +- An optional OLED header that shares the same bus + +import CircuitPreview from "@site/src/components/CircuitPreview" +import TscircuitIframe from "@site/src/components/TscircuitIframe" + + ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) +`} /> + +## Requirements + +For this bounty, the board needs to cover: + +- A BME280-based I2C sensor +- Pull-ups on SDA and SCL +- An optional OLED display connection +- A pin header for external access +- Schematic, code, and layout guidance + +## Why this circuit works + +The BME280 is a good fit for environmental monitoring because it gives you +temperature, humidity, and pressure over I2C. On a Raspberry Pi HAT, the bus +should stay tidy: + +- Use 3.3V logic +- Add pull-ups if the bus does not already provide them +- Keep decoupling close to the sensor power pins +- Route SDA and SCL as short, matched traces where practical + +By default, many BME280 breakouts use I2C address `0x77`. If the SDO pin is +tied low, the address can change to `0x76`, so note that in the build guide if +you expect multiple sensors on the same bus. + +## BME280 integration + +The BME280 should sit directly on the I2C bus with a clean 3.3V supply and a +short return path. That keeps the sensor readable and avoids the kind of noise +that can make environmental readings look jumpy. + +For the build note, call out these details: + +- wire VCC to 3.3V unless the breakout explicitly supports something else +- wire SDA and SCL to the Pi-compatible I2C pins +- keep pull-ups on the same board if the upstream bus does not already provide them +- add local decoupling near the sensor power pins +- note the address selection pin if the breakout exposes one + +That gives readers a simple path from the schematic to the first sensor read. + +## Microcontroller code examples + +If the reader wants to test the sensor outside the Pi first, include a small +microcontroller sketch they can adapt. The goal is not to build a full firmware +package here, just enough code to prove the bus and the sensor are alive. + +```cpp +#include + +void setup() { + Serial.begin(115200); + Wire.begin(); +} + +void loop() { + Serial.println("Read BME280 data here"); + delay(1000); +} +``` + +For a Python-based board, a tiny MicroPython example works just as well: + +```python +from machine import I2C, Pin +import time + +i2c = I2C(0, sda=Pin(0), scl=Pin(1)) + +while True: + print("scan:", i2c.scan()) + time.sleep(1) +``` + +These snippets keep the tutorial grounded in a real bring-up path: connect the +bus, confirm the device responds, then move on to the full build. + +## Step 1: Place the sensor module + +Start with the sensor module and expose the bus through a simple 4-pin header. +That makes the board easy to test on a bench before any enclosure work. + + ( + + + + + + + + +) +`} /> + +## Step 2: Add pull-ups and decoupling + +I2C behaves best when the pull-ups live on the same board as the bus owner. +For this layout, 4.7k is a safe default for the short traces on a HAT. + + ( + + + + + + + + + + + + + + + + + +) +`} /> + +## Step 3: Add the optional OLED header + +The OLED is easiest to support as a second I2C header so the same firmware can +drive both parts of the board. + + ( + + + + + + + + + + + + + + + + + + + + + +) +`} /> + +## Firmware example + +The firmware side can stay small. A typical CircuitPython loop looks like this: + +```python +import board +import busio +import time +import adafruit_bme280.basic as adafruit_bme280 + +i2c = busio.I2C(board.SCL, board.SDA) +sensor = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x77) + +while True: + print( + f"T={sensor.temperature:.1f} C", + f"H={sensor.humidity:.1f} %", + f"P={sensor.pressure:.1f} hPa", + ) + time.sleep(2) +``` + +If you wire SDO low and use address `0x76`, update the constructor to match. + +## PCB layout guidance + +Keep these parts close together when you move from schematic to board: + +- Put the sensor near an edge or vent opening if you want better airflow +- Keep the decoupling capacitor right next to the sensor power pins +- Run SDA and SCL together and avoid long stubs +- Place pull-ups near the bus owner, not out at the edge connector +- Leave space around the sensor so a later enclosure does not trap heat + +## What to check before publishing + +- The sensor, pull-ups, and OLED header all share the same I2C bus +- The board stays on 3.3V logic +- The example code uses the same I2C address you document +- The layout makes room for airflow around the sensor