In my home, I have a mechanical ventilation system with heat recovery powered by Stiebel Eltron V-400. Basically, it’s a large fan with air inflows and outflows ducts. Besides some built-in automation, it’s a pretty dumb device. Without a dedicated gateway (which costs extra money), I can only control it or see its current parameters on the controller, either on the unit or in the hall.

I thought it would be nice to collect some data from this device, both for some kind of analysis and out of curiosity. I run Home Assistant, which can display dedicated graphs and dashboards for such purpose. And, because I recently played with ESP boards, the idea was born pretty quickly.

Parts

For this project I used Dallas DS18B20 temperature sensors and a Wemos D1 with ESP8266 onboard. I picked the Wemos D1 because of 5V output, compact size, and because I had a one spare at this moment.

The Dallas DS18B20 is well-known for its 1-wire protocol, which allows you to connect multiple temperature sensors to a single data line. If you’ve ever wondered about the project where you can use more than one DS18B20 temperature sensor on a single board – here’s one.

I also had a 6-pin LED wire, which I split and used to connect the sensors to the board. For power, I used an old phone charger and a USB-C cable.

ESP8266 on Wemos D1, DS18B20 and pins
Most important parts: Wemos D1 powered by ESP8266 and 5x DS18B20

Plan

The heat recovery unit has four air pipes – two pairs of inflows and outflows. One pair handles air exchange with the outside, while the other circulates air within the house. The airflow setup is as follows:

Schema of Stiebel Eltron V-400 airflow
Schematic diagram of Stiebel Eltron V-400 airflow pipes

I expected these four pipes would carry air at different temperatures. Inside each one, I placed a single DS18B20 sensor. I added an extra one to measure the temperature in the attic, where the ventilation unit is installed.

Schema of DS18B20 placement within the Stiebel Eltron V-400 airflow pipes
Schematic diagram of DS18B20 placement within the Stiebel Eltron V-400 airflow pipes

As I mentioned earlier, the DS18B20 uses 1-wire interface, so all sensors can share the same data line. Instead of wiring sensors one into another in a form of chain, I connected them in a star topology, where each sensor has its own dedicated wires, but shares a common data pin.

Preparation

First – the sensors. Soldering the first one was fun, but each subsequent one became a bit more tedious. I soldered each sensor to a wire strip about half a meter long.

Wires prepared to be soldered to DS18B20 sensor
Wires prepared to be soldered to DS18B20 sensor
DS18B20 sensor with wires soldered
DS18B20 sensor with wires soldered
DS18B20 sensor with soldered wires and secured connections
DS18B20 sensor with soldered wires and secured connections

I wanted to connect everything on the breadboard. Unfortunately, I realised I was still missing the Dupont crimper needed to prepare proper pins for the sensor wires. I ended up using Wago connectors to make all connections.

I connected the data line to pin D13 (GPIO13) on the Wemos D1.

ESP8266 Wemos D1 with the DS18B20 sensors connected using Wago connectors on breadcrumb board
ESP8266 Wemos D1 with the DS18B20 sensors connected using Wago connectors on breadcrumb board

Firmware

I didn’t write the ESP firmware myself. Instead, I decided to use ESPHome which works seamlessly with Home Assistant.

Setting up the ESP with ESPHome was one of the most magical experiences I’ve had. Even though I enjoy digging into programming and writing things from scratch, being able to generate firmware from a YAML file is just wonderful.

Identifying sensors

I started with a basic ESPHome project, configured WiFi connection and set up the one_wire protocol.

one_wire:
  - platform: gpio
    pin: GPIO13

Then, after flashing the firmware, ESP printed the addresses of the connected sensors

[13:47:40][C][gpio.one_wire:021]:   Pin: GPIO13
[13:47:40][C][gpio.one_wire:080]:   Found devices:
[13:47:40][C][gpio.one_wire:082]:     0x48e2a7bc12fa3651 (DS18B20)
[13:47:40][C][gpio.one_wire:082]:     0xc903deab6719b425 (DS18B20)
[13:47:40][C][gpio.one_wire:082]:     0x1f64b28d4ca713ff (DS18B20)
[13:47:40][C][gpio.one_wire:082]:     0xa82fbac2e19d54e7 (DS18B20)
[13:47:40][C][gpio.one_wire:082]:     0x702c19f8ab65e038 (DS18B20)

All of my sensors were visible, but there was one problem. I wanted to name each sensor correctly, but I didn’t know which address was assigned to each one. Fortunately, the sensors are very sensitive and I just registered all of them, assigning the names. Then, I warmed up a specific one and observed which temperature reading increased.

That could have been enough, but I decided to use the different colored wires for inner flow and outer flow temperatures, so I needed to update the names accordingly. I ended up with the list as follows.

sensor:
  - platform: dallas_temp
    id: temp_inner_inflow
    address: 0x48e2a7bc12fa3651
    name: temp_inner_inflow
    update_interval: 60s 
  - platform: dallas_temp
    id: temp_inner_outflow
    address: 0xc903deab6719b425
    name: temp_inner_outflow
    update_interval: 60s
  - platform: dallas_temp
    id: temp_outer_inflow
    address: 0x1f64b28d4ca713ff
    name: temp_outer_inflow
    update_interval: 60s
  - platform: dallas_temp
    address: 0xa82fbac2e19d54e7
    name: temp_attic
    update_interval: 60s
  - platform: dallas_temp
    address: 0x702c19f8ab65e038
    name: temp_outer_outflow
    update_interval: 60s

Temperature efficiency

With all those temperatures available, I configured another sensor to calculate the temperature efficiency of the heat exchanger.

The formula is

η=T2T1T3T1×100

  • T1 – outdoor temperature before heat exchanger
  • T2 – temperature of supply air after heat exchanger
  • T3 – temperature of extracted air from rooms

The ESPHome definition:

sensor:
  - platform: template
    name: efficiency
    filters:
      - round: 2
    unit_of_measurement: '%'
    state_class: "measurement"
    accuracy_decimals: 1
    lambda: |-
      float t1 = id(temp_outer_inflow).state;
      float t2 = id(temp_inner_inflow).state;
      float t3 = id(temp_inner_outflow).state;
      float eff = (t2 - t1) / (t3 - t1);
      return eff * 100;
    update_interval: 60s

I could have done the same using a Home Assistant template sensor. However, doing it directly on the ESP allowed me to offload some work from the main instance and bring the calculation closer to the data source. The data is already available to the ESP, so it can expose the pre-calculated value as part of its API.

Deployment

The initial deployment was a bit different from a traditional software development workflow. I had to visit my attic, gently place all the sensors inside the air pipes according to the plan, and power up the Wemos D1 board.

Once everything was in place, I switched over to Home Assistant.

Home Assistant dashboard

Since I already had ESPHome integrated with Home Assistant, the new device was automatically discovered and all exposed entities were registered. I tweaked the names and prepared a dashboard to have a quick overview of my ventilation unit.

Custom Home Assistant showing temperature on each sensor
The image shows low efficiency and temperatures, that don’t look great in terms of heat exchange but no worries – that’s because the unit was operating in bypass mode at the time. I’ll provide a better image when it’s cooler.

I’m not going to show you step-by-step configuration here, but if you think it would be useful for you, just drop me a message. I’ll be happy to share the details.

Final thoughts

This setup is working flawlessly for half a year. In the next iteration, I’m going to give the ESP a dedicated case and replace the Wago connector. But once it’s working, the urge to improve it is lower than I expected.

I hope you found this write-up useful. Thanks for reading!