
家里养花最头疼的就是浇水这件事:浇多了烂根,浇少了叶子发黄,全凭手指头戳土那点感觉。这篇就带你用几块钱一个的土壤湿度传感器配上Arduino,把“该不该浇水”变成串口监视器里明明白白的提示。全程保姆级,只要会点亮LED就能跟上。
先认识这块传感器
常见的土壤湿度传感器有两部分:一块插进土里的叉形探头,和一小块带运算放大器的转接板。探头上是两根镀金属的叉齿,土壤里的水分含量不同,两齿之间的导电率就不同,读数也就跟着变。转接板上一般有四个引脚:VCC、GND、A0、D0。

A0输出的是随湿度连续变化的模拟电压,D0则是转接板上电位器比较出来的高低电平。想精细控制就用A0,想简单粗暴地“干了就响”可以直接用D0。转接板上还有一颗电源LED和一颗状态LED,调节板上的蓝色电位器可以改变D0的触发门槛,拧的时候LED会跟着亮灭变化,很好判断。
接线:只占三个脚
这次先玩模拟输出,一共三根线:VCC接Arduino的7号数字脚(后面解释为什么不用5V常供电),GND接地,A0接A0模拟输入。杜邦线直插直用,不存在接错方向的问题。

读出原始数值
有个小坑必须提醒:探头上只要通着电,就会一直发生电解腐蚀,用不了多久叉齿就烂了。所以官方做法是把VCC接到一个数字脚上,读数前才通电,读完立刻断电。下面的代码就是这个思路:
// Sensor pins
#define sensorPower 7
#define sensorPin A0
void setup() {
pinMode(sensorPower, OUTPUT);
// Initially keep the sensor OFF
digitalWrite(sensorPower, LOW);
Serial.begin(9600);
}
void loop() {
//get the reading from the function below and print it
Serial.print("Analog output: ");
Serial.println(readSensor());
delay(1000);
}
// This function returns the analog soil moisture measurement
int readSensor() {
digitalWrite(sensorPower, HIGH); // Turn the sensor ON
delay(300); // Allow power to settle
int val = analogRead(sensorPin); // Read the analog value form sensor
digitalWrite(sensorPower, LOW); // Turn the sensor OFF
return val; // Return analog moisture value
}烧录进去打开串口监视器(波特率9600),就能看到一秒一个的模拟读数。先把干燥的传感器插进土里记个数,再倒点水进去,观察读数往哪个方向跑。

校准:定出干湿两个门槛
这模块读数是反直觉的:数值越小说明越湿,越大说明越干。空气里读数大概在550到650之间,泡进一杯水里会掉到250到300,插在干燥土里则能飙到800以上。所以校准很简单:把探头插进浇透水的土里记下“湿值”,再等土彻底干透记下“干值”,中间取两个门槛写进代码:
/* Change these values based on your calibration values */
#define soilWet 500 // Define max value we consider soil 'wet'
#define soilDry 750 // Define min value we consider soil 'dry'
// Sensor pins
#define sensorPower 7
#define sensorPin A0
void setup() {
pinMode(sensorPower, OUTPUT);
// Initially keep the sensor OFF
digitalWrite(sensorPower, LOW);
Serial.begin(9600);
}
void loop() {
//get the reading from the function below and print it
int moisture = readSensor();
Serial.print("Analog Output: ");
Serial.println(moisture);
// Determine status of our soil
if (moisture < soilWet) {
Serial.println("Status: Soil is too wet");
} else if (moisture >= soilWet && moisture < soilDry) {
Serial.println("Status: Soil moisture is perfect");
} else {
Serial.println("Status: Soil is too dry - time to water!");
}
delay(1000); // Take a reading every second for testing
// Normally you should take reading perhaps once or twice a day
Serial.println();
}
// This function returns the analog soil moisture measurement
int readSensor() {
digitalWrite(sensorPower, HIGH); // Turn the sensor ON
delay(300); // Allow power to settle
int val = analogRead(sensorPin); // Read the analog value form sensor
digitalWrite(sensorPower, LOW); // Turn the sensor OFF
return val; // Return analog moisture value
}拿我的实测举例:湿土约480,干土约760,所以soilWet填500、soilDry填750刚好。你的土、你的传感器都不一样,务必以自己量出来的为准。跑起来之后串口会直接告诉你土是太湿、正好还是太干:

