💡 划重点

  • 主控芯片:ESP32-S3,支持 Wi-Fi 与 BLE,适合 MQTT 数据上报与本地控制。
  • 传感器:电容式土壤湿度传感器(模拟输出)+ DHT22 空气温湿度。
  • 人机交互:0.96 寸 OLED,实时显示土壤湿度、环境温湿度和 Wi-Fi 状态。
  • 联网方案:MQTT 协议上报数据到本地或云端 Broker,支持手机 App 查看。
  • 供电与功耗:采用 5V USB 供电,代码中启用 modem_sleep 与 light_sleep 机制,实现低功耗待机。
  • 总物料成本控制在 60 元以内,适合阳台园艺爱好者 DIY。

需求洞察

目标用户:城市阳台园艺爱好者,尤其是朝九晚五的上班族和刚刚开始养绿植的新手。

真实痛点:浇水完全靠经验或固定日历,夏天容易蒸发过快导致缺水,冬天又容易盆内涝根;出差或加班时无法得知盆栽的真实状态,往往等叶子发黄才发现问题。

为什么值得做:土壤湿度是一个典型的“看不见却致命”的变量。市售智能花盆价格动辄 200-400 元,且传感器集成度低,不能自行扩展。本项目基于 ESP32-S3,用 60 元以内成本搭建一套具备“实时感知—阈值提醒—远程查看—低功耗待机”的完整守护系统,帮助用户把浇水的“玄学”变成“科学”。

方案设计

感知层

控制层

执行层

日志/联网层

物料清单

物料名称 数量 用途 估算单价(元)
ESP32-S3-DevKitC-1 1 主控芯片 28.0
电容式土壤湿度传感器 1 土壤湿度感知 8.5
DHT22 温湿度传感器模块 1 环境温湿度采集 7.0
0.96 寸 OLED(I2C) 1 本地状态显示 10.0
5V 微型继电器模块 1 控制水泵通断 2.5
3.3V 蜂鸣器模块 1 预警提示 1.2
杜邦线/JST 连接线 若干 接线连接 2.0
合计 - - 59.2

接线与结构

模块 引脚 ESP32-S3 GPIO
土壤湿度模块 AO A0 GPIO34
土壤湿度模块 VCC - 3.3V
土壤湿度模块 GND - GND
DHT22 DATA - GPIO15
OLED SCL - GPIO22
OLED SDA - GPIO21
继电器 IN - GPIO4
蜂鸣器 I/O - GPIO5

接线说明:本项目完全遵循建议接线,未做 GPIO 微调。OLED 使用 I2C 标准引脚(SCL=22,SDA=21),湿度传感器模拟输出接 ADC 可用通道 GPIO34。继电器和蜂鸣器采用数字输出 GPIO4/5,避免与 I2C 和 ADC 冲突。

核心代码

本方案使用 Arduino 框架(PlatformIO 环境)编写,可直接编译烧录。


#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

// Wi-Fi 与 MQTT 配置
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
const char* mqtt_server = "broker.emqx.io";

WiFiClient espClient;

// 引脚定义
#define SOIL_PIN 34
#define DHT_PIN 15
#define OLED_SDA 21
#define OLED_SCL 22
#define RELAY_PIN 4
#define BUZZER_PIN 5

// 阈值定义
#define DRY_THRESHOLD 25
#define WET_THRESHOLD 70

DHT dht(DHT_PIN, DHT22);
Adafruit_SSD1306 display(128, 64, &Wire;, -1);

unsigned long lastPublish = 0;
const unsigned long interval = 1800000; // 30分钟上报一次

void setup() {
  Serial.begin(115200);
  pinMode(SOIL_PIN, INPUT);
  pinMode(DHT_PIN, INPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  display.clearDisplay();
  dht.begin();
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  unsigned long now = millis();
  if (now - lastPublish >= interval) {
    lastPublish = now;

    int soilRaw = analogRead(SOIL_PIN);
    int humidity = map(soilRaw, 2900, 1200, 0, 100); // 根据实际饱和度校准
    humidity = constrain(humidity, 0, 100);

    float temp = dht.readTemperature();
    float airHum = dht.readHumidity();

    // 自动浇水逻辑
    if (humidity < DRY_THRESHOLD) {
      digitalWrite(RELAY_PIN, HIGH);
      tone(BUZZER_PIN, 1000, 200);
    } else if (humidity > WET_THRESHOLD) {
      digitalWrite(RELAY_PIN, LOW);
    }

    // OLED 显示
    display.clearDisplay();
    display.setTextSize(1);
    display.setCursor(0, 0);
    display.printf("Soil: %d%%", humidity);
    display.setCursor(0, 16);
    display.printf("Temp: %.1f C", temp);
    display.setCursor(0, 32);
    display.printf("AirH: %.1f %%", airHum);
    display.display();

    // MQTT 发布
    String payload = "{\"soil\":" + String(humidity) +
                     ",\"temp\":" + String(temp) +
                     ",\"airh\":" + String(airHum) + "}";
    client.publish("balcony/pot/soil", payload.c_str());

    // 进入浅睡眠,等待下一个周期
    esp_light_sleep_start();
  }
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("ESP32S3_SoilGuard")) {
    } else {
      delay(1000);
    }
  }
}

调试步骤

  1. 烧录前将代码中的 SSID 和密码改为实际值,MQTT Broker 地址不做更改。
  2. 将传感器插入干燥土壤,读取串口输出的 soilRaw 最大值;再将传感器插入水中,读取最小值。修改 map() 函数参数完成一对一校准。
  3. 用手机安装 MQTT 调试工具(如 MQTT Dashboard),订阅 balcony/pot/soil 主题,验证数据是否正常上报。
  4. 调整 DRY_THRESHOLDWET_THRESHOLD 值至适合实际植物的水平。
  5. 测试自动浇水:将传感器放置在干燥花盆中,确认继电器吸合并水泵启动;再用湿毛巾包裹传感器,确认水泵停止运行。

设计图

阳台盆栽土壤湿度守护结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报

感知输入层包含土壤湿度传感器与 DHT22,数据流经控制处理层后,将指令分发至执行反馈层(继电器/水泵与蜂鸣器),同时通过 MQTT 上报至云端。整个系统由 ESP32-S3 在低功耗循环周期内串联所有环节,实现对盆栽全天候守护。