Aquarium water quality TDS sensor

Hello Forum,

please help me, I have problems with the following:
I anstalled a tds sensor to an esp32 board analog pin and see, that the ppm value isn’t correct shown and see that the value of the sensor isn’t 0 if the sensor is not attached to the board. Can anyone help me to fix the issue?

My esp configuration is:

sensor:
  - platform: adc
    pin: GPIO39
    name: "Aquarium tds"
    update_interval: 10s
    unit_of_measurement: "ppm"
    icon: "mdi:water-percent"
    filters:
       - lambda: return ((133.42*x*x*x - 255.86*x*x + 857.39*x)*0.5)*3.3;

Hardware:
Raspberry pi4 - 4 gb
ESP32 Wemos controller
Analog TDS Sensor - Water Conductivity Analog Tds Sensor Module Tester Waterproof Probe Liquid Detection Water Quality Monitoring For Arduino 3.3v - Sensors - AliExpress

Software:

  • Home Assistant OS
  • ESPHome
1 Like

You need to add temperature compensation.

https://wiki.dfrobot.com/Gravity__Analog_TDS_Sensor___Meter_For_Arduino_SKU__SEN0244#target_3

### TDS 01
# Raw TDS Reading
  - platform: ads1115
    multiplexer: 'A0_GND'
    gain: 6.144
    name: "TDS 01 Raw"
    ads1115_id: ads1
    id: tds01_raw
    update_interval: 10s
    unit_of_measurement: "v"
    accuracy_decimals: 3
    internal: true

# Temperature Compensated Voltage
  - platform: template
    name: "TDS 01 TCV"
    id: temp01_comp_v
    unit_of_measurement: 'v'
    accuracy_decimals: 3
    lambda: 'return ((id(tds01_raw).state) / (1 + (0.02 * ((id(probe01).state) - 25.0))));'
    update_interval: 10s
    internal: true

# Temperature Compensated TDS
  - platform: template
    name: "55G TDS 01"
    id: tds01_55g
    icon: "hass:water-opacity"
    unit_of_measurement: 'PPM'
    accuracy_decimals: 0    
    lambda: return (133.42*(id(temp01_comp_v).state)*(id(temp01_comp_v).state)*(id(temp01_comp_v).state) - 255.86*(id(temp01_comp_v).state)*(id(temp01_comp_v).state) + 857.39*(id(temp01_comp_v).state))*0.5;

# Temperature In °C
  - platform: dallas
    address: 0x6f01205fd42aa428
    name: "Probe 01"
    id: probe01
    unit_of_measurement: "°C"
    internal: true

# Temperature In °F
  - platform: template
    name: "55G TEMP 01"
    id: temp01_55g
    lambda: |-
      return id(probe01).state * (9.0/5.0) + 32.0;
    unit_of_measurement: "°F"

image

I become an error massage, that I need to configure I2c also.

Sorry, you don’t need to use my fist sensor, just use yours.

I am using a multiplexer because I have 4 TDS sensors.

What would I use as the RAW sensor if I’m not using analog to I2C? Where’s the gain parameter coming from?

this work well with me

esphome:
  name: wemosts1

esp8266:
  board: d1_mini_lite

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: 

ota:
  password: 

wifi:
  ssid: 
  password: 

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: 
    password: 

captive_portal:
dallas:
  - pin: GPIO14
# Raw TDS Reading
sensor:
  - platform: adc
    pin: GPIO17
    name: "TDS 01 Raw"
    id: tds01_raw
    update_interval: 10s
    unit_of_measurement: "v"
    accuracy_decimals: 3
    internal: true
    filters:
      - multiply: 3.3

# Temperature In °C

  - platform: dallas
    address: 0x04000000151e0c28
    name: "Probe 01"
    id: probe01
    accuracy_decimals: 0
    unit_of_measurement: "°C"

    
# Temperature Compensated Voltage
  - platform: template
    name: "TDS 01 TCV"
    id: temp01_comp_v
    unit_of_measurement: 'v'
    accuracy_decimals: 3
    lambda: 'return ((id(tds01_raw).state) / (1 + (0.02 * ((id(probe01).state) - 25.0))));'
    update_interval: 10s
    internal: true

