Hi there,
I found a nice video about a Capacitive Water Level sensor: DIY Capacitive Water Level Sensor using ESP32 Touch Read function - YouTube
I‘m try to do it with ESPHome.
I‘m new with ESP Home.
I don‘t know how i can read the value of the gpio.
How can I create a value list with the different translation values?
Would be nice for a hint how i can solve this.
Regards
Adrian
nickrout
(Nick Rout)
November 1, 2022, 7:07pm
2
Thanks, I know this page.
I don‘t want a binary sensor but a Value/Level Sensor in percent.
zoogara
(Daryl)
November 2, 2022, 1:48am
4
Unfortunately there is no component in ESPHome that will do that, unless you use one of the I2C touch controllers.
You could have a go at writing a custom component.
You could also try defining multiple binary sensors using the same pin but with different threshold values. The compiler doesn’t complain if I do that - but I don’t have the hardware to test.
1 Like
I found a way to do that.
esphome yaml code:
esphome:
name: waterlevel
includes:
- waterlevel.h
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "xxxx"
ota:
password: "xxxx"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "waterlevel"
password: "xx"
captive_portal:
esp32_touch:
#setup_mode: true
sensor:
- platform: custom
lambda: |-
auto WaterLevel = new MyWaterLevel();
App.register_component(WaterLevel);
return {WaterLevel};
sensors:
name: "Water Level"
unit_of_measurement: "%"
accuracy_decimals: 0
waterlevel.h
class MyWaterLevel : public PollingComponent, public Sensor {
public:
#define TOUCHPIN 12
int reading;
MyWaterLevel() : PollingComponent(1000) { }
void setup() override {
}
void update() override {
reading = touchRead(TOUCHPIN);
publish_state(reading);
}
};
Next Step:
Calibration Table:
I need to create a table where i can set the following correlation:
60 = 0, 55= 10, 40= 20, 10=100 etc.
Someone an idee how?
mulcmu
November 2, 2022, 8:45pm
6
Calibrate linear or polynomial filter should work to map reading to level percent. This would let calibration be adjustable via yaml config. Otherwise you could write a function to map reading to the percent and pass that to publish_state()
publish_state(-0.0022*reading*reading*reading + 0.2778*reading*reading - 11.889*reading + 193.33);
Below sample uses a lambda call that will get the raw value from the esp32 touch binary sensor and returns it in a template sensor (as an alternative to your custom component).
esphome:
name: capacitive-level-test
esp32:
board: esp32dev
framework:
type: arduino
# Enable Home Assistant API
api:
logger:
baud_rate: 115200
ota:
password: !secret esp_home_ota_pw
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: homeassistant_time
esp32_touch:
setup_mode: false
binary_sensor:
- platform: esp32_touch
#name: "ESP32 Touch Pad GPIO27"
pin: GPIO27
threshold: 1000
id: capacitive_level_hack
sensor:
- platform: template
name: "Water Level"
icon: mdi:car-coolant-level
update_interval: 1s
lambda: |-
return (float) id(capacitive_level_hack).get_value();
filters:
- calibrate_linear:
- 20.0 -> 100.0
- 2080.0 -> 0.1
nickrout
(Nick Rout)
November 2, 2022, 9:45pm
7
Those figures, if accurate, are certainly not linear, so I would use a polynomial filter.
BUT if the vessel is regular in shape, then the volume will be linear and there is no need to use a filter at all, because the volume is just the surface area X the height. A simple lambda calc will work.
Hi nickrout.
I’m not sure if it will be linear or not.
I just ordered some copper tape. it will be here in 24h.
Then i will create a measurement ruler and show how it would work.
I will continue update this thread will all information.
@mulcmu Thanks a lot for your help. You made my day!!! Much easier this way.
nickrout
(Nick Rout)
November 3, 2022, 7:52am
9
Cheers, intrigued to know what vessel you are using. Happy to help
Hi there (@nickrout )
Here is my actual code:
substitutions:
devicename: waterlevel-humidificator
upper_devicename: WaterLevel Huidificator
ip: 10.xx.xx.xx
esphome:
name: $devicename
on_boot:
priority: -200
then:
- wait_until:
condition:
wifi.connected:
timeout: 5s
# workaround for "wifi auth expired"
#https://community.home-assistant.io/t/esphome-wifi-auth-expired/443790/22
i2c:
sda: 21
scl: 22
frequency: 800kHz
esp32:
board: esp32dev
framework:
type: arduino
deep_sleep:
run_duration: 60s
sleep_duration: 1740s
id: deep_sleep_1
wakeup_pin:
number: 12
inverted: True
mode: INPUT_PULLUP
wakeup_pin_mode: KEEP_AWAKE
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: !secret esphome_api_encryption_key
ota:
password: !secret esphome_ota
wifi:
fast_connect: true
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${devicename}_FH"
password: !secret wifi_hotspot_password
manual_ip:
static_ip: $ip
gateway: 10.xx.xx.xx
subnet: 255.255.255.0
dns1: 10.xx.xx.xx
captive_portal:
web_server:
port: 80
include_internal: true
esp32_touch:
setup_mode: false
switch:
- platform: restart
name: "Reboot ESP32"
icon: "mdi:restart"
binary_sensor:
- platform: status
name: "${upper_devicename} Status"
- platform: esp32_touch
pin: GPIO15
threshold: 2000
id: capacitive_level_hack
- platform: gpio
name: "${upper_devicename} Defeat"
id: "defeat"
pin:
number: 12
mode: INPUT_PULLUP
inverted: True
on_press:
then:
- logger.log: "Prevent deep sleep"
- deep_sleep.prevent: deep_sleep_1
on_release:
then:
- logger.log: "Allow deep sleep"
- deep_sleep.allow: deep_sleep_1
sensor:
- platform: template
name: "${upper_devicename}"
icon: mdi:car-coolant-level
#update_interval: 10s
update_interval: 1s
unit_of_measurement: "%"
lambda: |-
ESP_LOGD("custom", "INT: %u", id(capacitive_level_hack).get_value());
int MIN_VALUE = 32;
int MAX_VALUE = 112;
int CURR_VALUE = id(capacitive_level_hack).get_value();
if(MIN_VALUE <= CURR_VALUE && CURR_VALUE <= MAX_VALUE)
{
//ESP_LOGD("custom", "Return: %u", CURR_VALUE);
return CURR_VALUE;
}
else
{
if(CURR_VALUE < MIN_VALUE)
{
//ESP_LOGD("custom", "Return: %u", MIN_VALUE);
return MIN_VALUE;
}
else
{
//ESP_LOGD("custom", "Return: %u", MAX_VALUE);
return MAX_VALUE;
}
}
accuracy_decimals: 0
filters:
- calibrate_polynomial:
degree: 3
datapoints:
# Map 0.0 (from sensor) to 0.0 (true value)
- 112 -> 0.0 #
- 86 -> 20.0 #
- 54 -> 40.0 #
- 45 -> 60.0 #
- 38 -> 80.0 #
- 32 -> 100.0 #
- heartbeat: 5s
- quantile:
window_size: 7
send_every: 4
send_first_at: 3
quantile: .9
- platform: adc
name: "${upper_devicename} Battery voltage"
pin: GPIO34
id: GPIO34
accuracy_decimals: 2
update_interval: 5s
attenuation: 11dB
filters:
- multiply: 2.0 # The voltage divider requires us to multiply by 2
- quantile:
window_size: 7
send_every: 4
send_first_at: 3
quantile: .9
- platform: template
name: "${upper_devicename} Battery Percent"
icon: mdi:car-coolant-level
update_interval: 15s
unit_of_measurement: "%"
accuracy_decimals: 0
lambda: |-
return (float) ((id(GPIO34).state));
filters:
- calibrate_polynomial:
degree: 2
datapoints:
# Map 0.0 (from sensor) to 0.0 (true value)
- 4.3 -> 100.0
- 4.2 -> 100.0
- 4.1 -> 94.0
- 4.0 -> 84.0
- 3.9 -> 74.0
- 3.8 -> 62.0
- 3.7 -> 53.0
- 3.6 -> 39.0
- 3.5 -> 22.0
- 3.4 -> 13.0
- 3.3 -> 3.0
- 3.2 -> 0.0
- 3.1 -> 0.0
- heartbeat: 20s
text_sensor:
# Reports the ESPHome Version with compile date
- platform: version
name: ${upper_devicename} ESPHome Version
The sensor runs since 10 days on battery (NCR18650B) 3200mAh and has 80% (4.000V) capacity.
Regards,
Adrian
2 Likes
And here how i made the waterlevel hardware sensor:
1 Like
hr33losi
(Hr33losi)
June 27, 2024, 5:18pm
12
I am working on the same proj right now…i do not know why i am getting always increase readings at a stable height. any thoughts?
I am not able to calibrate it at all because the values keep on increasing at a particular height.
In this video, he has done the 2 copper foils in pairs- but i have cut it into two separate foils. and stuck it in opposite sides of the wall. will that make any difference?
Sorry, I didn‘t saw your question.
Did you solve your problem?
Spiro
November 5, 2024, 7:28am
14
I imagine the copper will react with the water and this will change it’s capcitance.