Inconsistent values with ADC sensor platform

I’m using ESPhome to monitor the TDS level of my Reverse Osmosis (RO) water system. It generally works pretty well, but for random periods of time, sometimes 1 hour and sometimes 12 hours, the data spikes.

The lower line is around 12 TDS, I’ve used a separate TDS tester to determine that is accurate. The spikes range from 45-55 TDS and have a lot of variability. There isn’t any rhyme or reason to it. The spikes happen both when we are at home using the water and when we are out of town and only our ice maker might be drawing small amounts.

Is there any way to stop the spikes?

I’m using this sensor connected to the Wemos D1 Mini board - Amazon.com: KEYESTUDIO TDS Meter Probe Water Quality Monitoring V1 Sensor Module with XH2.54-3Pin Jumper Wire Connector for Arduino : Electronics

Here is my code.

esphome:
  name: reverse-osmosis-tds-sensor
  friendly_name: Reverse Osmosis TDS Sensor

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: "Phillips_IoT"
  password: "xxxxxxxx"
  #Static IP
  manual_ip:
    static_ip: 192.168.1.227
    gateway: 192.168.1.1
    subnet: 255.255.255.0
  #Turn Off Power Save Mode
  power_save_mode: none
  fast_connect: on

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Reverse-Osmosis-Tds-Sensor"
    password: "xxxxxxxxxxxxx"

captive_portal:
    

sensor:
  - platform: adc
    pin: A0
    name: "Water TDS"
    update_interval: 120s
    unit_of_measurement: "ppm"
    accuracy_decimals: 1
    filters:
      - calibrate_linear:
          - 0.01758 -> 16
          - 0.22266 -> 247

I had a look through the reviews, there are a lot of bad ones. This one caught my eye:

I originally connected these sensors to the analog-to-digital (ADC) on an ESP32 microcontroller, testing it in both the Arduino IDE and ESPHome. The voltage was all over the place and produced garbage readings. I ended up using instead an ADS1115 (16-Bit, 4 channel ADC) and connected it to the ESP32 via the I2C interface. This eliminated most of the problems of repeatability and I was finally getting consistent readings. HOWEVER, there was still a lot of variation in readings from one probe to the next. I had to individually calibrate each sensor to correct this.

With some smart filtering, yes.

But if I was you I would experiment little bit more.
Your sensor gives 0-2.3V for 0-1000ppm. If it’s linear 12ppm would be 0.027V. Can Esp read it or is your 12ppm output actually zero?
What you get if you place the sensor in glass of distilled water? Does it jump periodically even there?
Analog sensors are sensible for interferences. How is your wiring?

No amount of filtering is going to remove this:

With lambda you can filter out for example values between 40-60.
But that’s not what I meant. May be it’s that “floor” that has to be filtered out.

Which would leave an 18 hour gap in the data.

Better to fix the sensor.

You could output the previous value for cosmetic reasons.

Totally agree!

Anyway, maybe that 12ppm is actually zero with some temp compensation or whatever on conversion formula.
If one used Esp32 to read linear sensor 0-2.3V / 0-1000ppm, the lowest readable value would be above 50ppm. Esp8266 ADC is better though.

Holding the previous value for 18 hours would way too misleading.

Err, what?

ESP32 has a 12 bit ADC and has a variable attenuator.

ESP8266 is 10 bit no attenuator.

They both suffer major non-linearity at the range extremes.

ESP32 quantisation error for 1000ppm = 1000 / 2^12 → 0.24ppm

ESP8266 quantisation error for 1000ppm = 1000 / 2^10 → ~ 1ppm.

(assuming sensor output 0-2.3v scaled to 0-1V with voltage divider for the ESP8266 and 11dB attenuation used for the ESP32 → 2.45V max).

I was only referring that. Esp8266 might read little better ~100mV zone I was writing about.

Not addressing the root cause, but does a reboot help?

If you were confident the spikes were outside of your feasible range you could automate a reboot.

Also could it be power supply related?

is that because

  1. the ADC is reading incorrectly
  2. the sensor is outputting incorrectly
  3. the node is sending the wrong value to HA
  4. HA is recording the value incorrectly

The solution is likely different for each of those cases. Given the data you have shown, and the reviews others have pointed out, I 1 is the real issue.

from the data sheet

Attenuation Measurable input voltage range
ADC_ATTEN_DB_0 100 mV ~ 950 mV
ADC_ATTEN_DB_2_5 100 mV ~ 1250 mV
ADC_ATTEN_DB_6 150 mV ~ 1750 mV
ADC_ATTEN_DB_11 150 mV ~ 2450 mV

You are interested in data that is well outside the measurable range for most attenuation levels.

There are ways to make it work, but it is probably easier to get a better ADC.

1 Like

Yeah this is the issue.

11dB covers the maximum 2.3V output easily, but…

if they expect to measure on the order of 12ppm normally that will be:

12ppm * 2.7V/1000ppm = 32mV

Which is very much in the non-linear region of the ADC.

37ppm generates 100mV which is where the ESP ADC actually starts working.

Solution: as per previous post use a more suitable external I2C ADC, or pick a sensor more suited to your measurement range.

Thanks for all the help. I’ll look for a different sensor