# Temperature Compensated TDS
  - platform: template
    name: "TDS-01"
    id: tds01_55g
    icon: "hass:water-opacity"
    unit_of_measurement: 'PPM'
    accuracy_decimals: 0    
    lambda: return (133.42*(id(temp01_comp_v).state)*(id(temp01_comp_v).state)*(id(temp01_comp_v).state) - 255.86*(id(temp01_comp_v).state)*(id(temp01_comp_v).state) + 857.39*(id(temp01_comp_v).state))*0.5;

i use wemos d1 mini lite, Wemos D1 mini include external voltage divider circuitry to scale down a 3.3V input signal to the chip-internal 1.0V so i have to add a multiply filter to get correct values

 filters:
      - multiply: 3.3

This code does not work for me. I am getting about 350ppm on esphome and 850ppm when comparing with an actual TDS meter. Looking at the voltage provided by running the code/math in Arduino my voltage is around 2.1 but only 1.04 on the Esp32. If I apply the multiply by 3.3 filter then I am in the 2300ppm range. Any ideas?

EDIT:
Looks like attenuation is needed. The TDS sensor uses a range of 0-2.3 but the ESP32 is only capable of 0-1.1V.

EDIT: I added “attenuation: 6db” to the “TDS 01 TCV” template’s paramaters and it seems to be reading pretty accurately across the scale. Yay!

Hi, Did you get this working? Mine works, but is reading way low. My TDS meter reads ~417 when my handheld reads ~935. Based on the water in my aeroponic tub I believe the handheld is probably pretty close to accurate.

Where do you add the attentuation parameters in the ESPHome code? I’m assuming you add “attenuation: 2.5db” (or 6 or 11db) to temperature compensated TDS, or maybe the TDS Raw reading?

I guess I’ll play around with it, but I’ve got plants going at the moment and some automations using the ESP32 I’m trying to make this work on, so I don’t want to be resetting it constantly if I can help it.

How is everyone getting on with this?
I’m using a AZ-Delivery esp32 board and although the sensor is changing when either in or out of the water it seems that too high

I’m using GPIO32 and connected to ground and 5v from the esp

Probe 01 27 °C
TDS-01 1,288 PPM (In Water)

Probe 01 27 °C
TDS-01 134 PPM (Out of the water)

This is my raw output when the Phobe is in the water

