ESPHome and Home Assistant Guide: Custom Sensors Without Arduino Code

Arduino sketches are a fine way to build smart sensors if you enjoy C++ and manual library management. ESPHome replaces all of that with 60 lines of YAML that compile into native firmware for ESP32 and ESP8266 boards. This guide covers what ESPHome is, when to pick it over Arduino, and the workflow that runs in hundreds of homes with custom sensors that just work.

I switched from raw Arduino sketches to ESPHome in late 2020 and have not written a hand-rolled Arduino sketch for production hardware since. The 40 ESPHome sensors currently running in my flat would have been roughly 4000 lines of Arduino C++; the equivalent ESPHome YAML is around 800 lines total. Same hardware, same sensors, vastly less code to maintain.

What ESPHome Actually Does

ESPHome takes a YAML configuration describing the sensors, actuators, and behaviour you want, and produces ESP32/ESP8266 firmware that implements that configuration. The framework handles WiFi connection, OTA updates, sensor reading, Home Assistant API integration, and reboot recovery automatically.

The contrast with raw Arduino is sharp. An Arduino sketch for a DHT22 temperature sensor reporting to Home Assistant via MQTT runs about 80 lines of C++ -- include directives, WiFi setup, MQTT client configuration, reading loop, and JSON formatting. The same sensor in ESPHome is six lines of YAML naming the platform, the pin, and the entity names.

The official ESPHome documentation lists roughly 200 supported sensor types. For each type, the YAML configuration is documented with example snippets. The catalogue covers nearly every cheap sensor available on AliExpress, and many specialised ones (mmWave presence, particulate matter, CO2 with NDIR sensors).

The Five-Step ESPHome Workflow

The standard workflow is the same on every project:

The first step is writing a YAML file describing the device. Even complex sensors fit in 40-80 lines. ESPHome's structure encourages readability: each section (esphome, esp32/esp8266, wifi, api, sensor, switch, light) has a clear purpose.

The second step is compiling. Run "esphome compile" or click Install in the ESPHome dashboard, and PlatformIO compiles the YAML into a firmware binary. The first compile takes 1-3 minutes; subsequent compiles cache and complete in 20-40 seconds.

The third step is flashing. The first time, connect the board via USB and run "esphome upload --device /dev/ttyUSB0". After that, all updates happen wirelessly through OTA. The dashboard's Install button handles both first-time and OTA flashing automatically.

The fourth step is waiting for the device to boot. A fresh ESP8266 takes about 15 seconds to connect to WiFi and register with Home Assistant. ESP32 boards boot in under 10 seconds. The dashboard shows live status.

The fifth step is using the device. Home Assistant auto-discovers ESPHome devices on the network. A notification appears in the HA UI offering to add the new integration. One click later, the sensor entities appear in the Home Assistant entity list ready for automations.

A Real ESPHome Config I Run

The temperature sensor in my airing cupboard has been running for 18 months. The complete config:

esphome:
  name: airing-cupboard-sensor
  friendly_name: Airing Cupboard Temp

esp8266:
  board: d1_mini

wifi:
  ssid: "..."
  password: "..."

api:
  encryption:
    key: "..."

ota:
  - platform: esphome

logger:
  level: WARN

sensor:
  - platform: dht
    pin: D4
    model: DHT22
    temperature:
      name: Airing Cupboard Temperature
      filters:
        - filter_out: nan
    humidity:
      name: Airing Cupboard Humidity
      filters:
        - filter_out: nan
    update_interval: 60s

binary_sensor:
  - platform: status
    name: Airing Cupboard Sensor Online

That's the complete file. 30 lines including blanks. The sensor reports temperature and humidity every 60 seconds, deduplicates NaN readings, exposes an online/offline binary sensor, and supports OTA updates. The equivalent Arduino sketch with comparable robustness would be 150-200 lines.

When ESPHome Beats Arduino IDE

Five scenarios where ESPHome wins decisively:

The first is when you have more than three custom sensors. Maintaining three Arduino sketches with separate WiFi/MQTT logic is annoying; maintaining thirty is impossible. ESPHome centralises that boilerplate.

The second is when you need OTA updates. Arduino IDE supports OTA but the setup is fiddly. ESPHome enables it by default with one line in the YAML config.

The third is when you want consistent behaviour across devices. Every ESPHome device reports through the same API, behaves the same on WiFi disconnect, and shows up in Home Assistant the same way. Three Arduino sketches written months apart almost always behave subtly differently.

The fourth is when you don't want to manage Arduino libraries. ESPHome handles library versions internally; you never see PlatformIO library conflicts or version drift.

The fifth is when you want declarative documentation. The YAML file is itself the documentation for what the device does. Past-you reading a 40-line YAML in six months will understand it; reading a 150-line Arduino sketch is much harder.

When Arduino IDE Still Wins

For honesty, three scenarios where Arduino IDE remains the better choice:

Very tight memory or timing requirements. ESPHome adds overhead compared to a hand-tuned Arduino sketch. For projects where you need every byte of flash or sub-millisecond timing, hand-coded Arduino still wins.

