Skip to content

Fluid / Flow · ESP32 DevKit (GPIO34 ADC1 example) guide

Interfacing Analog TDS Probe and Interface Board — DFRobot SEN0244-Style Reference with ESP32 DevKit (GPIO34 ADC1 example)

Estimate dissolved solids in water with a simple analog probe, then calibrate and temperature-compensate it for readings you can trust.

Updated October 29, 2026 Arduino C++ESP32 Arduino ADC (analogReadMilliVolts)Also forArduino Uno R3

What is the TDS Sensor (SEN0244 Reference)?

A TDS sensor gives you a quick estimate of how much dissolved material is in a sample of water. This page covers the DFRobot Gravity Analog TDS Sensor (SEN0244), a two-part kit made of a small interface board and a waterproof two-needle probe. It reports its reading as a plain analog voltage, so any Arduino, ESP32 or other board with an ADC can read it without a special library or bus.

TDS stands for total dissolved solids: the combined amount of salts and minerals dissolved in water, usually written in ppm (parts per million, the same as mg/L). The sensor does not measure those solids directly. It measures how well the water conducts electricity. Dissolved salts make water conduct better, so a conversion turns conductivity into an estimated ppm figure.

That makes it a good fit for watching trends: checking that a reverse-osmosis filter is still doing its job, keeping a hydroponic reservoir or aquarium stable, or logging how tap water changes through the year. It is a poor fit for anything that needs a certified number. Many boards sold online as "TDS meters" look similar to this one but use different circuits, output ranges and calibration constants, so every figure on this page refers to the SEN0244 reference kit. Check the markings and datasheet of your own module before relying on them.

How the sensor works

Pure water is a poor conductor. Salts and minerals dissolve into charged particles called ions, and the more ions there are, the more current flows between two electrodes placed in the water. The probe is exactly that: two metal needles a fixed distance apart. The interface board applies a small alternating signal to the needles (a steady DC signal would slowly corrode them), measures how easily it passes through the water, and turns the result into a voltage on the A pin.

Your code then does two things. It converts the ADC reading back into a voltage, and it converts that voltage into ppm. DFRobot's sample code uses a cubic curve fitted to readings from standard solutions, and the same constants are used in the sketch below. Because the curve was fitted to this kit, it will not suit a different module.

Conductivity is the physical quantity being measured, and "TDS" is a convention layered on top. DFRobot uses the rule TDS ≈ EC ÷ 2, so a solution of 1413 µS/cm shows as about 707 ppm. Other meters use a different divisor, so two instruments can disagree even when both are working properly. Always compare readings on the same scale.

What the numbers usually mean

Very pure water, such as reverse-osmosis output, reads close to zero. Ordinary tap water often falls somewhere in the low hundreds of ppm, depending on where you live. The kit stops at 1000 ppm, so check that your target range fits. Some hydroponic nutrient solutions run higher than that and will read at the top of the scale rather than at their true value.

Temperature compensation

Warm water conducts better than cold water, so the same water reads higher on a hot day. The effect is about 2% per °C around room temperature, which is large enough to matter: a 10 °C swing changes the reading by roughly a fifth.

The kit has no temperature sensor, and without one DFRobot's code assumes 25 °C. For stable readings, measure the water temperature with a waterproof DS18B20 and correct the voltage before converting it:

compensation = 1.0 + 0.02 × (temperature − 25)
corrected voltage = measured voltage ÷ compensation

Compensation only removes the temperature effect. It cannot fix a dirty probe, a wrong calibration or a poor connection.

Arduino Uno and Mega sketch

This sketch takes 30 samples, uses the median to ignore noise spikes, applies temperature compensation and prints the result. Set temperatureC from a DS18B20 in a real project; it is fixed at 25 °C here so the example runs on its own.

ESP32 changes

The ESP32 has a 12-bit ADC and a 3.3 V reference, but its raw readings are not perfectly linear, especially near the ends of the range. The simplest fix is to ask the Arduino core for a corrected value in millivolts instead of computing the voltage yourself. Use an ADC1 pin such as GPIO34, because ADC2 pins stop working while Wi-Fi is active. Replace the sampling and voltage lines in the sketch above with:

const int TDS_PIN = 34;

// inside readTdsPpm(): take the median of millivolt readings
readings[i] = analogReadMilliVolts(TDS_PIN);
float volts = medianOf(readings, SAMPLES) / 1000.0;

Power the module from 3V3 so its output can never exceed what the ESP32 pin tolerates. The rest of the sketch stays the same.

Calibration

The factory curve is a good starting point, but every probe and board pair differs slightly, and probes drift as deposits build up on the needles. Calibrating against a solution of known value fixes both problems.