[08:01:47][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.54412 v with 3 decimals of accuracy
[08:01:48][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.57070 v with 3 decimals of accuracy
[08:01:57][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.48978 v with 3 decimals of accuracy
[08:01:58][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.54100 v with 3 decimals of accuracy
[08:02:07][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.46102 v with 3 decimals of accuracy
[08:02:08][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.54100 v with 3 decimals of accuracy
[08:02:13][D][sensor:125]: ‘TDS-01’: Sending state 1274.54382 PPM with 0 decimals of accuracy
[08:02:17][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.46102 v with 3 decimals of accuracy
[08:02:18][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.55090 v with 3 decimals of accuracy
[08:02:25][D][dallas.sensor:144]: ‘Probe 01’: Got Temperature=26.6°C
[08:02:25][D][sensor:125]: ‘Probe 01’: Sending state 26.62500 °C with 0 decimals of accuracy
[08:02:27][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.47061 v with 3 decimals of accuracy
[08:02:28][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.53110 v with 3 decimals of accuracy
[08:02:37][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.45143 v with 3 decimals of accuracy
[08:02:38][D][api:102]: Accepted ::FFFF:C0A8:F64
[08:02:38][D][api.connection:861]: Home Assistant 2022.8.3 (::FFFF:C0A8:F64): Connected successfully
[08:02:38][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.61360 v with 3 decimals of accuracy
[08:02:47][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.53133 v with 3 decimals of accuracy
[08:02:48][D][sensor:125]: ‘TDS 01 Raw’: Sending state 2.54100 v with 3 decimals of accuracy
[08:02:57][D][sensor:125]: ‘TDS 01 TCV’: Sending state 2.46102 v with 3 decimals of accuracy

dallas:
  - pin: GPIO22
# Raw TDS Reading
sensor:
  - platform: adc
    pin: GPIO32
    name: "TDS 01 Raw"
    attenuation: 6db
    id: tds01_raw
    update_interval: 10s
    unit_of_measurement: "v"
    accuracy_decimals: 3
    internal: true
    filters:
      - multiply: 3.3

# Temperature In °C

  - platform: dallas
    address: 0x010321318b448428
    name: "Probe 01"
    id: probe01
    accuracy_decimals: 0
    unit_of_measurement: "°C"

    
# Temperature Compensated Voltage
  - platform: template
    name: "TDS 01 TCV"
    id: temp01_comp_v
    unit_of_measurement: 'v'
    accuracy_decimals: 3
    lambda: 'return ((id(tds01_raw).state) / (1 + (0.02 * ((id(probe01).state) - 25.0))));'
    update_interval: 10s
    internal: true

# Temperature Compensated TDS
  - platform: template
    name: "TDS-01"
    id: tds01_55g
    icon: "hass:water-opacity"
    unit_of_measurement: 'PPM'
    accuracy_decimals: 0    
    lambda: return (133.42*(id(temp01_comp_v).state)*(id(temp01_comp_v).state)*(id(temp01_comp_v).state) - 255.86*(id(temp01_comp_v).state)*(id(temp01_comp_v).state) + 857.39*(id(temp01_comp_v).state))*0.5;

I will write you my working config today afternoon.

That would be smashing, Thank you.
I think it’s almost there just seems that the reading are high, having a similar issue with a Gravity Analog Ph Sensor.

switch:
  - platform: gpio
    pin: 25
    name: "Aquarium CO2"
    inverted: true
  - platform: gpio
    pin: 32
    name: "Aquarium heater"

    
light:
  - platform: monochromatic
    name: "Aquarium LED"
    output: gpio_02
output:
  - platform: ledc
    pin: GPIO02
    id: gpio_02
#    min_power: 0.3
    max_power: 0.6
#    zero_means_zero: true


dallas:
  - pin: GPIO23

  
sensor:
  - platform: dallas
    address: 0xb7000006c34eb728
    name: "Aquarium Temperature"
    id: aquarium_temperature
#	  icon: "mdi:water-percent"
#	  unit_of_measurement: "°C"
#	  device_class: "temperature"
#    state_class: "measurement"
    filters:
      - offset: -2.0
      
  - platform: adc
    pin: GPIO34
    name: "Aquarium tds raw voltage"
    id: tds_raw_v
    update_interval: 120s
    unit_of_measurement: "V"
    icon: "mdi:water-percent"
    internal: true

# Temperature Compensated Voltage  
  - platform: template
    name: "TDS TCV"
    id: tds_tcv
    unit_of_measurement: 'v'
    accuracy_decimals: 3
    lambda: 'return ((id(tds_raw_v).state) / (1 + (0.02 * ((id(aquarium_temperature).state) - 25.0))));'
    update_interval: 120s
    internal: true
  
# Temperature Compensated TDS
  - platform: template
    name: "Aquarium TDS"
    id: aquarium_tds
    icon: "hass:water-opacity"
    unit_of_measurement: 'PPM'
    accuracy_decimals: 0    
    update_interval: 120s
    lambda: return (133.42*(id(tds_tcv).state)*(id(tds_tcv).state)*(id(tds_tcv).state) - 255.86*(id(tds_tcv).state)*(id(tds_tcv).state) + 857.39*(id(tds_tcv).state))*0.5;

So with the sensor in or out of cup of water, I’m getting the follwoing

14:34:37][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy
[14:34:42][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy
[14:34:47][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy
[14:34:52][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy
[14:34:57][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy
[14:35:02][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy
[14:35:07][D][sensor:125]: ‘TDS TCV’: Sending state 0.07051 v with 3 decimals of accuracy

and what ppm do you receive for this value?

This was because I hadn’t wired it in correctly. (Sometimes it’s best to walk away and come back to it later :slight_smile: )

This done the trick for me, Thank you for this.

Do you have the PH sensor and TDS in the same system? If you do and aren’t using an isolator then your readings will definitely be skewed, at least on the PH side. This is an issue that I am dealing with now. Trying to figure out how to control transistors to turn the TDS sensor on and off.

Just a quick word of warning, I used one of those tds sensors from ali that output a linear voltage that can be correlated to tds. The issue was in the aquarium, after x amount of days I’d get 0 tds. Turns out that the biofilm was isolating the two prongs on the sensor. A quick scrub between my fingers and good to go.

Do you monitor pH, temp, etc? I’d love to build some monitoring for my son’s aquarium if you can steer me in the right direction. Thanks.

Yes, just Temp and TDS ATM with Esphome, the pH Sensor didn’t work out, I plan to attempt it again soon.

1 Like