家里最有用的水质检测仪,是一支能从水龙头一路提到鱼缸边的。把 TDS 探头经它的测量板接上 Arduino Uno,把 ppm 读数显示在 0.96 寸 OLED 上,自来水、滤水器出水和鱼缸水,各花几秒钟就能比出高下。有一处小小的焊接是绕不开的 —— 我们会指给你看在哪里、为什么。
TDS 传感器测的到底是什么?
TDS(Total Dissolved Solids,总溶解固体)传感器不是一粒一粒地数杂质 —— 它测的是电流穿过水有多容易。溶解的盐分和矿物质在水里分解成离子,正是这些离子在 TDS 探头的两根电极之间搬运电流:离子越多,电导率越高,测量板再把电导率换算成以 ppm(毫克每升)计的溶解固体估算值。纯水几乎完全不导电。
也要明白它看不见什么。细菌、氯和大多数有机物几乎不改变电导率,所以读数低不是水可以放心喝的证明,读数高也不代表有毒 —— 矿泉水本来就特意带着几百 ppm 出售,RO 水则因为膜把离子挡在外面而读数接近零。这就是为什么单独一个数字意义有限,两个读数之间的差才是重点:自来水对比滤水器出水,用数字而不是猜测回答“我的滤水器还管用吗?”这个问题。
| 你看到的读数 | 它的意思 | 它不是这个意思 |
|---|---|---|
| RO 出水接近 0–50 ppm | RO 膜正把几乎所有溶解矿物质挡在外面 —— 滤水器在正常工作 | 不保证无菌;细菌在这块表上是隐形的 |
| 活性炭滤水器出水 ≈ 自来水 | 正常 —— 活性炭对付的是氯、味道和气味,不是溶解固体 | 不是你的活性炭滤芯坏了的证据 |
| 矿泉水几百 ppm | 矿物质本来就是卖点 —— 特意溶进去的 | 不代表那瓶水脏或有害 |
| 鱼缸 TDS 一周比一周高 | 固体在累积:残饵、排泄物,加上水蒸发时把矿物质留了下来 | 不能代替氨氮或 pH 测试 —— 它是该换水的信号 |
我们其他的水类教程测的是水位 —— 比如 JSN-SR04T 水塔监控器 —— 或者像自动浇花系统那样把水抽走。这是第一个给水本身标上数字的项目。
材料清单 —— TDS 探头、读它的 Uno,以及显示 ppm 的 OLED
Parts list
| Item | Price | Qty | |
|---|---|---|---|
Soldering Service for Circuit Boards & Electronics - 5 Pins Soldering ServiceSOLSE05 | RM0.80 |
TDS 板到手时 A0/T1/−/+ 四个焊盘是空的,盒子里也没有排针。加购这项 5 针焊接服务,我们帮你把 4 针排针焊到这些焊盘上 —— 请先在 WhatsApp 上告诉我们,让我们知道是给这块 TDS 板用的。
盒子里有什么 —— 哪一步焊接是必须的?
我们的 TDS Water Quality Sensor 模块到手是两个部分:印着 TDS BOARD V1.0 的蓝色测量板,和一支尾端带两根针状电极的白色圆柱探头,探头的黑色防水线以白色 JST-XH 插头收尾,插进板子左边缘的 2 针插座。它下方的 3 针 JST-XH 是输出插座 —— 但配套的线没有附送,所以我们走的是板子右边缘标着 A0、T1、− 和 + 的四个焊盘,每一个在丝印上都标得清清楚楚。
这四个焊盘出厂就是没有排针的空孔,盒子里也没有排针条 —— 所以焊接排在最前面。从 40 针公排针条上掰下 4 针一段,插进 A0/T1/−/+ 焊盘,从背面焊好;手法我们的排针焊接教程一步一步讲全了。不想碰烙铁?上面材料清单里那行可选项目替你搞定。

