I bought this sensor and interface card from AliExpress:
Waterproof Ultrasonic Module JSN-SR04T / AJ-SR04M Water Proof Integrated Distance Measuring Transducer Sensor for Arduino
With some plastic pipes for plumbing i created sensor ‘cork’:
and I replaced old mechanical meter on tank with it:
Created esphome device which measures distance from sensor to oil surface and from that is possible to calculate content of tank.
I also measuring temperature of tank using Dallas DS18B20 one wire sensor, but at this time temperature is not used in volume calculation yet.
I placed esphome device in plastic case on the wall near the tank and also added display to be able read data in place.
Schematics drawn by hand:
Program:
#
# Ultrasound distance measurement
#
# Wiring:
# + 5V (positive power supply) -> 5V
# Trig (control side) RX -> D5
# Echo (the receiver) TX -> D6
# GND (negative) -> GND
# Na D4 je status led (na pločici)
#
# https://markus-haack.com/ultrasonic-distance-sensors-esphome/
# https://www.aliexpress.com/item/32665460264.html?spm=a2g0o.order_list.order_list_main.69.608c1802MeRvmI
#
# 2023-12-02:
# - Initial version
#
# 2023-12-03:
# - Dodan I2C LCD display 16x2
# - Wiring:
# + 5V (positive power supply) -> 5V
# scl -> D1
# sda -> D2
# GND (negative) -> GND
# - Ispisuje sadržaj input_text.heat_fuel_display_l1 u liniji 1
# - Ispisuje sadržaj input_text.heat_fuel_display_l2 u liniji 2
#
# 2023-12-04:
# - Dodano zaboravljeno id(api_was_connected) = 1; u on_boot sekciju
#
# 2023-12-15:
# - Dodan template sensor "${devname} Raw distance" koji šalje svaku
# izmjerenu vrijednost distance prije svih filtera
# - Povećano vrijeme između mjerenja na 10s
# - Produžen uzv impuls na 80us što doprinosi pouzdanijem odzivu
#
# 2023-12-16:
# - Isproban prototip na stvarnom tanku i radi
# - Između D3 i GND dodan pushbutton koji se vidi kao senzor button
# - te kao akcija: single, double, triple ili hold
# - Dodan switch LCD Backlight te servisi backlight_on i backlight_off.
# Svi oni preko scripta display_on i display_off kontroliraju LCD backlight.
#
# 2023-12-17:
# - Dodana plava led dioda za status
# S D4 ide 4k7 na anodu, a katoda ide na GND
# - Dodan Dallas DS18B20 da mjeri temperaturu tanka
# Spojen s 1,5m telefonske flat žice
# VCC na 5V, GND na GND, data pin DQ na D7 na ESP8266
# Pull up otpornik od 4k7 stavljen na stranu senzora
#
# 2023-12-31:
# - Podešeni parametri ultrasonic senzora i stavljen filter: sliding_window_moving_average
# - Uređaj je u upotrebi
#
#
# 2024-01-02:
# - Nakon raznih pokušaja s sliding_window_moving_average vraćen median filter
#
# 2024-01-08:
# - Za ultrasonic senzor primijenjen cijeli niz filtera koji napokon smiruju priču
#
# 2024-01-09:
# - Isti set filtera upotrebljen za temperaturu
#
substitutions:
devname: usdist01
globals:
- id: api_was_connected
type: int
restore_value: no
initial_value: '0'
- id: reboot_counter
type: int
restore_value: no
initial_value: '0'
- id: display_backlight
type: int
restore_value: no
initial_value: '1'
- id: display_ln2_mode
type: int
restore_value: no
initial_value: '0'
wifi:
networks:
- ssid: "IShome08"
password: !secret wifi_password
- ssid: "IShome04"
password: !secret wifi_password
- ssid: "IShome06"
password: !secret wifi_password
- ssid: "IShome07"
password: !secret wifi_password
- ssid: "IShome05"
password: !secret wifi_password
domain: !secret domain
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: ${devname}
password: !secret ap_password
captive_portal:
# Do not enable logging
logger:
#level: DEBUG
level: INFO
baud_rate: 0
ota:
password: !secret ota_password
esphome:
name: $devname
platform: ESP8266
board: d1_mini
on_boot:
priority: -110
then:
- script.execute: display_off
- wait_until:
api.connected:
- lambda: |-
id(api_was_connected) = 1;
- sensor.template.publish:
id: "${devname}_display_ln2_mode"
state: !lambda 'return id(display_ln2_mode);'
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "none";'
- script.execute: display_on
- delay: 1000ms
- homeassistant.service:
service: script.usdist01_startup_script
data: {}
api:
password: !secret api_password
services:
- service: backlight_on
then:
- script.execute: display_on
- service: backlight_off
then:
- script.execute: display_off
- service: update_display
then:
- component.update: lcd_display
- service: display_ln2_next
then:
- lambda: |-
id(display_ln2_mode)++;
if (id(display_ln2_mode) > 1) {
id(display_ln2_mode) = 0;
}
- sensor.template.publish:
id: "${devname}_display_ln2_mode"
state: !lambda 'return id(display_ln2_mode);'
dallas:
- pin: D7
update_interval: 2s
sensor:
- platform: uptime
name: "${devname} uptime"
id: "${devname}_uptime"
- platform: wifi_signal
name: "${devname} WiFi Signal"
id: "${devname}_wifi_signal"
update_interval: 60s
- platform: ultrasonic
trigger_pin: D5
echo_pin: D6
name: "${devname} Distance"
id: "${devname}_distance"
device_class: distance
icon: mdi:arrow-expand-down
unit_of_measurement: m
accuracy_decimals: 6
update_interval: 3s
#pulse_time: 60us
pulse_time: 80us
#pulse_time: 100us
timeout: 1.8m
on_raw_value:
then:
- sensor.template.publish:
id: "${devname}_raw_distance"
state: !lambda 'return x;'
filters:
- skip_initial: 3
- filter_out: NaN
- median:
window_size: 9
send_every: 4
send_first_at: 3
- quantile:
window_size: 7
send_every: 4
send_first_at: 3
quantile: .9
- sliding_window_moving_average:
window_size: 7
send_every: 4
send_first_at: 3
#- delta: 0.005
- delta: 0.002
- platform: template
name: "${devname} Raw distance"
id: "${devname}_raw_distance"
unit_of_measurement: m
device_class: distance
accuracy_decimals: 6
icon: mdi:arrow-expand-down
- platform: template
name: "${devname} Display ln2 mode"
id: "${devname}_display_ln2_mode"
- platform: dallas
#index: 0
address: 0x8b000000643cf428
id: "${devname}_tank_temperature"
name: "${devname} Tank Temperature"
resolution: 12
force_update: false
filters:
- skip_initial: 3
- filter_out: NaN
- filter_out: 85.0
- filter_out: -127.0
- median:
window_size: 9
send_every: 4
send_first_at: 3
- quantile:
window_size: 7
send_every: 4
send_first_at: 3
quantile: .9
- sliding_window_moving_average:
window_size: 7
send_every: 4
send_first_at: 3
- delta: 0.1
text_sensor:
- platform: homeassistant
name: "${devname} Display L1"
entity_id: input_text.heat_fuel_display_l1
id: "${devname}_display_l1"
- platform: homeassistant
name: "${devname} Display L2"
entity_id: input_text.heat_fuel_display_l2
id: "${devname}_display_l2"
# Expose ESPHome version as sensor.
- platform: version
name: $devname ESPHome Version
# Expose WiFi information as sensors.
- platform: wifi_info
ip_address:
name: $devname IP
ssid:
name: $devname SSID
bssid:
name: $devname BSSID
- platform: template
name: "${devname} button action"
id: "${devname}_button_action"
icon: "mdi:gesture-tap"
binary_sensor:
- platform: status
name: "Statussensor"
id: statussensor
- platform: gpio
pin:
number: D3
mode:
input: true
pullup: true
name: "${devname} button"
id: "${devname}_button"
filters:
- invert:
- delayed_on: 30ms
- delayed_off: 30ms
on_multi_click:
- timing:
- ON for 40ms to 400ms
- OFF for at least 330ms
then:
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "single";'
- delay: 10ms
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "none";'
- timing:
- ON for 40ms to 400ms
- OFF for 40ms to 300ms
- ON for 40ms to 400ms
- OFF for at least 330ms
then:
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "double";'
- delay: 10ms
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "none";'
- timing:
- ON for 40ms to 400ms
- OFF for 40ms to 300ms
- ON for 40ms to 400ms
- OFF for 40ms to 300ms
- ON for 40ms to 400ms
- OFF for at least 50ms
then:
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "triple";'
- delay: 10ms
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "none";'
- timing:
- ON for at least 2s
then:
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "hold";'
- delay: 10ms
- text_sensor.template.publish:
id: "${devname}_button_action"
state: !lambda 'return "none";'
# I want status LED too (red one)
# It will be on D4 pin of D1 mini
status_led:
pin:
number: D4
inverted: true
mode:
input: false
pullup: false
output: true
switch:
- platform: restart
name: "${devname} Restart"
id: rst_switch
- platform: template
name: "${devname} LCD Backlight"
id: "${devname}_lcd_backlight"
lambda: |-
if (id(display_backlight) > 0) {
return true;
} else {
return false;
}
turn_on_action:
- lambda: |-
id(display_ln2_mode) = 0;
- sensor.template.publish:
id: "${devname}_display_ln2_mode"
state: !lambda 'return id(display_ln2_mode);'
- script.execute: display_on
- component.update: lcd_display
turn_off_action:
- script.execute: display_off
script:
- id: display_on
mode: restart
then:
- lambda: |-
id(lcd_display).backlight();
id(display_backlight) = 1;
- id: display_off
mode: restart
then:
- lambda: |-
id(lcd_display).no_backlight();
id(display_backlight) = 0;
interval:
- interval: 20sec
then:
- if:
condition:
lambda: 'return id(api_was_connected) > 0;'
then:
- if:
condition:
not:
api.connected:
then:
- if:
condition:
lambda: 'return id(display_backlight) < 1;'
then:
- script.execute: display_on
- component.update: lcd_display
# Reboot after 20 cycles (20 * 20sec = 5min)
- if:
condition:
lambda: 'return id(reboot_counter) > 20;'
then:
- switch.turn_on: rst_switch
- lambda: |-
id(reboot_counter) = 0;
- lambda: |-
id(reboot_counter) += 1;
- if:
condition:
lambda: 'return id(display_backlight) < 1;'
then:
- script.execute: display_on
#-
else:
- lambda: |-
id(reboot_counter) = 0;
i2c:
sda: D2
scl: D1
frequency: 200kHz
display:
- platform: lcd_pcf8574
update_interval: 10s
id: lcd_display
dimensions: 16x2
address: 0x3f
lambda: |-
if (id(statussensor).state) {
if (id(display_backlight) > 0) {
it.printf(0,0," ");
it.printf(0,0,id(${devname}_display_l1).state.c_str());
it.printf(0,1," ");
it.printf(0,1,id(${devname}_display_l2).state.c_str());
}
} else {
if (id(api_was_connected) > 0){
it.printf(0,0," ");
it.printf(0,1," ");
it.printf(0,0,"Connection lost!");
it.printf(0,1,"Reconnecting....");
} else {
it.printf(0,0," ");
it.printf(0,1," ");
it.printf(0,0,"Starting system");
it.printf(0,1,"and connecting!");
}
}
# EOF
Hope this helps.
Best regards,