Zigbee waterflow meter for Clack valve using ESP32-C6
This is a personal project, based on this tutorial and Ai aid.
I am using this ESP32-C6 Development Kit and Arduino IDE.
Arduino IDE settings:
USB CDC On Boot: "Enabled"
CPU Frequency: "160MHz (WiFi)"
Core Debug Level: "None"
Erase All Flash Before Sketch Upload: "Disabled"
Flash Frequency: "80MHz"
Flash Mode: "QIO"
Flash Size: "4MB (32Mb)"
JTAG Adapter: "Disabled"
Partition Scheme: "Zigbee 4MB with spiffs"
Upload Speed: "115200"
Zigbee Mode: "Zigbee ED (end device)"
It will do the following:
- LED is red prior to connecting to Zigbee, it turns green when connected
- LED will blink when PIN 10 reads some pulses
- Pin 10 will read the pulse from the Clack WS-1 meter and calculate the water usage, unit is Litre
- It will report the data via Zigbee, to be used on Home Assistant
- It will save the reading to the ESP32-C6 board, treated like a real water meter.
Code
#include <Preferences.h>
#include "Zigbee.h"
#define WATER_PIN 10
#define PULSES_PER_LITER 17
#define FLOW_SENSOR_ENDPOINT_NUMBER 10
#define SAVE_INTERVAL 1800000 // 30 minutes in milliseconds
#define RGB_BRIGHTNESS 50 // LED brightness
Preferences preferences;
int pulseCount = 0;
float totalLiters = 0.0;
bool isLowVoltage = true;
bool isConnected = false;
uint32_t lastReportTime = 0;
uint32_t lastSaveTime = 0;
ZigbeeFlowSensor zbFlowSensor = ZigbeeFlowSensor(FLOW_SENSOR_ENDPOINT_NUMBER);
void setLEDColor(uint8_t red, uint8_t green, uint8_t blue) {
#ifdef RGB_BUILTIN
rgbLedWrite(RGB_BUILTIN, red, green, blue);
#endif
}
void saveToNVS() {
preferences.putFloat("totalLiters", totalLiters);
Serial.println("Saved to NVS");
}
void loadFromNVS() {
totalLiters = preferences.getFloat("totalLiters", 0.0);
Serial.printf("Loaded from NVS: %.3f L\n", totalLiters);
}
void setup() {
Serial.begin(115200);
pinMode(WATER_PIN, INPUT_PULLUP);
preferences.begin("water_meter", false);
loadFromNVS();
setLEDColor(RGB_BRIGHTNESS, 0, 0); // Red at start
zbFlowSensor.setManufacturerAndModel("Espressif", "ZigbeeWaterMeter");
Zigbee.addEndpoint(&zbFlowSensor);
Serial.println("Starting Zigbee...");
if (!Zigbee.begin()) {
Serial.println("Zigbee failed to start! Rebooting...");
ESP.restart();
}
while (!Zigbee.connected()) {
delay(100);
}
isConnected = true;
setLEDColor(0, RGB_BRIGHTNESS, 0); // Green when connected
zbFlowSensor.setReporting(0, 60, 1.0);
}
void loop() {
int waterValue = digitalRead(WATER_PIN);
if (waterValue == LOW) {
if (isLowVoltage) {
pulseCount++;
isLowVoltage = false;
totalLiters += 1.0 / PULSES_PER_LITER;
zbFlowSensor.setFlow(totalLiters);
Serial.printf("Total Water Usage: %.3f L\n", totalLiters);
// Blink LED to indicate water flow
if (isConnected) {
setLEDColor(0, 0, 0); // Off
delay(100);
setLEDColor(0, RGB_BRIGHTNESS, 0); // Back to green
}
}
} else {
isLowVoltage = true;
}
if (millis() - lastReportTime >= 60000) { // Report to HA every 60s
zbFlowSensor.report();
lastReportTime = millis();
}
if (millis() - lastSaveTime >= SAVE_INTERVAL) { // Save to NVS every 30 minutes
saveToNVS();
lastSaveTime = millis();
}
}
Add a sensor on configuration.yaml on Home Assistant:
- sensor:
- name: "Total Water Usage"
unique_id: total_water_usage
state: "{{ states('sensor.espressif_zigbeewatermeter') | float(0) }}"
unit_of_measurement: "L"
device_class: water
state_class: total_increasing