The sensor has labels on each pin. Its pretty self explanatory.
Those are great questions.
In the sample YAML, I am updating the sensor every 5 seconds. you should see - interval: 5s
under interval:
. You can change it to a value that suits you. For my case, I found setting it to 60s
to be good enough.
I did not think of a weather based integration. But now you say it, it seems to me that would add unnecessary point of failure and dependency on internet connectivity for the benefit we will get from it.
Also note the delays before and after the sensor update. These help sensor warm-up and reading time. For simple sensor as rain sensor that uses resistance, a short delay is fine. However, for other sensors, based on the manufacturer, you may need longer delays.
Regarding the wiring, I used the same as in the YAML file. Pins from left to right with the back of the board facing you.
VCC on sensor -> D7 on esp32
GND on sensor -> GND on sp32
A0 on sensor -> A0 on esp32
D0 on sensor -> D2 on esp32
PS: I updated the original code to add substitutions on top to control interval, warmup and cooldown.
Hello,
I am also trying to build a weather station and have the same rain sensor and a few other sensors (BMP280, DHT22) which I have already got working.
Unfortunately I am having problems with the rain sensor.
To solve the problem, I created a YAML that only contains the rain sensor with the code from “Shamasis”.
When uploading to my ESP32 (board: az-delivery-devkit-v4) I get the following error message
error: ‘GPIO33’ was not declared in this scope
GPIO pin 33 is assigned as pin_rs_digital.
I have already tried different GPIO pins.
If I comment out these lines
- lambda: |-
bool rain_state = !digitalRead(${pin_rs_digital});
id(rain_sensor).publish_state(rain_state);
the code can be installed on the ESP32
But, I don’t get any changes in the values when I apply a drop of water to the sensor
‘water_resistance’: Sending state 109.88889 V with 2 decimals of accuracy
‘Raindrop Coverage Sensor’: Sending state 0.00000 % with 1 decimals of accuracy
I would be happy if someone could help me, as I am a real beginner in the lambda functions.
Thank you very much
substitutions:
name: esp32-weatherstation
friendly_name: ESP32_WeatherStation
board: az-delivery-devkit-v4
pin_power: GPIO32
pin_rs_analog: GPIO36
pin_rs_digital: GPIO33
sensor_update_interval: 5s
sensor_warmup: 10ms
sensor_cooldown: 10ms
esphome:
name: ${name}
friendly_name: ${friendly_name}
name_add_mac_suffix: false
project:
name: esphome.web
version: '1.0'
esp32:
board: ${board}
framework:
type: arduino
version: 2.0.0
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "XXXX"
ota:
password: "XXXX"
globals:
- id: rain_state
type: bool
restore_value: no
initial_value: 'false'
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp32-Weatherstation"
password: "XXXX"
dashboard_import:
package_import_url: github://esphome/example-configs/esphome-web/esp8266.yaml@main
import_full_config: true
# --------------------------------------------------------------------------------------------
sensor:
- platform: adc
pin: ${pin_rs_analog}
id: water_resistance
internal: true
filters:
- calibrate_linear: # trim erroneous 5% edges
- 0.05 -> 0.0
- 0.95 -> 100.0
- platform: template
name: "Raindrop Coverage Sensor"
id: raindrop_coverage_sensor
accuracy_decimals: 1
unit_of_measurement: "%"
icon: "mdi:water-percent"
binary_sensor:
- platform: template
name: "Rain Sensor"
id: rain_sensor
device_class: moisture
icon: "mdi:umbrella"
# we read data every 5 seconds and update the sensors
interval:
- interval: ${sensor_update_interval}
then:
- output.turn_on: sensor_power
- delay: ${sensor_warmup}
- component.update: water_resistance
- sensor.template.publish:
id: raindrop_coverage_sensor
state: !lambda |-
return std::max(0.0, std::min(100.0, 100.0 - id(water_resistance).state));
#- lambda: |-
# bool rain_state = !digitalRead(${pin_rs_digital});
# id(rain_sensor).publish_state(rain_state);
- delay: ${sensor_cooldown}
- output.turn_off: sensor_power
# This Pin provides power to the sensor. We use one of the pins so that
# we can power on the sensor right before reading data and power back off.
# This reduces power consumption, but more importantly, being exposed to
# water, it reduces the side effects of sensor's physical corrosion.
output:
- platform: gpio
pin: ${pin_power}
id: sensor_power
Hi @Slein.
Does anything around the water sensor work? I mean, at a quick glance I could not spot any issue with your lambda. (I am not an expert either.) I was thinking of taking your code and flashing it to try. But before I do that, if you don’t mind, can you confirm if you have checked some of the basics with your setup?
- Can you log the value of digital read? Using something like. (Temporarily remove other lambdas to be more confident.)
- lambda: |-
int digital_value = digitalRead(${pin_rs_digital});
ESP_LOGD("main", "Digital Read Value: %d", digital_value);
-
I am not familiar with the variant of your board can you ensure that GPIO33 (used as
pin_rs_digital
) is a valid pin for digital read operations on your specific ESP32 board. GPIO33 should be usable, but it’s always good to confirm with the ESP32 pinout for theaz-delivery-devkit-v4
. -
Does the sensor work? Using a simple 3v3,GND,GPIO33GPIO36 connection and an
update_interval: 10s
on the sensor and logging it, do you see values?
Update: Also check with return std::max(0.0, std::min(100.0, 100.0 - id(water_resistance).state()));
. (called the .state()
function instead of .state prop)
I have set everything up according to these instructions, but apparently there are some problems with the configuration. There is also an issue about this on GitHub. Basically, the idea is great, but I think the code needs to be revised. I don’t understand the code completely, so I’m a bit helpless.
When flashing, you get the message that the attenuation of 11dB is outdated and you should use 12dB. In the ESPhome documentation it also says that the adc behaves differently since 2021.11. Does the code have to be adapted in this respect?
The status “rain” is only ever displayed briefly in Home Assistant and then “watching” is displayed. When it stops raining, “drying” is displayed. I have never seen “dry” displayed, for example.
I think ist is due to the following code:
Test for dry
# We assume sensor is dry when current resistance == max resistance
- if:
condition:
lambda: "return id(resistance_sensor).state == $max_resistance;"
then:
- script.execute: its_dry
- script.execute: end_measure
- script.wait: end_measure
If the max_resistance ist defined here:
Skip the value not in the range
min_resistance: “1000”
max_resistance: “500000”
but the
[D][sensor:094]: ‘Rain Detector resistance’: Sending state 42138.82031 Ω with 1 decimals of accuracy
the condition will never be true and therefore the status never changes to “dry”. But as i said i don’t understand the code completely. Maybe i’m completely wrong.
I think it would be great and certainly help many people if someone who understands the code could update it so that there is a good, working guide for a simple and cheap rain detector.
Ok… i think we need to clarify which rain sensor exactly you’re using. Got a model number? Link?, picture? Are you 100% sure its even analog? Does it have analog and digital pins? This is important details you need to always add or else how are we supposed to know if the problem is the code or the sensor?
I had the same problem with various pins I tried to my NodeMCU v.3 board.
Finally the solution was to declare only the pin number in quotes.
pin_rs_digital: '16' # instead D0 or GPIO16 on my board or
pin_rs_digital: '33' # instead GPIO33 as in your example