用ESP8266实现自动浇花系统

专为新手设计的智能灌溉入门教程!无需编程基础,只需简单配置几个MQTT主题(如topic_pump_set手动控制水泵、topic_threshold_set设置湿度阈值、topic_moisture查看实时湿度),就能亲手打造一个会“自己判断是否浇水”的小系统。边做边学,轻松锻炼动手能力,开启你的智能家居第一步!
准备工作:
材料:
材料名称
数量
备注
土壤湿度传感器
1
ESP8266
1
水泵
1
软管
1
杜邦线
若干
电池盒
1
2
安装串口驱动

首先需要安装CK341SER驱动程序,以支持后续的硬件连接与调试。
3
设置ESP8266下载地址




12
在Arduino IDE的开发板管理器中,添加ESP8266的下载源地址:http://arduino.esp8266.com/stable/package_esp8266com_index.json。
4
下载必要依赖




12
在Arduino IDE中的“开发板管理器”来查找并下载ESP8266核心库,下载完成之后切换到库管理,搜索"PubSubClient",选中"安装"即可。
5
接线图

- 土壤湿度传感器(电容式)连接:
- 传感器的 auto 引脚连接到 ESP8266 的 A0 模拟输入口,用于读取土壤湿度值。
- 传感器的 VCC 引脚连接到 ESP8266 的 3V3 电源引脚,提供工作电压。
- 传感器的 GND 引脚连接到 ESP8266 的 GND 地线。
- 继电器模块连接:
- 继电器的 IN 输入端连接到 ESP8266 的 D1 数字输出引脚,用于接收控制信号。
- 继电器的 DC+ 接 ESP8266 的 3V3 供电,DC- 接 GND,为继电器提供工作电源。
- 水泵与电源连接:
- 水泵的正极(+)连接到 5V电池 的正极。
- 水泵的负极(-)连接到继电器的 NO(常开)触点。
- 继电器的 COM(公共端) 连接到电池的负极(-)。
- 当 ESP8266 输出高电平,继电器吸合,COM 与 NO 接通,水泵得电开始工作;反之则关闭。
6
代码

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// ===== 配置区 =====
const char* ssid = "vivoX200";
const char* password = "12345678";
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
const char* mqtt_client_id = "esp8266_garden_01";
const char* mqtt_user = "";
const char* mqtt_password = "";
// 检测湿度
const char* topic_moisture = "garden/sensor/moisture";
// 水泵状态
const char* topic_pump_status = "garden/pump/status";
// 上报水泵模式
const char* topic_mode_status = "garden/mode/status";
// 水泵模式设置 ON/OFF/AUTO
const char* topic_pump_set = "garden/pump/set";
// 设置阈值 当前干燥值400
const char* topic_threshold_set = "garden/threshold/set";
// 土壤湿度模块
const int sensorPin = A0;
// 继电器
const int relayPin = 5; // D1
// 工作参数
int dryThreshold = 400; // 干燥阈值(需根据传感器校准)
// 防止浇水过多
int stopWater =200;
const int hysteresis = 30; // 迟滞值,防止抖动(例如:开泵<400,关泵>430)
bool pumpState = false; // 水泵当前状态(false=关)
bool autoMode = true; // 默认自动模式
const unsigned long minWaterDuration = 5000; // 最少浇水5秒
const unsigned long cooldownTime = 60000; // 浇水后冷却1分钟
const unsigned long readInterval = 10000; // 每10秒读一次
unsigned long lastReadTime = 0;
WiFiClient espClient;
PubSubClient client(espClient);
// 工具函数:发布水泵状态和模式
void publishStatus() {
client.publish(topic_pump_status, pumpState ? "ON" : "OFF", true);
client.publish(topic_mode_status, autoMode ? "AUTO" : "MANUAL", true);
}
// 控制水泵(注意:继电器类型!)
void setPump(bool on) {
// 假设继电器是“低电平触发”:LOW = 开泵
digitalWrite(relayPin, on ? LOW : HIGH);
pumpState = on;
publishStatus();
Serial.println("Pump: " + String(on ? "ON" : "OFF"));
}
// MQTT 回调
void mqttCallback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
String msg = String((char*)payload);
msg.trim();
String topicStr = String(topic);
Serial.print("MQTT Received ["); Serial.print(topicStr); Serial.print("]: "); Serial.println(msg);
if (topicStr == topic_pump_set) {
if (msg == "ON") {
autoMode = false;
setPump(true);
} else if (msg == "OFF") {
autoMode = false;
setPump(false);
} else if (msg == "AUTO") {
autoMode = true;
Serial.println("Switched to AUTO mode");
publishStatus(); // 立即上报模式变更
}
}
else if (topicStr == topic_threshold_set) {
int newThresh = msg.toInt();
if (newThresh >= 0 && newThresh <= 1023) {
dryThreshold = newThresh;
Serial.println("New dry threshold: " + String(dryThreshold));
// 可选:上报确认
client.publish("garden/threshold/current", String(dryThreshold).c_str(), true);
}
}
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect(mqtt_client_id, mqtt_user, mqtt_password)) {
Serial.println("Connected");
client.subscribe(topic_pump_set);
client.subscribe(topic_threshold_set);
// 上报初始状态
publishStatus();
} else {
Serial.print("Failed, rc=");
Serial.print(client.state());
delay(2000);
}
}
}
void setup() {
// 设置串口
Serial.begin(115200);
// 设置D1针脚为输出模式
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH); // 初始关闭
setPump(false);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected. IP: " + WiFi.localIP().toString());
client.setServer(mqtt_server, mqtt_port);
client.setCallback(mqttCallback);
}
void loop() {
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
unsigned long now = millis();
// 每隔 readInterval 读取一次传感器并上报
if (now - lastReadTime >= readInterval) {
lastReadTime = now;
int moisture = analogRead(sensorPin);
Serial.print("Moisture: "); Serial.println(moisture);
client.publish(topic_moisture, String(moisture).c_str());
// 最低湿度
if(moisture==stopWater){
autoMode = false;
setPump(false);
}
// === 自动控制逻辑 ===
if (autoMode) {
bool shouldRun = false;
// 【关键】判断传感器特性:
// 多数土壤湿度模块:数值越小 → 越湿;数值越大 → 越干
// 所以:moisture > dryThreshold 表示“太干”
if (moisture > dryThreshold) {
shouldRun = true;
}
// 关泵条件:必须比阈值高一个迟滞值(避免在阈值附近反复开关)
else if (moisture < (dryThreshold - hysteresis)) {
shouldRun = false;
}
// 如果需要开泵,且不在冷却期
if (shouldRun && !pumpState) {
Serial.println("Auto: Soil dry, starting pump.");
// 开启水泵
setPump(true);
}else{
Serial.println("Auto: Soil moisture, stop pump.");
// 关闭水泵
setPump(false);
}
}
}
delay(100); // 避免 watchdog 触发
}
7
MQTTX连接




