Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Magnetometer Water Meter → Home Assistant

Reading a residential water meter with an ESP32 and a magnetometer, reporting live flow rate and cumulative volume to Home Assistant via ESPHome.

No utility cooperation required, no plumbing modification, no cutting into the water line. The sensor tapes to the outside of the meter body.


How it works

Positive-displacement water meters use a nutating disc that drives a magnet. That magnet turns the register dials. A magnetometer taped to the meter body sees the magnet as a rotating field; count the rotations, multiply by a calibrated volume-per-rotation, and you have consumption.

[rotating magnet in meter] --magnetic field--> [QMC5883P] --I2C--> [ESP32]
                                                                     |
                                                                   WiFi
                                                                     |
                                                            [Home Assistant]

This works on essentially any positive-displacement meter regardless of what radio or register is attached to it.

Rotation counting, threshold detection, and volume math are handled by tronikos/esphome-magnetometer-water-gas-meter. This repo is the config, the dashboard, and the gotchas.

Tested on a 3/4" positive-displacement residential meter.


Hardware

Part Notes
ESP32 WROOM-32 DevKit (30-pin) Any common clone works
GY-271 magnetometer breakout See the chip warning below
4x female-female jumper wires Or solder directly
USB power supply 5V, any phone charger

Wiring

wiring diagram

Four wires. The magnetometer speaks I²C, which needs two data lines plus power and ground — that's the whole connection.

GY-271 ESP32 Purpose
VCC 3V3 Power
GND GND Ground
SDA GPIO21 I²C data
SCL GPIO22 I²C clock
DRDY not connected Data-ready interrupt, unused

Female-to-female DuPont jumpers push straight onto both headers, so no soldering is needed beyond attaching the 4-pin header to the breakout if it shipped loose.

Power from 3V3, not VIN

The GY-271 board is rated 3–5 V, so 5 V will not damage the magnetometer itself. The problem is the two I²C pull-up resistors on the breakout: they tie SDA and SCL to whatever you feed VCC. Power the board at 5 V and those lines idle at 5 V, driving the ESP32's 3.3 V GPIO pins out of spec. It often appears to work, then degrades the pins over time.

Running VCC from 3V3 puts the whole bus at 3.3 V and the problem disappears. No level shifter and no external pull-ups are needed — the ones on the breakout are already correct for a short bench-length bus.

Why GPIO21 and GPIO22

Nothing about those pins is special. The ESP32 can route I²C to almost any GPIO, and the pin assignment is set in the YAML:

i2c:
  sda: GPIO21
  scl: GPIO22

They are simply the convention — ESPHome's examples and most tutorials use them, so sticking with the default keeps your config comparable to everyone else's. If you need to move them, avoid GPIO6–11 (wired to the internal flash chip) and the strapping pins GPIO0, 2, 12, and 15, which affect boot mode.

Pin labels vary between clones

Silkscreen on the 30-pin WROOM-32 DevKits is inconsistent. The 3.3 V pin may read 3V3, 3.3V, or occasionally just 33. GPIO pins may be labeled D21/D22 or bare 21/22. On the GY-271 side, pin order is usually VCC, GND, SCL, SDA, DRDY — note that SCL comes before SDA, which is the opposite of the order people tend to assume, and is the most common wiring mistake with this board.

If SDA and SCL are swapped, the I²C scan finds nothing at all rather than reporting an error. A silent empty scan is the symptom.

Verifying the connection

Before flashing the full config, flash a minimal one and read the boot log:

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true

A working bus prints the device address:

[C][i2c.idf:113]: Results from bus scan:
[C][i2c.idf:119]: Found device at address 0x2C

Found no i2c devices! means one of: SDA/SCL swapped, VCC not connected, a cold solder joint on the header, or a dead board. Check in that order — swapped data lines and bad solder joints account for nearly all cases.

The address itself tells you which chip you have, which determines the ESPHome platform. See the next section.


The GY-271 chip lottery

Boards sold as "GY-271 QMC5883L" ship with at least three different chips. Scan the I2C bus before assuming anything:

Address Chip ESPHome platform
0x1E HMC5883L hmc5883l (built in)
0x0D QMC5883L qmc5883l (built in)
0x2C QMC5883P external component — see below

This build got a QMC5883P at 0x2C, which ESPHome does not support natively. The register map differs from the QMC5883L despite the near-identical name, so pointing the qmc5883l platform at it silently fails — no error, just no readings.

The fix is the qmc5883p.yaml overlay in the tronikos package, which pulls in mazzhead/esphome-components. It's already wired up in water-meter.yaml.

To scan, flash a minimal config with i2c: { scan: true } and read the boot log.


Placement is everything

This was the single biggest factor in getting it working, and it is worth more than any amount of config tuning.

Magnetic field strength falls off with roughly the cube of distance. Halving the gap between the chip and the magnet increases signal by ~8x.

Measured on this meter:

Sensor position Signal swing Result
~1 cm off, poorly aligned ~2.8 uT Calibration failed: low signal
Pressed against the housing, hunted for the hotspot ~85 uT Works reliably

Noise floor on this sensor is roughly 2-4 uT, so the first position was producing a signal barely distinguishable from noise.

Find the hotspot first. Install a magnetometer app on your phone (Physics Toolbox, Sensors, etc.), run water, and sweep the phone slowly across the meter face watching for the largest oscillation. Mount the sensor there. The strongest point is often off-center rather than directly on top.


Setup

  1. Wire it up per the table above.
  2. Flash a scan config and note the I2C address from the boot log.
  3. Copy water-meter.yaml, adjusting the files: list if your chip is not a QMC5883P.
  4. Select the axis. In Home Assistant, set the Axis dropdown to whichever of X/Y/Z shows the largest swing under flow. Watch the ESPHome log's Got x=... y=... z=... lines with qmc5883p: DEBUG — much easier to read than the HA history graphs.
  5. Calibrate. With water running, trigger the calibration entity. It sets thresholds from the observed min/max. Calibration Status will report Ready or Failed: low signal — the latter means go back to placement.
  6. Set volume per half rotation. Note the meter dial reading and the half-rotation count, run a measured volume, then divide gallons used by half-rotations counted. More volume gives a better figure.
  7. Hide the diagnostic sensors. Set both hide_* substitutions to 'true' and reinstall. The magnetic field sensors publish every ~5 ms and are a real load on the ESP; hiding them improves accuracy at high flow.

Home Assistant

Flow gauge card

flow-gauge-card.yaml

A custom:button-card (HACS) showing an animated pump dial — the water level rises with flow and the impeller spins proportionally.

Energy dashboard

Add sensor.water_meter_total as a water source under Settings → Dashboards → Energy.

Watch out: changing Volume per half rotation rescales Total, and with state_class: total_increasing a decrease reads as a meter reset — HA records the entire new value as fresh consumption, producing enormous phantom spikes. Fix via Developer Tools → Statistics → adjust or delete the statistic. recorder.purge_entities does not clear long-term statistics.


License

This repository is licensed under the MIT License — see LICENSE.

That covers the contents of this repo only: the ESPHome device configuration, the Home Assistant card, the wiring diagram, and this documentation.

Upstream projects

This project does not bundle or redistribute any third-party code. The packages below are fetched at build time from their own repositories and remain under their own licenses:

Project License Role
tronikos/esphome-magnetometer-water-gas-meter Apache-2.0 Rotation counting, calibration, and volume math — the actual meter-reading logic
mazzhead/esphome-components see repo QMC5883P driver, pulled in by the qmc5883p.yaml overlay
custom-cards/button-card MIT Renders the flow gauge card

Nearly all of the difficult work here belongs to tronikos. If this project is useful to you, star that repository — this one is a thin configuration layer, some hardware notes, and a dashboard card on top of it.

A note on authorship

Portions of the documentation, the wiring diagram, and the dashboard card SVG were drafted with AI assistance. The hardware findings, measurements, and testing are the author's own.

About

ESP32 + QMC5883P magnetometer reading a water meter into Home Assistant. Includes the GY-271 chip-identification gotcha.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors