Using a ESP32 with QMC5883L compass module. TBD
Quite accurate, each interval (max to min to max) from the water meter appears to be 32.5ml, this was confirmed over the course of a few days and about 1.6 m³ of water (about 49 thousand intervals).
This is still a work in progress, and will need some customization for your specific installation (such as defining which magnetic axis to monitor and thresholds).
esphome: name: WaterMeter friendly_name: water project: name: "photonicsguy.Water Meter Sensor" version: "0.1.2" on_boot: priority: 300 then: - lambda: |- id(sample)=id(total_pulses); esp32: board: esp32dev framework: type: arduino version: recommended # Don't use VERBOSE or DEBUG logging when Hall sensor has fast updates logger: level: WARN # Enable Home Assistant API api: encryption: key: !secret ha_key ota: password: !secret ota_passwd wifi: ssid: !secret wifi_ssid password: !secret wifi_password i2c: - id: bus_a sda: 4 scl: 15 frequency: 800kHz scan: true text_sensor: - platform: wifi_info ip_address: name: IP Address entity_category: "diagnostic" switch: - platform: restart name: "Reboot" - platform: template name: "Reset usage" id: resetusage optimistic: false icon: mdi:water-sync restore_mode: ALWAYS_OFF turn_on_action: then: - lambda: |- id(sample)=id(total_pulses); id(wateruse).publish_state((id(total_pulses)-id(sample)) * 0.01 * id(offset)); number: - platform: template name: "Threshold Minimum" id: minVal optimistic: true restore_value: true entity_category: config initial_value: 70 min_value: -200 max_value: 200 step: 5 unit_of_measurement: "µT" set_action: - lambda: id(pulse).set_lower_threshold(x); - platform: template name: "Threshold Maximum" id: maxVal optimistic: true restore_value: true entity_category: config initial_value: 90 min_value: -200 max_value: 200 unit_of_measurement: "µT" step: 5 set_action: - lambda: id(pulse).set_upper_threshold(x); - platform: template name: "Threshold Minimum alt" id: minVal2 optimistic: true restore_value: true entity_category: config initial_value: 40 min_value: -200 max_value: 200 step: 5 unit_of_measurement: "µT" set_action: - lambda: id(pulse2).set_lower_threshold(x); - platform: template name: "Threshold Maximum alt" id: maxVal2 optimistic: true restore_value: true entity_category: config initial_value: 60 min_value: -200 max_value: 200 unit_of_measurement: "µT" step: 5 set_action: - lambda: id(pulse2).set_upper_threshold(x); globals: - id: total_pulses type: int restore_value: True initial_value: '0' - id: sample type: int restore_value: False initial_value: '0' - id: offset type: float restore_value: False initial_value: '3.25' sensor: - platform: wifi_signal name: "RSSI" id: rssi_db filters: - delta: 2 - throttle: 300s entity_category: "diagnostic" - platform: qmc5883l i2c_id: bus_a address: 0x0D field_strength_x: name: "Field Strength X" id: fsx internal: true range: 200uT oversampling: 64x update_interval: 0.005s - platform: template name: "Water Consumption new" id: waterconsumption3 device_class: water unit_of_measurement: "m³" state_class: "total_increasing" icon: "mdi:water" accuracy_decimals: 4 lambda: |- return id(total_pulses) * 0.00001 * id(offset); - platform: template name: "Water usage" id: wateruse device_class: water unit_of_measurement: "L" state_class: "measurement" icon: "mdi:hand-water" accuracy_decimals: 2 lambda: |- return (id(total_pulses)-id(sample)) * 0.01 * id(offset); - platform: template name: "Counter" unit_of_measurement: pulses id: watercounter lambda: |- return id(total_pulses); binary_sensor: - platform: analog_threshold name: "Pulse" # Cover closed id: pulse #internal: True sensor_id: fsx threshold: upper: 90 lower: 80 on_state: then: - lambda: |- id(total_pulses) += 1; id(waterconsumption3).publish_state(id(total_pulses) * 0.00001 * id(offset)); id(wateruse).publish_state((id(total_pulses)-id(sample)) * 0.01 * id(offset)); id(watercounter).publish_state(id(total_pulses)); - platform: analog_threshold name: "Pulse2" #Cover open id: pulse2 sensor_id: fsx threshold: upper: 60 lower: 40 on_state: then: - lambda: |- id(total_pulses) += 1; id(waterconsumption3).publish_state(id(total_pulses) * 0.00001 * id(offset)); id(wateruse).publish_state((id(total_pulses)-id(sample)) * 0.01 * id(offset)); id(watercounter).publish_state(id(total_pulses));