小提醒:校准的时候别用手捏着叉齿往土里怼,皮肤上的汗会影响读数,也容易把叉齿掰歪。要垂直插到盆栽一半深度左右才准。
校准这步别偷懒直接抄我的数值。同样一块传感器,插在黏土和插在椰糠里读数能差出一大截,浇透水的黏土可能才500出头,而椰糠能掉到300以下。正确的做法是:把探头插进盆里,浇一次透水,等底孔往外渗水了再记湿值;然后放着让它自然干到你平时觉得“该浇了”的干度,记干值。门槛取在这两个数之间稍微偏湿一点的位置,因为植物怕旱不怕短暂偏湿。要是你拿不准,让代码把每次读数都打出来,观察两三天再定门槛,比一次校准靠谱得多。
升级成自动浇花提醒
校准完,这个提醒系统其实已经成型了:把loop里的delay(1000)改成delay(21600000)(六小时测一次,实际项目里建议一天一到两次),把“too dry”那行换成蜂鸣器响一声或者点亮一颗红色LED,一个不用你操心的浇花提醒器就完成了。
提醒的方式看你想多吵。最简单的是一颗LED:土干了就亮,塞在花盆边上,路过瞄一眼就知道。想更醒目就上个无源蜂鸣器,串口提示too dry的同时响三短声。再讲究点,可以直接接一块ESP8266之类的WiFi板,干透了往手机推一条消息,人不在家也不怕。代码层面都只是在判断分支里加几行digitalWrite的事,先把基础版本跑稳再往上叠功能。
想更进一步,可以加个继电器直接带小水泵,土一干自动补水,连提醒都省了——不过继电器接水泵是另一个话题,改天单独写。如果你嫌模拟输出麻烦,还有更偷懒的玩法:用D0数字输出,接线换成D0接8号脚,电位器拧到“湿土时板载状态LED刚好灭”这个临界点,然后digitalRead一下就能判断干湿。代码更短:

// Sensor pins
#define sensorPower 7
#define sensorPin 8
void setup() {
pinMode(sensorPower, OUTPUT);
// Initially keep the sensor OFF
digitalWrite(sensorPower, LOW);
Serial.begin(9600);
}
void loop() {
//get the reading from the function below and print it
int val = readSensor();
Serial.print("Digital Output: ");
Serial.println(val);
// Determine status of our soil moisture situation
if (val) {
Serial.println("Status: Soil is too dry - time to water!");
} else {
Serial.println("Status: Soil moisture is perfect");
}
delay(1000); // Take a reading every second for testing
// Normally you shoul take reading perhaps every 12 hours
Serial.println();
}
// This function returns the analog soil moisture measurement
int readSensor() {
digitalWrite(sensorPower, HIGH); // Turn the sensor ON
delay(300); // Allow power to settle
int val = digitalRead(sensorPin); // Read the analog value form sensor
digitalWrite(sensorPower, LOW); // Turn the sensor OFF
return val; // Return analog moisture value
}代价是门槛只能靠拧电位器来定,没有模拟读数直观,适合做“低于某个湿度就报警”这种单一场景。两条路线按需选,模拟版信息量大,数字版接线简单。
顺带答几个新手常问的问题。读数一直不动或者一直是满值,八成是VCC没接对,或者探头没插到位,叉齿有一半露在空气里。读数飘忽不定,可能是刚浇完水土还没渗匀,等几分钟再看;也可能是杜邦线接触不良,换根线试试。叉齿发黑是电镀层被腐蚀的正常现象,只要叉齿还没断就不影响读数,黑得厉害了记得换个新的。还有人说插进土里读数和空气里一样,检查一下探头上那两个圆孔是不是被塑料袋之类的隔住了,探头必须和土壤紧密贴合才有读数。
最后说下摆放位置。别把探头怼在盆正中间贴着根须最密的地方,那里浇水后永远湿着,测出来的数偏乐观;也别贴盆边,土干得快,读数偏悲观。插在盆沿往里三分之一、深度到叉齿一半最合适。多肉这类耐旱植物可以适当把门槛调高,绿萝蕨类这类爱水的就调低,同一套代码换个门槛就能伺候不同脾气。
总结一下三步走:接线时VCC走数字脚做软开关,先烧原始读数代码记下自家湿土干土两个数,再把门槛填进判断代码。剩下的就是把它塞进花盆,接个小蜂鸣器,从此告别“想起来才浇水”的日子。装好之后欢迎在评论区汇报你家的读数区间,看看各家的土壤差别有多大。










教程写得挺细,那个delay(21600000)我一开始没反应过来是六小时,数了数零才明白哈哈。不过一天测两次会不会太频繁,电池供电的话是不是改成一天一次更好
已照做,我的问题是插进盆中间读数一直偏高,看到文末才知道不能怼在根须最密的地方,明天挪个位置重新校准
正好想给我家阳台上那盆绿萝搞个自动提醒,先收藏了。问下校准的时候湿值和干值差太少怎么办?我上次测一个才差50多
分享个翻车经历:我把探头一直接着5V挂在花盆里两个月,拔出来一看叉齿锈得不成样子,读数也没法用了。博主说的通电才读数这条真的是血的教训,大家千万别省这个步骤
请教一下,多肉用这个方案的话门槛一般设多少合适?我上次调完总觉得它明明干了还在喊perfect