Thanks a lot!! You saved the day!!
Now, I will install the A02YYUW in the water tank, let’s see if it works without problems of condensation.
Regards
Jordi
Thanks a lot!! You saved the day!!
Now, I will install the A02YYUW in the water tank, let’s see if it works without problems of condensation.
Regards
Jordi
Well, I had some troubles with the readings, highly random and with a lot of fluctuations. I still have to check thoroughly the cables and try again. I will chime in with news once I figure out what is going on. I guess that some of the soldering I did is defective, or maybe too long cables adding too much noise, go figure…
Two days and much frustration later:
Use Fileeditor
add file: /config/esphome/A02YYUW-Sensor.
#include "esphome.h"
class MyCustomSensor : public PollingComponent, public Sensor {
public:
MyCustomSensor() : PollingComponent(1000) {}
void setup() override {
// Configure the UART for communication with A02YYUW-Sensor
Serial.begin(9600);
pinMode(echo_pin_, INPUT);
pinMode(trigger_pin_, OUTPUT);
}
void update() override {
// Trigger the sensor to send a pulse
digitalWrite(trigger_pin_, LOW);
delayMicroseconds(2);
digitalWrite(trigger_pin_, HIGH);
delayMicroseconds(10);
digitalWrite(trigger_pin_, LOW);
// Read the pulse duration and calculate the distance
long duration = pulseIn(echo_pin_, HIGH);
float distance = (duration / 2) / 29.1;
// Publish the distance as a sensor reading
publish_state(distance);
}
private:
const uint8_t echo_pin_ = 16; // YOUR PIN HERE
const uint8_t trigger_pin_ = 17; // YOUR PIN HERE
};
And here the code snipped From EspHome-Device:
esphome:
name: water-sensor
friendly_name: Water-Sensor
includes:
- A02YYUW-Sensor.h
esp32:
board: node32s
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "YOUR KEY HERE"
ota:
password: "YOUR PW HERE"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Static IP
manual_ip:
static_ip: 192.168.178.100
gateway: 192.168.178.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Water-Sensor Fallback Hotspot"
password: "YOUR PW HERE"
sensor:
- platform: custom
lambda: |-
auto my_sensor = new MyCustomSensor();
App.register_component(my_sensor);
return {my_sensor};
sensors:
name: "Tank Water Level"
unit_of_measurement: "cm"
accuracy_decimals: 0
It´s not the final version, but its works!
Hope it helps and gives you a good starting point.
p.s.
Best regards
Hi guys,
I am playing with that same sensor (A02YYUW) in ESPhome, too. I am currently using @taraant custom component. As it is nicer code then the one I glued together.
But, I find annoying to poll the sensor every 100 ms as I need the info, let’s say every minute. And you can not make the update interval bigger, as the UART apparently have a buffer. So, if I change the polling interval, I get to read the data from buffer, but only 4 bytes at a time. AKA, I get the data from now, much later in a future.
Do anybody know, the proper approach to this? I was thinking about, serial.begin() in .h file. That might help to solve that issue. Or is there another “proper way” to do this?
Bonjour j’ai aussi un capteur A02YYUW avec carte wemos d1 et je arrive pas à avoir de valeurs dans home assistant avec esp home
Pouvez vous m’expliquer quel code yaml avez vous modifier avec file editor ?
Bonjour j’ai le même projet avec le capteur ultrason je ne comprend pas les codes ci dessus ou faut il les installer ? Config/esp home/?
Hi Fantomaz,
esphome:
name: water-sensor
friendly_name: Water-Sensor
includes:
- A02YYUW-Sensor.h
Thanks @Equilibrium for the custom component - however I am having some trouble with it, as it will only output a distance of 16cm. Is this still working for you?
[14:13:41][D][sensor:110]: 'Tank Water Level': Sending state 16.08247 cm with 0 decimals of accuracy
[14:13:42][D][sensor:110]: 'Tank Water Level': Sending state 16.04811 cm with 0 decimals of accuracy
[14:13:43][D][sensor:110]: 'Tank Water Level': Sending state 16.04811 cm with 0 decimals of accuracy
[14:13:44][D][sensor:110]: 'Tank Water Level': Sending state 16.08247 cm with 0 decimals of accuracy
[14:13:45][D][sensor:110]: 'Tank Water Level': Sending state 16.08247 cm with 0 decimals of accuracy
So i was finally able to get the A02YYUW sensor working with UART , here is the below code. Following above code i was also getting the same readings.
I am using the sensor with ESP32 so using the hardware serial at GPIO 16/17
below is the code for the A02YYUW.h file
#pragma once
#include "esphome.h"
class A02YYUWSensor : public esphome::Component, public esphome::sensor::Sensor {
public:
void setup() override;
void loop() override;
private:
HardwareSerial serial_ = HardwareSerial(2); // Use the second hardware serial port (GPIO16=RX, GPIO17=TX)
uint8_t buffer_[4] = {};
float distance_ = 0.0f;
};
void A02YYUWSensor::setup() {
// Set up the serial port for the UART communication
serial_.begin(9600, SERIAL_8N1, 16, 17); // baud rate, parity, RX pin, TX pin
}
void A02YYUWSensor::loop() {
// Read the UART data from the sensor
while (serial_.available()) {
if (buffer_[0] == 0xFF && serial_.readBytes(buffer_ + 1, 3) == 3) {
uint8_t sum = (buffer_[0] + buffer_[1] + buffer_[2]) & 0xFF;
if (sum == buffer_[3]) {
uint16_t distance_raw = (buffer_[1] << 8) | buffer_[2];
if (distance_raw > 30) {
distance_ = static_cast<float>(distance_raw) / 10.0f; // Convert to cm
} else {
distance_ = 0.0f; // Below the lower limit
}
break; // Successfully parsed a valid UART frame, exit the loop
}
} else {
buffer_[0] = serial_.read(); // Invalid header, discard and try again
}
}
// Update the sensor with the current distance value
publish_state(distance_);
// Your code for processing sensor data goes here
// ...
}
below is the code for the yaml file
esphome:
name: tank-level
platform: ESP32
board: esp32dev
includes:
- A02YYUW-Sensor.h
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
ota:
password: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
wifi:
ssid: "xxxxxxxxxxj"
password: "xxxxxxxxxxxx"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "xxxxxxxxxxxx"
password: "xxxxxxxxxxxxxxxxxx"
uart:
rx_pin: 16
tx_pin: 17
baud_rate: 9600
sensor:
- platform: custom
lambda: |-
auto a02yyuw_sensor = new A02YYUWSensor();
App.register_component(a02yyuw_sensor);
return {a02yyuw_sensor};
sensors:
- name: "Tank Level"
unit_of_measurement: cm
accuracy_decimals: 1
icon: mdi:gauge
just try this one and update if this holds good for you too.
Thank you for this, it works perfectly
Is there a way to reduce the interval it stores in ESPHOME please?
Would it be a case of header file to only publish every xx loop, instead of constantly?
I played with the sensor with some arduino code (not in ESPHOME) and it has a default sensing delay of 100mS. When i increased that , it didnt read properly so I am assuming, it must run/sample at that frequency to function correclty?
I am just consious about how often its battering ESPHOME with readings.
Thanks
Code from @vishwamittrabhardwaj worked but with no update interval it updated every 100ms so I’ve added PollingComponent into the code
#pragma once
#include "esphome.h"
class A02YYUWSensor : public PollingComponent, public Sensor {
public:
A02YYUWSensor() : PollingComponent(4000) {}
void setup() override;
void loop() override;
void update() override;
private:
HardwareSerial serial_ = HardwareSerial(2); // Use the second hardware serial port (GPIO16=RX, GPIO17=TX)
uint8_t buffer_[4] = {};
float distance_ = 0.0f;
};
void A02YYUWSensor::setup() {
// Set up the serial port for the UART communication
serial_.begin(9600, SERIAL_8N1, 44, 43); // baud rate, parity, RX pin, TX pin
}
void A02YYUWSensor::loop() {
// Read the UART data from the sensor
while (serial_.available()) {
if (buffer_[0] == 0xFF && serial_.readBytes(buffer_ + 1, 3) == 3) {
uint8_t sum = (buffer_[0] + buffer_[1] + buffer_[2]) & 0xFF;
if (sum == buffer_[3]) {
uint16_t distance_raw = (buffer_[1] << 8) | buffer_[2];
if (distance_raw > 30) {
distance_ = static_cast<float>(distance_raw) / 10.0f; // Convert to cm
} else {
distance_ = 0.0f; // Below the lower limit
}
break; // Successfully parsed a valid UART frame, exit the loop
}
} else {
buffer_[0] = serial_.read(); // Invalid header, discard and try again
}
}
}
void A02YYUWSensor::update() {
// Update the sensor with the current distance value
publish_state(distance_);
}
Sorry if there mistakes, first time understanding C++ code
I used Update and Loop at the same time.
Every 4000ms publish_state
is sent with the latest distance from loop.
If you just use Update then it’s the older distance that is in a queue
I also added Quantity and Percentage of water to use in a tank into the yaml file:
uart:
rx_pin: GPIO44
tx_pin: GPIO43
baud_rate: 9600
sensor:
- platform: custom
lambda: |-
auto a02yyuw_sensor = new A02YYUWSensor();
App.register_component(a02yyuw_sensor);
return {a02yyuw_sensor};
sensors:
- name: "Tank Level"
id: level_cm
unit_of_measurement: cm
accuracy_decimals: 1
icon: mdi:gauge
- platform: template
name: "Tank Quantity"
id: quantity_l
icon: "mdi:water"
unit_of_measurement: "l"
accuracy_decimals: 0
lambda: return ((((id(level_cm).state)-7)-89)/89)*-826;
# 7: Distance from sensor and full water
# 826: Numbers of liters of the tank
# 89: Max distance from top to bottom water
update_interval: 1s
filters:
- clamp:
min_value: 0
max_value: 826
- platform: template
name: "Tank Percentage"
id: percentage
icon: "mdi:water"
unit_of_measurement: "%"
accuracy_decimals: 0
lambda: return ((((id(level_cm).state)-7)-89)/89)*-100;
update_interval: 1s
filters:
- clamp:
min_value: 0
max_value: 100
text_sensor:
- platform: template
name: "Tank"
icon: "mdi:gauge-full"
lambda: |-
if (id(percentage).state >= 100) {
return {"Full"};
}
else if (id(level_cm).state >= 89) {
return {"Empty"};
}
else {
return {"Filling"};
}
update_interval: 1s
You need to change the RX and TX pin, mine are from an ESP32-S3
I’m trying to get the A02YYUW sensor working on a Wemos D1 mini but I’m not successful. Tried every suggestion in this topic, nothing works for me.
The docs are not very helpful either. Any help would be greatly appreciated.
never mind, I got it to work.
I dont get it to work either? How did you do it?
I’m not using it any more, but this is the code I used in my yaml file:
(I had it connected to a D1 mini)
uart:
rx_pin: D4
baud_rate: 9600
sensor:
- platform: a02yyuw
id: a02yyuw_sensor
name: "Water level"
unit_of_measurement: 'm'
accuracy_decimals: 1
filters:
- multiply: 0.001
- throttle: 5s
- heartbeat: 5s
- quantile:
window_size: 7
send_every: 4
send_first_at: 3
quantile: .9
- debounce: 0.1s
Hello!
i get this?
Failed config
sensor.a02yyuw: [source /config/esphome/avstand.yaml:41]
Platform not found: ‘sensor.a02yyuw’.
platform: a02yyuw
id: a02yyuw_sensor
name: Water level
unit_of_measurement: m
accuracy_decimals: 1
filters:
- multiply: 0.001
- throttle: 5s
- heartbeat: 5s
- quantile:
window_size: 7
send_every: 4
send_first_at: 3
quantile: 0.9
- debounce: 0.1s
What do i have to add?
i got it working!! I hade the RX TX shifted…
Thank you! Fore your answer…
/Micke