TDS 板为什么要用 AC「摇晃」探头?
板上的 CD4060BM 芯片是一个振荡器 —— 它用交变电压(AC)而不是 DC 驱动探头,而这正是这支探头不能用两根线直接接模拟引脚来读的原因。DC 电流流过水时会把离子拉向电极,在电极表面堆出一层带电的膜 —— 极化 —— 这层膜会越来越掐住电流,读数就一路往下漂个不停。AC 激励换向太快,这层膜根本来不及成形。旁边的 LMV324A 芯片再把探头信号转换回平滑的 DC 电压,让 A0 引脚能够读取。
它的工作参数:这块 TDS 板在 3.3–5.5 V 供电下运行,消耗 3–6 mA,输出 0–2.3 V 模拟电压,测量范围 0–1000 ppm,25 °C 下精度为满量程的 ±10%。电压由厂商的多项式换算成 ppm —— (133.42V³ − 255.86V² + 857.39V) × 0.5 —— 公式里的 V 应该是做过温度补偿的电压,因为离子在更暖的水里跑得更欢 —— 水的电导率每升高一摄氏度上升约 2%。T1 焊盘是温度探头的输入;我们让它空着,在代码里固定 25 °C,所以更冷的水会读得略低、更暖的水读得略高。对于比较类的用法 —— 自来水对滤水器、这周对上周 —— 只要在相近的温度下比较,这个局限几乎察觉不到。
TDS 板和 OLED 怎么接到 Uno?
刚焊好的那 4 针排针,加上 0.96 寸 OLED 出厂就装好的公排针,让整个接线变成纯粹的公对母杜邦线活 —— 连面包板都不用:母头插模块引脚,公头插 Uno 的母排座。如果你手上只有公对公杜邦线,一块面包板就能补上这个公母缺口。
| 模块引脚 | Uno 引脚 | 原因 |
|---|---|---|
| TDS + | 5V | 板子供电 —— 范围 3.3–5.5 V;5 V 正好对上 sketch 里的 VREF |
| TDS − | GND | POWER 排座上两个 GND 孔任选其一 |
| TDS A0 | A0 | sketch 读取的 0–2.3 V 模拟输出 |
| TDS T1 | — | 温度探头输入 —— 留空;补偿在代码里按 25 °C 处理 |
| OLED GND | GND | 这块模块的排针 GND 在前:GND VCC SCL SDA |
| OLED VCC | 3.3V | 这块 SSD1306 模块在 3.3–5 V 都跑得很顺 |
| OLED SCL | A5 | Uno 的 I2C 时钟(或 R3 数字排座末端的 SCL 孔) |
| OLED SDA | A4 | Uno 的 I2C 数据(或 SDA 孔) |
留意 OLED 的排针 GND 在前 —— GND VCC SCL SDA,和大多数模块 VCC 在前的习惯正好相反,照习惯接线正是烧掉它的经典方式。还有一条贯穿整个项目的安全规则:这里全是低压 DC,但水和电子元件终究不是朋友 —— 每次要在这套装置附近移水、加水或倒水,先把 USB 线拔掉。
这个 TDS 检测仪的 sketch 长什么样?
在 Library Manager 安装 Adafruit SSD1306,让 IDE 顺手把 Adafruit GFX 一起拉进来。代码里有一个值得弄懂的决定:原始读数用中位数过滤,而不是平均值。AC 激励和晃动的水面会在 ADC 读数里制造偶发的尖峰 —— 平均值会让一个尖峰拖歪整个读数,中位数则直接把它扔掉。
// 便携 TDS 检测仪:TDS Board V1.0 接 A0,SSD1306 OLED 挂 I2C 总线。
// ppm 读数大约每秒在屏幕上刷新一次。
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
const uint8_t PIN_TDS = A0; // TDS 板的 A0 焊盘 -> Uno 的 A0 引脚
const float VREF = 5.0; // 板子由 Uno 的 5V 引脚供电
const uint8_t N = 30; // 中位数缓冲区大小
int sampel[N]; // 原始 ADC 读数
uint8_t idx = 0;
// 水温假定固定为 25 摄氏度 —— T1 焊盘没有接线,
// 所以温度补偿在代码里按这个固定值进行。
const float SUHU_AIR = 25.0;
// 中位数滤掉板子 AC 激励带来的偶发尖峰,
// 比普通平均值好得多。
float median(int *d, uint8_t n) {
int t[N];
for (uint8_t i = 0; i < n; i++) t[i] = d[i];
for (uint8_t i = 0; i < n - 1; i++) // 简单插入排序
for (uint8_t j = i + 1; j < n; j++)
if (t[j] < t[i]) { int s = t[i]; t[i] = t[j]; t[j] = s; }
if (n & 1) return t[n / 2];
return (t[n / 2 - 1] + t[n / 2]) / 2.0;
}
void setup() {
Serial.begin(9600);
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // 这块模块应答 0x3C
Serial.println("SSD1306 not found at 0x3C - check wiring");
while (true) delay(100);
}
oled.setTextColor(SSD1306_WHITE);
for (uint8_t i = 0; i < N; i++) sampel[i] = analogRead(PIN_TDS);
}
void loop() {
static unsigned long tSampel = 0, tPapar = 0;
// 每 40 ms 取一个读数,放进环形缓冲区
if (millis() - tSampel >= 40) {
tSampel = millis();
sampel[idx] = analogRead(PIN_TDS);
idx = (idx + 1) % N;
}
// 每秒计算并显示一次
if (millis() - tPapar >= 1000) {
tPapar = millis();
float v = median(sampel, N) * VREF / 1024.0; // ADC -> 伏特
// 温度补偿:水的电导率每摄氏度上升约 2%。
// SUHU_AIR = 25.0 时这个系数 = 1.0(即不做修正)。
float pekali = 1.0 + 0.02 * (SUHU_AIR - 25.0);
float vKompensasi = v / pekali;
// 板子厂商给的电压 -> ppm 转换多项式
float ppm = (133.42 * vKompensasi * vKompensasi * vKompensasi
- 255.86 * vKompensasi * vKompensasi
+ 857.39 * vKompensasi) * 0.5;
if (ppm < 0) ppm = 0;
Serial.print("V=");
Serial.print(v, 3);
Serial.print(" TDS=");
Serial.print(ppm, 0);
Serial.println(" ppm");
oled.clearDisplay();
oled.setTextSize(1);
oled.setCursor(0, 0);
oled.print("TDS");
oled.setCursor(98, 0);
oled.print(v, 2);
oled.print("V");
oled.setTextSize(3); // 大号数字,隔远也看得清
oled.setCursor(10, 22);
oled.print(ppm, 0);
oled.setTextSize(1);
oled.setCursor(104, 36);
oled.print("ppm");
oled.display();
}
}
编译出来是 16,746 字节 —— Uno sketch 空间的一半。SUHU_AIR 那一行故意写成变量而不是埋进公式的数字:25 °C 时系数正好是 1.0,日后谁想在 T1 焊盘加温度探头,只要把这一个值换成真实读数就行。
ppm 读数在家里怎么用?
TDS 检测仪最有力的用法是比较,所以先立一条基准线:把探头尖端浸进一杯自来水,等数字稳住,记下来。然后第二杯接滤水器出水 —— 橱下 RO 应该比自来水断崖式下跌,屋外的活性炭滤水器则读得几乎一样,两种结果都正常,就像上面那张解读表说的。至于鱼缸,每周记一次的读数就是一条靠得住的趋势线:水蒸发时把矿物质留下,残饵不断累积,一条爬升的线就是该换掉部分水的早期信号。
浸测手法有三条简单规则。只浸探头尖端 —— 水位保持在带凹槽的护圈以下,线缆接头绝不入水。拿稳探头别晃,避开滤水器的气泡和水泵的水流,因为流动的水会摇乱读数。每测完一个样本,用清水冲洗探头并擦干,免得上一杯的盐分残留抬高下一杯的读数。