12
打开安装好的MQTTX软件,选择创建新的连接。设置名称、服务器地址以及端口信息,完成后点击右上角的连接。
8
添加订阅内容





123
点击“添加订阅”按钮后,系统将弹出输入框,此时请填入您事先定义好的主题名称。为了便于后续识别和管理,建议在输入主题的同时为其设置一个简洁明了的别名。例如,若主题为“weather_data_feed”,可将其别名设为“天气数据推送”。
9
演示
配置好之后,系统就可以直接用了。默认是 自动模式(AUTO),也就是说,它会根据你提前设好的湿度阈值,自动判断要不要浇水——比如土壤太干了,就自动打开水泵;湿度够了,就自动停掉,完全不用你操心。
当然,你也可以手动控制:
- 只要往
topic_pump_set这个主题发个指令(比如“开”或“关”),就能立刻手动启动或关闭水泵; - 如果想调整自动浇水的“干湿标准”,就往
topic_threshold_set发送一个新的数值,比如设成600,意思是土壤湿度高于600才浇水; - 想随时看看地里现在有多湿?订阅
topic_moisture就行,它会实时把当前的湿度数据推给你。
0
0
0
qq空间
微博
复制链接
分享 更多相关项目
猜你喜欢
评论/提问(已发布 0 条)
0