Running Home Assistant on a Raspberry Pi 5 (8GB) is the current gold standard for local, high-performance smart homes. However, integrating bare-metal I2C sensors directly into the Home Assistant ecosystem trips up many builders because of the OS architecture. If you use the recommended Home Assistant OS (HAOS), direct GPIO access is blocked by Docker containerization and AppArmor profiles.
The direct answer: To interface a raw I2C sensor with Home Assistant on a Pi 5 without fighting the HAOS kernel, you should run Raspberry Pi OS Lite (Bookworm) with Home Assistant Container, and use a local Python MQTT bridge. This guide targets the Raspberry Pi 5 (8GB) variant, wiring an LM75A I2C temperature sensor to the primary I2C bus, and publishing the data to Home Assistant via a local Mosquitto broker.
Hardware Spec Sheet & Parts List
Do not attempt to run Home Assistant Container on a microSD card. The write-amplification from SQLite and MariaDB logs will destroy a standard SanDisk Ultra card in 4 to 6 months. Boot from NVMe.
| Component | Exact Variant / Model | Estimated Cost (2026) | Why This Specific Part |
|---|---|---|---|
| Compute Board | Raspberry Pi 5 (8GB RAM) | $80 | 8GB is required for local Whisper/LLM add-ons; 4GB bottlenecks ZHA. |
| Storage | Samsung 980 256GB NVMe M.2 | $35 | High TBW endurance to survive HA database write cycles. |
| Enclosure | Argon NEO 5 NVMe Case | $35 | Provides passive cooling for the RP1 southbridge and M.2 slot. |
| Sensor | LM75A I2C Temp Sensor Module | $4 | Simple 2-byte register map, 3.3V logic, no complex calibration. |
| Zigbee Dongle | Sonoff ZBDongle-P (CC2652P) | $25 | Best-in-class range for ZHA; requires USB extension cable. |
Pin Mapping & Physical Wiring
The Raspberry Pi 5 routes its primary I2C bus through the new RP1 southbridge chip, but it maintains backward compatibility with the standard 40-pin header layout for I2C1. The LM75A sensor operates at 3.3V and includes internal pull-up resistors, so you do not need external 4.7k pull-ups for wires under 30cm.
| Pi 5 GPIO Pin (Physical) | BCM / Function | LM75A Sensor Pin | Wire Color (Standard) |
|---|---|---|---|
| Pin 1 | 3.3V Power | VCC | Red |
| Pin 3 | GPIO 2 (SDA1) | SDA | Yellow |
| Pin 5 | GPIO 3 (SCL1) | SCL | Orange |
| Pin 6 | Ground | GND | Black |
The MQTT Bridge: Python I2C Publisher
Because Home Assistant Container runs in Docker, it cannot natively see the host's /dev/i2c-1 device without privileged container flags (which is a security risk). Instead, we run a lightweight Python script on the host OS that reads the sensor and publishes it to the Home Assistant Mosquitto MQTT Add-on.
Prerequisites: Install the required libraries on your Pi OS host:
sudo apt update && sudo apt install python3-pip i2c-tools
pip3 install smbus2 paho-mqtt --break-system-packages
Save the following code as i2c_mqtt_bridge.py. This script targets paho-mqtt v2.x and includes robust error handling for both I2C bus drops and MQTT broker disconnects.
import smbus2
import paho.mqtt.client as mqtt
import time
import json
import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# --- Hardware Definitions ---
I2C_BUS = 1
LM75A_ADDR = 0x48 # Default I2C address for LM75A
TEMP_REG = 0x00 # Temperature register pointer
# --- MQTT Definitions ---
MQTT_BROKER = '192.168.1.100' # Replace with your HA local IP
MQTT_PORT = 1883
MQTT_USER = 'your_mqtt_user'
MQTT_PASS = 'your_mqtt_password'
MQTT_TOPIC = 'homeassistant/sensor/pi5_lab/temp'
def on_connect(client, userdata, flags, rc, properties=None):
if rc == 0:
logging.info('Successfully connected to MQTT Broker')
else:
logging.error(f'MQTT Connection failed with result code {rc}')
# Initialize MQTT Client (paho-mqtt v2.x API)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id='pi5_i2c_bridge')
client.username_pw_set(MQTT_USER, MQTT_PASS)
client.on_connect = on_connect
def connect_mqtt():
try:
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()
except ConnectionRefusedError as e:
logging.critical(f'MQTT Error: {e}. Verify Mosquitto Add-on is running and port 1883 is open.')
exit(1)
def init_i2c():
try:
bus = smbus2.SMBus(I2C_BUS)
# Quick ping to verify device presence
bus.read_byte_data(LM75A_ADDR, TEMP_REG)
return bus
except FileNotFoundError:
logging.critical('I2C Error: /dev/i2c-1 not found. Run "sudo raspi-config" and enable I2C.')
exit(1)
except OSError as e:
logging.critical(f'I2C Error: {e}. Check SDA/SCL wiring and ensure sensor is powered.')
exit(1)
def main():
connect_mqtt()
bus = init_i2c()
logging.info('Bridge initialized. Publishing every 30 seconds.')
while True:
try:
# LM75A returns 2 bytes for temperature (9-bit resolution)
raw_data = bus.read_i2c_block_data(LM75A_ADDR, TEMP_REG, 2)
# Bitwise conversion to Celsius
temp_c = (raw_data[0] << 8 | raw_data[1]) / 256.0
# Format payload for Home Assistant MQTT Discovery / State
payload = json.dumps({
'temperature': round(temp_c, 2),
'unit': 'C',
'source': 'pi5_gpio'
})
# Publish with QoS 1 and Retain=True so HA gets immediate state on boot
client.publish(MQTT_TOPIC, payload, qos=1, retain=True)
logging.info(f'Published: {temp_c}C')
time.sleep(30)
except OSError as e:
logging.error(f'I2C Read Fault: {e}. Re-initializing bus...')
bus = init_i2c() # Re-bind the bus on transient wire faults
time.sleep(5)
except Exception as e:
logging.error(f'Unexpected error: {e}')
time.sleep(10)
if __name__ == '__main__':
main()
Debugging: I2C and MQTT Failure Modes
When bridging bare-metal hardware into a containerized smart home OS, failures usually happen at the physical layer or the network boundary. If your script crashes, look for these exact error strings.
Error 1: OSError: [Errno 121] Remote I/O error
This is the most common I2C failure. It means the Pi's I2C controller sent a clock signal, but the sensor did not acknowledge (NACK) on the SDA line.
- Wrong I2C Address: Run
i2cdetect -y 1in the terminal. If the LM75A shows up at0x49instead of0x48, the A0 address pin on the sensor is pulled high. Update theLM75A_ADDRvariable. - SDA/SCL Swapped: The RP1 chip on the Pi 5 does not auto-swap pins. Verify Pin 3 is SDA and Pin 5 is SCL.
- Missing Pull-ups: If your wires are longer than 50cm, the internal 1.8k pull-ups on the Pi 5 are too weak. Solder 4.7k resistors between SDA/SCL and 3.3V.
Error 2: ConnectionRefusedError: [Errno 111] Connection refused
The Python script cannot reach the Mosquitto broker inside Home Assistant.
- Add-on Not Running: Ensure the 'Mosquitto Broker' Add-on is installed and started in the HA Supervisor panel.
- Port Mapping: By default, the HA Mosquitto add-on maps to port 1883. If you changed this in the add-on network settings, update
MQTT_PORTin the script. - Authentication Failure: If the broker rejects the connection silently, verify that
MQTT_USERmatches an actual Home Assistant user account with admin privileges.
1. Run
ls /dev/i2c* to verify the kernel module loaded the I2C bus.2. Run
i2cdetect -y 1 to confirm the sensor is physically answering.3. Check the HA Mosquitto Add-on logs for 'Socket error' or 'Authentication failed' messages.
Extending or Simplifying the Build
To Simplify: If managing Python scripts and host-level MQTT bridges feels like too much overhead, abandon the direct Pi GPIO approach. Buy a $6 ESP32-C3 dev board, wire the LM75A to it, and use ESPHome. ESPHome compiles the sensor logic into firmware and pushes it directly to Home Assistant via the native API, completely bypassing the need for MQTT or Pi OS configuration. You can read more about ESPHome's I2C implementation in the official ESPHome I2C documentation.
To Extend: You can expand this Python script to read multiple sensors on the same bus (e.g., adding a BME280 at 0x76 for humidity). You can also add a relay HAT to the Pi 5 and use MQTT subscribe callbacks in the Python script to trigger physical relays based on Home Assistant automations, effectively turning your Pi into a multi-purpose I/O controller.
Frequently Asked Questions
Is a Raspberry Pi 5 overkill for Home Assistant in 2026?
No. While a Pi 4 (4GB) can run basic dashboards, the modern Home Assistant ecosystem heavily relies on local processing. Running the Whisper speech-to-text add-on, local LLM agents for natural language automations, and managing a Zigbee mesh with 100+ devices via ZHA will quickly max out a 4GB board. The 8GB Pi 5 provides the necessary headroom for these edge-computing tasks without swapping to disk.
Why does Home Assistant OS block direct GPIO access?
Home Assistant OS (HAOS) is a heavily locked-down, container-optimized Linux distribution. Every add-on and the core supervisor run in isolated Docker containers with strict AppArmor security profiles. Allowing a container raw access to /dev/mem or /dev/i2c-1 would break this isolation, creating a massive security vulnerability where a compromised add-on could brick the host hardware or access the host filesystem. Using HA Container on standard Raspberry Pi OS bypasses this restriction by giving you host-level control.
Can I run Home Assistant on a Raspberry Pi without an SSD?
Technically, yes. The official Home Assistant installation guide provides an SD card image. However, in practice, it is a terrible idea for long-term use. Home Assistant writes to its SQLite database and log files constantly. This write-amplification will exhaust the write-cycles of a standard microSD card, leading to read-only filesystem errors and total corruption within 6 months. An NVMe or SATA SSD via a USB 3.0 adapter is mandatory for a reliable production system.






