Thomas shares makes


Heater-on-light tracking using Home Assistant

hacked circuit

Living in a house with Aterno resistive electric heating, I wanted to get a feel of how our thermostat settings and outside temperature impacts our electricity bill.

I did not want to change the electric installation to add invasive interfacing like current sensing, and hacked a ZigBee door sensor to report on the heater's status LED.

home assistant energy tab



I improvised a first version of the circuit with parts I had at hand:

arduino optical sensor module
  • A light dependent resistor (LDR), which yields about 1.7kOhm when the LED hits it, and > 10kOhm in the relative dark.
  • A Xiaomi Aqara 'zigbee' door & window contact sensor (MCCGQ11LM), of which I also use several to track doors and the doorbell.
  • A TCRT5000 optical sensor module, typically used in educational line following robots.
  • Double AA battery holder with wires (to replace the 1620 coin cell)

Hooking up the LDR straight over the reed switch did not work, so I performed some experiments with using a LED as light sensor together with a Darlington transistor pair. The ZigBee module's input is quite sensitive, so I decided to try a comparator and ignore the circuit's battery life for now (the circuit draws 0.9mA, which could last 2.5months on LR6 AA batteries).

I had a TCRT5000 optical sensor module, which among other things had the required LM393 and a variable resistor on a small pcb. Perfect! I removed the sensor module's LEDS and replaced the phototransistor by the LDR, leaving only the LM393 comparator and some resistors and a cap.

The comparator compares the voltage over the LDR against a reference voltage produced by a potentiometer, and if the LDR's voltage drops below that, it pulls its output pin to ground. The door sensor's reed switch also shorts the ZigBee microcontroller's I/O pin to ground, so I simply had to connect the two.

For testing purposes, I improvised a little fixture to align the LDR with the radiator's LED by reusing 3D printed scrap prototype cut to form, and fixed it using double sided tape to the radiator's control box. This proved to be very unreliable so I designed an alignment jig which I 3D printed:

alignment jig

The next step is to turn the alignment jig into an enclosure that holds the AA batteries and circuit boards.

Definitive hardware

I used a SOP8 to DIP adapter PCB to break out the LM393 to a more workable footprint. I added through-hole and surface mount resistors to provide a fixed voltage divider. I also switched the positive and negative inputs of the comparator so no extra template entity to invert the signal is needed in Home Assistant.

comparator photo 1
comparator photo 2

I designed an enclosure around the LED alignment jig I had made earlier.


This has room for two AA batteries and the two circuit boards.


Home assistant configuration

Inverting the signal

When the radiator is heating, the comparator shunts the reed switch, resulting in a 'closed' door. Since that is the idle state of the binary sensor, I invert it with a template sensor in binary_sensors.yaml:

- platform: template
      friendly_name: 'Resistive Heating'
      value_template: >-
          {{ is_state('binary_sensor.heaterliving_contact','off') }}
      icon_template: 'mdi:radiator'

This creates a nice entity in home assistant:

inverted binary sensor

Integrating over time

A new history_stats integration is set up in sensors.yaml to track the total on time:

- platform: history_stats
  name: Heatingtime
  entity_id: binary_sensor.heaterliving_contact_inverted
  state: 'on'
  type: time
  start: '{{ now().replace(hour=0, minute=0, second=0) }}'
  end: '{{ now() }}'
time tracking binary sensor

Applying power usage of the heater

Energy is time x power, so we need to multiply the heating-time-sensor's value (in hours) with the radiators average 4.8kW (actually two radiators of 3kW and 1,8kW). To get a more accurate value, the actual power the radiator draws should be determined. This is done using yet another template sensor, in sensors.yaml:

- platform: template
       device_class: energy
       unit_of_measurement: kWh
       value_template: >
         {% if is_number(states('sensor.Heatingtime')) %}
         {{ states('sensor.Heatingtime')|float * 4.8  }}
         {% else %}
         {% endif %}
       last_reset: '{{ now().replace(hour=0, minute=0, second=0) }}'
       state_class: 'total_increasing'
energy tracked template sensor

Liked something? Worked on something similar? Let me know what you think on Mastodon!
You can use your Mastodon account to reply to this post.

Reply to post

You can respond to this post with an account on the Fediverse or Mastodon. Since Mastodon is decentralized, you can use your existing account or create your account on a server of your choice.

Copy and paste this URL into the search field of your favourite Fediverse app or the web interface of your Mastodon server.

Learn how @carlschwan wrote the code that loads Mastodon posts into this webpage here.

Follow me on Mastodon!