我们常见的错误
探头不经板子直接接模拟引脚。两根线插进水里确实会出读数 —— 一个在 DC 极化掐住电极表面电流时不停往下漂的读数。让读数稳定的正是板子的 AC 激励;没有板子的探头不是检测仪。
OLED 按习惯当成 VCC 在前来接。这块屏的排针是 GND VCC SCL SDA —— 地在最前。每次上电前先把丝印读一遍,因为供电接反可以直接送走这块模块。
整支探头连护圈一起沉进水里。需要入水的只有带电极的尖端。护圈和线缆接头始终留在水面以上 —— 它的防水设计是为浸测准备的,不是为整支泡水。
冰箱里的冷水拿来和室温自来水比。电导率每摄氏度上升约 2%,而代码把温度固定在 25 °C,跨温度比较会给出误导性的结论。先让冷的那杯回到室温再测。
把读数当成水质的最终判决。这块表是精度为满量程 ±10% 的业余估算工具 —— 意思是这个百分比按 1000 ppm 的量程顶端计算,不是按当前读数,所以任何读数的偏差都可能达到 ±100 ppm。这个偏差在同一支探头上大多是系统性的,这正是趋势和比较依然可靠的原因 —— 但它不是饮用水认证仪器。
常见问题
TDS 读数低是不是代表水可以放心喝?
不是。TDS 只通过电导率估算溶解固体 —— 细菌、病毒和氯几乎不改变它,所以受污染的水可以读得很低,优质矿泉水反而读得很高。用读数来监测滤水器和鱼缸趋势,不要当成安全判决。
为什么我的 TDS 读数不稳定?
常见原因:探头在晃、气泡粘在电极上,或者样本正好取在水泵或滤水器的水流里。把探头拿稳、放进静止的水里等几秒 —— sketch 里的中位数能滤掉偶发尖峰,但救不了一直翻腾的水。
这块表能用在海水缸吗?
不合适。海水在 35,000 ppm 上下,远远超出这块板 0–1000 ppm 的测量范围,读数会饱和、失去意义。淡水鱼缸、鱼池和家用滤水器则正好落在这个量程的正中央。
这个 TDS 传感器需要校准吗?
比较类的用法 —— 自来水对滤水器、这周对上周 —— 不需要:sketch 里厂商的多项式已经够用,而且满量程 ±10% 的精度对比较的两边一视同仁。只有当你需要能和其他仪表对得上的绝对数字时,用标准液校准才值得。
能让探头一直泡在鱼缸里吗?
不要。这支探头是为短暂浸测设计的:测完、拿出来、冲洗、擦干。长期浸泡会加速电极腐蚀,让读数随时间漂移 —— 而每周一次的读数就已经足够画出有用的鱼缸趋势了。

当水质变成你亲手记下的数字,它就不再是猜谜。焊好那四根针,浸下探头尖端,下次再有人问家里的滤水器还管不管用,你的答案是两个读数 —— 一个滤前,一个滤后。
最后更新:2026年8月。有问题?WhatsApp 联系我们。



TDS Water Quality Sensor Module Liquid Detection Meter Testing Equipment for Arduino DIY Projects
Arduino Uno Compatible SMD UNO R3 with Type B Cable - ATMEGA328P with CH340G-Microcontroller Project
0.96‘ OLED Display Module Blue White Screen I2C IIC Serial 128X64 LCD Display Board - 0.96' OLED WHITE
2.54mm Pin Header Female Male Single Row Header 40P Connector Black White Red Yellow Green Blue - 40P MALE HEADER (BLACK)
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-F 20CM
Soldering Service for Circuit Boards & Electronics - 5 Pins Soldering Service