Sensor types ESPHome does not yet support. The catalogue is large but not infinite. If you have a niche sensor that lacks ESPHome support, an Arduino sketch with the vendor library is the fastest path until someone contributes ESPHome support.

Complex custom behaviour. ESPHome supports lambda expressions for custom logic, but past about 30 lines of lambda the YAML becomes harder to read than the equivalent Arduino C++. For genuinely complex behaviour, drop into Arduino.

Common Patterns Worth Knowing

Three patterns that show up in nearly every ESPHome config I write:

The "filter_out: nan" filter handles sensor disconnections gracefully. Without it, a momentary read failure pushes "NaN" into Home Assistant which breaks downstream automations. With it, the previous valid reading sticks until a new valid one arrives.

The deep sleep pattern for battery-powered devices uses the "deep_sleep" component with a time-based wakeup. A coin-cell ESP8266 contact sensor in deep sleep can last 90+ days; without deep sleep it lasts 18 hours. Use it on anything battery-powered.

The captive portal fallback gives the device a known recovery path if WiFi credentials change. Add the captive_portal component and the device boots into an access point mode when it cannot reach the configured WiFi, letting you connect from a phone to update credentials without USB.

Debugging ESPHome Devices

Three debugging approaches that work consistently:

Serial logging via USB shows live device behaviour. Connect the board, run "esphome logs config.yaml", and the device's log stream appears in the terminal. Useful for diagnosing boot loops, sensor read failures, or WiFi connection issues.

Wireless logging via the ESPHome dashboard works after the first flash. Click the device, then Logs. The dashboard streams the same log content over the API connection. Faster than reconnecting USB every time.

Home Assistant Developer Tools shows current state of every ESPHome entity. If a sensor reports through the device logs but doesn't appear in HA, the issue is the API connection rather than the sensor itself. Restart the ESPHome integration in HA, not the device.

What I Would Build First

For someone with one ESP8266 D1 Mini in a drawer, three projects worth tackling in order:

A temperature and humidity sensor with DHT22. The classic first ESPHome project. Cost: about 12 GBP including board. Takes 20 minutes from unpacking to first temperature reading in Home Assistant.

A motion sensor with a PIR module. Slightly more complex because the PIR has trim pots that need calibration. Cost: about 16 GBP. Pays back in motion-triggered hallway light automations.

A smart plug with a relay module wired to a wall socket. Important: this is mains voltage, use a proper enclosure or buy a pre-built smart plug and reflash it with ESPHome rather than wiring relays yourself. The reflash path is safer and cheaper than the DIY relay approach for most readers.

The Home Assistant ESPHome integration docs cover pairing edge cases (encryption keys, IP allocation, API timeouts). Most installs never need to look beyond the dashboard UI for setup. After three or four projects the ESPHome workflow becomes muscle memory, and writing custom sensors stops feeling like a project and starts feeling like normal smart home work.

ESPHome is the single biggest improvement I made to my smart home development workflow in the past five years. The 30 minutes spent learning it on the first project pays back across every sensor you build for the rest of the install's lifetime.

Cost Comparison Versus Commercial Sensors

For honesty about when DIY ESPHome makes economic sense, here are real costs from 2026 hardware orders. A custom ESPHome temperature sensor (ESP8266 D1 Mini at 4 GBP plus DHT22 at 4 GBP plus jumper wires at 1 GBP plus enclosure at 3 GBP) comes to about 12 GBP per device. The equivalent commercial Zigbee temperature sensor from Aqara or Sonoff costs 12-18 GBP. The cheapest WiFi commercial sensor from Tuya or Xiaomi runs 8-15 GBP.

On a per-sensor basis, DIY ESPHome saves nothing or actively costs more once you factor in time. Where DIY wins is the long tail: a wine fridge probe at 0.5-degree accuracy, a soil moisture sensor for a specific plant, a custom multi-sensor combining temperature plus light plus motion in one enclosure. Commercial equivalents for these niche cases either do not exist or cost 60-150 GBP.

The rule of thumb: buy commercial for the first 10-15 standard sensors (door contacts, basic temperature, motion) where market pricing is competitive. DIY ESPHome for the next 10-20 specialised sensors where you control the form factor, the protocol, and the data ownership. The hybrid approach keeps the smart home affordable while letting you build the parts no vendor sells.

Migration Path From Arduino to ESPHome

If you already have a few Arduino sensors running and want to migrate to ESPHome, the path is gradual rather than wholesale. Pick the most-recently broken Arduino device and rebuild it in ESPHome; ship that to production; observe behaviour for a week. Then migrate the second-most-recent.

The full migration of 8 Arduino sensors to ESPHome took me about three months at roughly one device per fortnight. The end result was lower maintenance burden, consistent OTA workflow, and unified logs. The migration was worth it in retrospect but not urgent enough to do in a weekend sprint. Treat it as a slow improvement project rather than a forced rewrite.