Esp32 soil capcitive sensor issue

first and foremost i want you to know that I am new to the esp32 and to home assistant. After some research, I was able to get the esp32 to talk to home assistant but it is always reading 100% solid humidity whether the sensor is in water, soil, or air

CODE:


esphome:
name: bedroom-plant1-soil

esp32:
board: esp-wrover-kit
framework:
type: arduino

Enable logging

logger:

Enable Home Assistant API

api:

ota:
password: “898f6de17e55f992f3ad58331170cb16”

wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password

Enable fallback hotspot (captive portal) in case wifi connection fails

ap:
ssid: “Bedroom-Plant1-Soil”
password: “rCjTLkPlWPRL”

captive_portal:

i2c:
sensor:

  • platform: adc
    pin: A0
    name: “Soil Moisture”
    update_interval: 10s
    unit_of_measurement: “%”
    attenuation: 11db
    filters:

    • median:
      window_size: 7
      send_every: 4
      send_first_at: 1
    • calibrate_linear:
      • 1.25 → 100.00
      • 2.8 → 0.00
    • lambda: if (x < 1) return 0; else if (x > 100) return 100; else return (x);

    accuracy_decimals: 0


CODE

Please use 3 backticks when posting code.

In your diagram you connect the data pin to pin GPIO35, so change the pin in your code to:

sensor:
- platform: adc
  pin: GPIO35  
  name: “Soil Moisture”
  update_interval: 10s

So far as I know the A0 pin is only available on an ESP8266, see also the first lines in the documentation: Analog To Digital Sensor — ESPHome

Thanks for that. still not the right pin According to the specs on my board it is actually GPIO34

I updated the yaml file and now I am getting the polar opposite. it is giving me 0% even if it is straight water or mud

i2c:
sensor:

  • platform: adc
    pin: GPIO34
    name: “Soil Moisture”
    update_interval: 5s
    unit_of_measurement: “%”
    attenuation: 11db
    filters:

    • median:
      window_size: 7
      send_every: 4
      send_first_at: 1
    • calibrate_linear:
      • 1.25 → 100.00
      • 2.8 → 0.00
    • lambda: if (x < 1) return 0; else if (x > 100) return 100; else return (x);

    accuracy_decimals: 0

Ok, now you are using the right pin, it is time for some troubleshooting :grinning:

I don’t have such a moisture sensor myself, however I would start with removing all the filter, calibrate and lambda stuff. I would read the docs carefully (see link I posted before) and start with the suggested values for the different parameters. I would use a multimeter to measure the different (raw) values on the data pin and check what the sensor is reporting in ESPHome. If you read different values in different situations, you know for sure the moisture sensor is working and then the calibrate process can start, based on your sensor readings.

For me it looks like you cut&paste the current yaml together from different examples, that can work fine, but it gives you headache if your sensor is behaving different or needs other calibration or parameter values. Then you have to start from the basics. That costs some (or more) time however if it is finally working you have learned a lot and it gives you a very good feeling!

Why i2c if your sensorconnected directly to the ESP ?
My code here and its working.Sensor connected to ESP32

 - platform: adc
    pin: GPIO39
    
    name: Mulla niiskus
    id:  soil_moisture
    accuracy_decimals: 1
    update_interval: 1s
    icon: mdi:sprout
    unit_of_measurement: '%'
    filters:
      - lambda: |-
          if (x > 0.67) { 				// if over 0.7 volts, we are dry
            return 0;
          } else if (x < 0.28) { 			// if under 0.264 volts, we are fully saturated
            return 100;
          } else {
            return (0.67-x) / (0.67-0.28) * 100.0; 	// use a linear fit for any values in between
          }

I’m having the same issue. I’ve tried multiple pins and 2 efferent ESP32 WROOMs.

This is my yaml:

sensor:

  - platform: adc
    raw: true
    pin: GPIO34
    name: "Soil"
    update_interval: 10s

And this is the result, no matter where the probe is, it always reads 4095 from the pin:

[11:10:17][D][sensor:094]: 'Soil': Sending state 4095.00000 V with 2 decimals of accuracy
[11:10:27][D][sensor:094]: 'Soil': Sending state 4095.00000 V with 2 decimals of accuracy

When I use a multimeter I get readings from between 1.8v and 2.8v depending on moisture levels. I’ve used two different capacitive sensors, same readings.

Any ideas?

EDIT: It works fine using ESP8266, just seem to be a problem with ESP32. I bought a bunch of ESP32 for this project :see_no_evil:

Hello,
I have resistive soil moisture sensor but the connection is exactly the same. This is why I wanted to share with you my findings that sensors may work well with Tasmota firmware which can be uploaded into Nodemcu board, which in my opinion is the easiest one to setup.

I used below connection:
D7 to VCC
GRD to GRD
A0 to A0
To reduce power in the circuit (I read somewhere that this will increase life for resistive soil moisture sensor) I connected VCC from sensor to D7 pin. You can connect it directly to 3v3 pin in Nodemcu if you don’t need that. It will work well too but then you don’t need to use option Relay in Tasmota as in below screenshot:

Moreover in Tasmota console I changed settings to:
TelePeriod 20
which will increase the frequency of refreshing the results.

My automation looks like:

alias: YourAutomationName
description: ""
trigger:
  - platform: time_pattern
    minutes: /1
condition: []
action:
  - type: toggle
    device_id: YOUR_DEVICE_ID
    entity_id: YOUR_ENTITY_ID
    domain: switch
  - delay:
      hours: 0
      minutes: 0
      seconds: 12
      milliseconds: 0
  - if:
      - condition: and
        conditions:
          - condition: numeric_state
            entity_id: sensor.sensor_analog_a0
            below: 800
            above: 100
    then:
      - service: notify.mobile_app_oneplus
        data:
          message: Water!
    else: []
  - type: toggle
    device_id: YOUR_DEVICE_ID
    entity_id: YOUR_ENTITY_ID
    domain: switch
mode: single