Many cheap smart plugs measure power with an HLW8012 or BL0937 chip, which reports watts, volts and amps as streams of pulses. ESPHome counts those pulses with its software pulse counter, and on plugs built around Beken or Realtek chips under LibreTiny that counting has long been unreliable. Pull request #21271, merged into ESPHome's development branch on 22 October 2026, changes how the counter listens to the pin.

What went wrong

The software pulse counter is used on ESP8266, RP2040, LibreTiny, nRF52, and on ESP32 when use_pcnt: false is set. It always attached an interrupt to both edges of the signal, then read the pin inside the interrupt handler to work out whether the edge was rising or falling. That happened even in the default setup, where only rising edges are counted and falling edges are ignored.

The weak spot is the pin read. On platforms where interrupts take a while to reach the handler, the level has often flipped back by the time it is read, so fast pulse trains such as the HLW8012's CF and CF1 outputs get counted on the wrong edge or not counted at all. The issue that led to the fix, opened on 21 October, says LibreTiny chips suffer most because their vendor SDKs react to GPIO interrupts more slowly than Espressif's. It links about ten older ESPHome and LibreTiny issues and pull requests with workarounds for the same problem.

What changes

The type of interrupt now depends on internal_filter, because a filter has to see both edges to measure a pulse:

  • With internal_filter set (the pulse_counter sensor defaults to 13 µs), nothing changes: both edges, with a pin read, so pulses that end inside the filter window are still rejected.
  • With internal_filter: 0us, ESPHome attaches the interrupt only to the edges that count. In the default setup (rising edges increment, falling edges disabled) that means a single-edge interrupt, and the handler no longer reads the pin at all.
  • If both edges are disabled, no interrupt is attached.

The hlw8012 and bl0937 components use the counter directly with no filter, so they get the single-edge path automatically. That is the case from the original report. A plain pulse_counter sensor on LibreTiny that needs the same behaviour can set internal_filter: 0us.

One side effect

The interrupt type is now chosen at setup. If a lambda changes the edge modes later, ESPHome logs an error and ignores the change. The pull request flags this as an undocumented C++ API change, so it matters only to people who adjust the counter from their own code.

The fix is in the development branch, so it should reach users with ESPHome 2026.11, unless it is also backported to a 2026.10 patch release. Plugs on Beken or Realtek chips whose power readings looked too low are the ones to recheck after updating.