💡 划重点
- 面向阳台园艺的 60 元内土壤湿度监测方案,主控用 ESP32-S3。
- 感知层读取土壤湿度、空气温湿度,控制层做阈值判断与滤波。
- 本地 OLED 实时显示,MQTT 上报远程查看,支持深度睡眠省电。
- 土壤湿度模拟量从建议的 GPIO34 微调至 GPIO4,原因是 ESP32-S3 的 ADC1 通道集中在 GPIO1—GPIO10,GPIO34 不适合模拟采集。
- 适合上班族、出差党、阳台种植新手,避免浇水过多或干死。
需求洞察
阳台盆栽和地栽不同,盆土体积小,水分蒸发快,夏季一天就可能从湿润变干燥。目标用户是城市阳台园艺爱好者、经常加班或出差的上班族,以及刚入门的种植新手。真实痛点是:凭感觉浇水不可靠,传统指针湿度计要蹲下看,出差几天回来植物已经萎蔫;浇水过多还会烂根,尤其多肉、香草、番茄苗对湿度敏感。为什么值得做?ESP32-S3 自带 Wi-Fi,成本低,配合土壤湿度传感器和 OLED 就能把“看不见的湿度”变成数字和远程消息。它既能提醒浇水,也能为后续自动滴灌留出控制接口。60 元内即可完成,门槛低,重复可复制。
方案设计
感知层:电容式土壤湿度传感器插入盆土,输出模拟电压;DHT22 采集空气温湿度,辅助判断蒸发速度。控制层:ESP32-S3 读取 ADC 值,做滑动平均滤波,换算为湿度百分比,并按阈值判断“偏干、适宜、偏湿”。执行层:0.96 寸 OLED 显示土壤湿度、温度和空气湿度;当湿度低于阈值时,屏幕闪烁提示,也可扩展 LED 或蜂鸣器。日志/联网层:通过 MQTT 将 JSON 数据发布到 Broker,手机或 Home Assistant 订阅后远程查看。低功耗方面,采集间隔设为 10 分钟,其余时间进入深度睡眠,适合电池供电。
物料清单
| 物料 | 数量 | 用途 | 估算单价 | 合计 |
|---|---|---|---|---|
| ESP32-S3 开发板 | 1 | 主控与 Wi-Fi | 22 元 | 22 元 |
| 电容式土壤湿度传感器 | 1 | 采集盆土湿度 | 5 元 | 5 元 |
| DHT22 温湿度传感器 | 1 | 空气温湿度 | 9 元 | 9 元 |
| 0.96 寸 OLED I2C | 1 | 本地显示 | 8 元 | 8 元 |
| 杜邦线 | 若干 | 连接 | 3 元 | 3 元 |
| 10k 电阻 | 1 | DHT22 上拉 | 0.2 元 | 0.2 元 |
| 面包板 | 1 | 搭建电路 | 4 元 | 4 元 |
| 5V 电源或电池盒 | 1 | 供电 | 8 元 | 8 元 |
| 合计 | 59.2 元 |
接线与结构
土壤湿度传感器:VCC 接 3.3V,GND 接 GND,A0 接 GPIO4。微调理由:ESP32-S3 的 ADC1 通道为 GPIO1—GPIO10,GPIO34 不属于可用模拟通道,改用 GPIO4 可稳定读取。DHT22:VCC 接 3.3V,GND 接 GND,DATA 接 GPIO15,DATA 与 VCC 之间加 10k 上拉电阻。OLED:VCC 接 3.3V,GND 接 GND,SDA 接 GPIO21,SCL 接 GPIO22。结构上,主控和 OLED 放入阳台防水盒,土壤传感器探针插入盆土,DHT22 露在空气中。电源可用 USB 适配器或 18650 电池盒。注意探针不要长期浸泡,电容式比电阻式更耐腐蚀。
核心代码
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#define SOIL_PIN 4
#define DHT_PIN 15
#define DHT_TYPE DHT22
#define OLED_SDA 21
#define OLED_SCL 22
DHT dht(DHT_PIN, DHT_TYPE);
Adafruit_SSD1306 display(128, 64, &Wire;, -1);
WiFiClient espClient;
PubSubClient mqtt(espClient);
const char* ssid = "你的WiFi";
const char* password = "你的密码";
const char* mqttServer = "broker.emqx.io";
const int mqttPort = 1883;
const char* topic = "balcony/soil";
void setup() {
Serial.begin(115200);
pinMode(SOIL_PIN, INPUT);
dht.begin();
display.clearDisplay();
display.setTextSize(1);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
while (!mqtt.connected()) mqtt.connect("esp32-soil");
}
void loop() {
int raw = analogRead(SOIL_PIN);
int soil = map(raw, 4095, 0, 0, 100);
soil = constrain(soil, 0, 100);
float temp = dht.readTemperature();
float hum = dht.readHumidity();
display.clearDisplay();
display.setCursor(0, 0);
display.print("Soil:"); display.print(soil); display.println("%");
display.print("Hum:"); display.print(hum); display.println("%");
display.display();
char payload[128];
snprintf(payload, 128, "{\"soil\":%d,\"temp\":%.1f,\"hum\":%.1f}", soil, temp, hum);
mqtt.publish(topic, payload);
delay(2000);
esp_deep_sleep_start();
}
调试步骤
- 单独给土壤湿度传感器供电,串口打印
analogRead原始值,分别记录空气中、刚浇水后、干燥时的数值,确定干湿映射范围。 - 测试 DHT22,确认温湿度读数正常,若失败检查上拉电阻和 GPIO15。
- 用 I2C 扫描程序确认 OLED 地址,通常为 0x3C,然后显示固定文字。
- 配置 Wi-Fi 和 MQTT,用 MQTTX 或 mosquitto_sub 订阅
balcony/soil,查看 JSON 是否上报。 - 整机联调,观察深度睡眠电流,调整上报间隔为 10 分钟或 30 分钟。
- 放入防水盒,探针插入盆栽,连续运行一天,对比人工浇水记录,微调阈值。