I’ve gotten tired of having to remember to check the water reservoir for the Christmas tree, so I’ve used an ESP32 and an ultrasonic sensor to let me know the level of the water under the tree. It’s even got a festive light, and I hung it from a branch using an ornament hook so it’s the first light AND ornament on the tree!
I’ve created some “convenience” sensors to provide details like the % of water remaining from the “max fill” line (I initially put in 5 liters of water, so that’s what I’m considering the max) and the amount of liters remaining based on the % remaining * max_fill, etc… This will really help me keep the tree hydrated this year. The math is made a little easier by the fact that 5 liters is 10cm high in the stand that I have! To keep it safe from the water, the ultrasonic sensor is mounted higher than that, 14cm from the bottom of the stand, so I have a few global variables that help with those calculations.
This is based on another ESPHome project I have that’s doing relatively the same thing in my water softener in the basement (another thing I neglect to check on regularly).
The configuration is:
esphome:
name: christmas-tree
esp32:
board: esp32dev
framework:
type: arduino
globals:
# distance between bottom of container and sensor position
- id: sensor_height
type: float
initial_value: '0.14'
# distance between max fill line and sensor position
- id: distance_offset
type: float
initial_value: '0.04'
# distance between bottom of container and max fill line
- id: max_fill_height
type: float
initial_value: '0.10'
# max volume of container in liters
- id: max_volume
type: float
initial_value: '5.0'
sensor:
- platform: ultrasonic
id: "raw_distance"
trigger_pin: GPIO17
echo_pin: GPIO18
name: "Water Level Distance"
update_interval: 10s
unit_of_measurement: "m"
- platform: copy
source_id: "raw_distance"
name: "Water Level Distance From Max Fill Line"
filters:
# Calculates distance, in centimeters, of the difference between the max fill line height and the current level
- lambda: return (x - id(distance_offset)) * 100;
unit_of_measurement: "cm"
- platform: copy
source_id: "raw_distance"
name: "Remaining Water Level"
filters:
# Calculates height, in centimeters, of water pellets remaining
- lambda: return (id(sensor_height) - x) * 100;
unit_of_measurement: "cm"
- platform: copy
source_id: "raw_distance"
name: "% Remaining Water Level"
filters:
# Calculates % of water remaining
- lambda: return (id(sensor_height) - x) * (100/id(max_fill_height));
unit_of_measurement: "%"
- platform: copy
source_id: "raw_distance"
name: "Liters Remaining"
filters:
# Calculates remaining volume based on % remaining
- lambda: return ((id(sensor_height) - x) * (100 / id(max_fill_height)) / 100) * id(max_volume);
unit_of_measurement: "l"