DFRobot recommends a standard solution of 707 ppm, equal to 1413 µS/cm, measured at 25 °C. Calibration solutions are sold in small bottles, and a TDS pen can stand in if you do not have one. Note the temperature: the reference value is only correct at 25 °C, so either keep the solution at that temperature or compensate for it.

The procedure with the sketch above is:

If you use DFRobot's own GravityTDS library instead, calibration is done from the Serial Monitor: send enter to start, cal:707 with the probe in the 707 ppm solution, and exit to save the result. Either way, recalibrate occasionally if the probe is in constant use.

Using it well

  1. Calibrate first, then trust trends. A calibrated sensor is good for watching change. Treat any single number as an estimate.
  2. Keep the electronics dry. Mount the board above the water, route the probe cable so it cannot pull on the connector, and inspect the cable joint regularly.
  3. Stir, then wait. Let the reading settle before you record it, and do not measure while a pump is creating bubbles around the needles.
  4. Rinse between solutions. Carry-over from one liquid to the next is one of the biggest sources of error.
  5. Do not leave it powered and wired to noisy loads. Pumps and relays on the same supply add noise to a small analog signal.
  6. Record the temperature with every reading. It makes your logs far more useful later.

Frequently asked questions

Can I use it to test drinking water? No. It estimates dissolved solids only. It cannot detect bacteria, pesticides or most harmful contaminants, so use proper lab testing for safety decisions.

What is the difference between TDS and EC? EC (electrical conductivity) is the measured quantity, in µS/cm. TDS in ppm is calculated from it with a conversion factor. This kit uses TDS = EC ÷ 2.

Does it work in salt water? Not with the reference kit, which stops at 1000 ppm. Seawater is many times higher than that and would read at the top of the scale.

Why does the output only reach about 2.3 V? The board is designed that way. It keeps the signal within range of both 5 V and 3.3 V microcontrollers.

Can I leave the probe in the water all the time? Only the probe section is waterproof, and long-term immersion encourages deposits on the needles. If you do leave it in, inspect and clean it regularly and recalibrate.

Do I need a temperature sensor? Not for a rough reading, but yes if you want results to stay consistent as the water warms and cools.

Specifications

Input voltage
3.3 to 5.5 V DC
Output signal
Analog, 0 to 2.3 V
Working current
3 to 6 mA
TDS measurement range
0 to 1000 ppm
Accuracy
±10% of full scale at 25 °C (about ±100 ppm on the 0 to 1000 ppm range)
Module size
42 × 32 mm
Module connector
PH2.0-3P (3-pin Gravity cable)
Probe connector
XH2.54-2P
Probe
Two electrodes (needles), waterproof, 83 cm cable
Temperature sensing
None built in; add a separate waterproof sensor such as the DS18B20
Conversion rule
TDS ≈ electrical conductivity (EC) ÷ 2

Pinout

PinNameDescription
1- (GND)Power ground, 0 V
2+ (VCC)Power supply, 3.3 to 5.5 V
3AAnalog signal output, 0 to 2.3 V
4TDSProbe connector (XH2.54-2P) for the two-needle electrode
5LEDPower indicator

Swipe sideways to see every column →

Match the labels, not the colours. The 3-pin cable carries power on the outer pins and the signal on the third, but clone boards do not always follow the same order. Read the "-", "+" and "A" markings on your board before connecting it.

The output never reaches the supply voltage. The signal tops out around 2.3 V even on a 5 V supply, so it is safe for a 3.3 V ESP32 input. It also means the ADC sees only part of its range, which is why averaging several samples matters.

Only the probe goes in the water. The probe is the waterproof part. The board and the probe connector are not, so mount them above the waterline.

Wiring & code

Setting up TDS Sensor (SEN0244 Reference) with ESP32 DevKit (GPIO34 ADC1 example)

Library

ESP32 Arduino ADC (analogReadMilliVolts) by Arduino-ESP32 / SolderHub

Use an ESP32 board package in Arduino IDE; no additional library.

Wiring — ESP32 DevKit (GPIO34 example)

Module pinESP32 pinNotes
VCC3V3Use 3.3V for the reference kit; verify exact clone
GNDGNDCommon ground
A / analog outputGPIO34Classic ESP32-WROOM ADC1 example; keep signal within GPIO limits
TDS probeProbe socketKeep interface board and connector dry

Swipe sideways to see every column →

C++

Targets a classic ESP32-WROOM DevKit and GPIO34 (ADC1); verify the pinout for C3/S3 variants. Power the reference module from 3.3V and ensure the analog output is safe. Not physically bench-tested.

Keep learning

Related guides & projects