DIY智能家居:用ESP8266实现温湿度联动风扇自动控制(接入EMQX平台)


·居
原创
发布时间: 2025-11-20 14:27:39 | 阅读数 0收藏数 0评论数 0
封面
本项目基于ESP8266实现智能风扇控制系统,集成DHT11温湿度传感器,支持自动与手动双模式。通过MQTT协议接入EMQX云平台,用户可远程设置开关或切换为自动模式(温度≥28°C开启,≤26°C关闭)。系统实时上报环境数据与设备状态,具备低功耗、响应快、稳定性高特点,适用于智能家居场景。

准备工作:

材料:

材料名称
数量
备注
esp8266
1
用于和MQTT通信
马达
1
模拟风扇降温
继电器
1
控制风扇开关
DHT11
1
温度检测
杜邦线
若干
1

安装MQTTX

搜索MQTTX官网,进入官网下载MQTTX。

2

安装串口驱动

首先需要安装CK341SER驱动程序,以支持后续的硬件连接与调试。

3

设置ESP8266下载地址

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

4

下载必要依赖

在Arduino IDE中的“开发板管理器”来查找并下载ESP8266核心库及PubSubClient库并进行下载,之后切换到"库管理"中下载DHT sernor library依赖,点击安装之后会有弹窗,选中“全部安装”即可。

5

接线图

  1. 电源与共地
  2. 所有模块的 GND(继电器、DHT11、马达驱动部分)都连接到 ESP8266 的 GND,形成共地。
  3. DHT11 连接
  4. DHT11 的 VCC 接 ESP8266 的 3.3V
  5. DHT11 的 GNDGND
  6. DHT11 的 数据引脚(DATA) 接 ESP8266 的某个 GPIO(常见为 D2 )。
  7. 继电器连接
  8. 继电器模块的 VCC3.3V 或 5V(视模块而定,多数可兼容 3.3V 控制)。
  9. 继电器的 GNDGND
  10. 继电器的 IN(控制信号) 接 ESP8266 的一个 GPIO(例如 D1 )。
  11. 继电器的常闭(NC)接ESP8266的GND。
  12. 马达(模拟风扇)连接
  13. 马达一端接 外部电源正极(如 3V电源)。
  14. 马达负极接继电器的COM(公共端)。
PDF
Untitled Sketch_bb.pdf
603.66KB
6

代码

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

// === 配置区 ===
// 修改为自己的WiFi名称
#define WIFI_SSID "vivoX200"
// 修改密码
#define WIFI_PASSWORD "12345678"

#define MQTT_SERVER "broker.emqx.io"
#define MQTT_PORT 1883
#define MQTT_USER ""
#define MQTT_PASSWORD ""

#define DEVICE_PREFIX "home/yj"

// 温度
#define TOPIC_TEMP DEVICE_PREFIX "/sensor/temperature"
// 湿度
#define TOPIC_HUM DEVICE_PREFIX "/sensor/humidity"
// 设置开关
#define TOPIC_FAN_SET DEVICE_PREFIX "/fan/set"
// 当前风扇开关状态
#define TOPIC_FAN_STATE DEVICE_PREFIX "/fan/state"
// 手动/自动
#define TOPIC_FAN_MODE DEVICE_PREFIX "/fan/mode" // 新增:模式状态

// 引脚定义
#define DHT_PIN 4 // D2 (GPIO4)
#define RELAY_PIN 5 // D1 (GPIO5)

#define DHTTYPE DHT11

const long SENSOR_INTERVAL = 5000; // 5秒读一次传感器

// 自动控制阈值(带迟滞)
const float TEMP_THRESHOLD_ON = 28.0; // ≥28°C 开风扇
const float TEMP_THRESHOLD_OFF = 26.0; // ≤26°C 关风扇

// === 全局变量 ===
DHT dht(DHT_PIN, DHTTYPE);
WiFiClient espClient;
PubSubClient client(espClient);

unsigned long lastSensorRead = 0;
bool fanState = false;
bool fanStateChanged = false;
bool autoMode = true; // 默认启动自动模式

void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("MQTT Message received on [");
Serial.print(topic);
Serial.print("]: ");

String msg = "";
for (int i = 0; i < length; i++) {
msg += (char)payload[i];
}
Serial.println(msg);

if (String(topic) == TOPIC_FAN_SET) {
if (msg == "ON") {
setFanState(true);
autoMode = false;
client.publish(TOPIC_FAN_MODE, "MANUAL", true);
Serial.println("🔄 Switched to MANUAL mode (ON)");
} else if (msg == "OFF") {
setFanState(false);
autoMode = false;
client.publish(TOPIC_FAN_MODE, "MANUAL", true);
Serial.println("🔄 Switched to MANUAL mode (OFF)");
} else if (msg == "AUTO") {
autoMode = true;
client.publish(TOPIC_FAN_MODE, "AUTO", true);
Serial.println("🔄 Switched to AUTO mode");
// 触发立即评估温度
fanStateChanged = true; // 实际会在 loop 中通过温度判断
} else {
Serial.println("⚠️ Unknown command! Use 'ON', 'OFF' or 'AUTO'");
}
}
}

void setFanState(bool on) {
Serial.print("🔧 Setting fan to ");
Serial.println(on ? "ON" : "OFF");

digitalWrite(RELAY_PIN, on ? HIGH : LOW); // 继电器:HIGH=开(根据你的模块调整)
fanState = on;
fanStateChanged = true;
}

void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to WiFi: ");
Serial.println(WIFI_SSID);

WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}

if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.println("✅ WiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println();
Serial.println("❌ Failed to connect to WiFi!");
}
}

void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");

String clientId = "ESP8266_DHT_Fan_";
clientId += String(ESP.getChipId(), HEX);
if (clientId.length() > 23) clientId = clientId.substring(0, 23);

if (client.connect(clientId.c_str(), MQTT_USER, MQTT_PASSWORD)) {
Serial.println(" ✅ Connected!");
client.subscribe(TOPIC_FAN_SET);
Serial.print("Subscribed to: ");
Serial.println(TOPIC_FAN_SET);
} else {
Serial.print(" ❌ Failed, rc=");
Serial.print(client.state());
Serial.println(" - retrying in 5 seconds");
delay(5000);
}
}
}

void setup() {
Serial.begin(115200);
delay(1000);
Serial.println(">>> SMART FAN CONTROLLER v2.1 (Auto + Manual) <<<");
Serial.println("===================================");
Serial.println("🚀 Starting Smart Fan Controller");
Serial.println("===================================");

pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW); // 默认关闭风扇
Serial.println("🔌 Relay initialized to OFF");

dht.begin();
Serial.println("🌡 DHT11 sensor initialized");

setup_wifi();

client.setServer(MQTT_SERVER, MQTT_PORT);
client.setCallback(mqttCallback);

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

// 初始上报模式和状态
client.publish(TOPIC_FAN_MODE, "AUTO", true);
client.publish(TOPIC_FAN_STATE, "OFF", true);
}

void loop() {
if (!client.connected()) {
Serial.println("⚠️ MQTT disconnected, reconnecting...");
reconnect();
}
client.loop();

// 上报风扇状态变化(仅当变化时)
if (fanStateChanged) {
client.publish(TOPIC_FAN_STATE, fanState ? "ON" : "OFF", true);
Serial.print("📡 Published fan state: ");
Serial.println(fanState ? "ON" : "OFF");
fanStateChanged = false;
}

// 定期读取传感器并执行自动控制
if (millis() - lastSensorRead > SENSOR_INTERVAL) {
lastSensorRead = millis();

float h = dht.readHumidity();
float t = dht.readTemperature();

if (!isnan(t) && !isnan(h)) {
client.publish(TOPIC_TEMP, String(t).c_str());
client.publish(TOPIC_HUM, String(h).c_str());

Serial.print("📊 Temp: ");
Serial.print(t);
Serial.print("°C, Humidity: ");
Serial.print(h);
Serial.println("%");

// ========== 自动控制逻辑 ==========
if (autoMode) {
bool targetState = fanState; // 默认保持当前状态

if (t >= TEMP_THRESHOLD_ON) {
targetState = true; // 太热,开风扇
} else if (t <= TEMP_THRESHOLD_OFF) {
targetState = false; // 足够凉,关风扇
}
// 在 (26°C, 28°C) 区间保持原状态(防抖)

if (targetState != fanState) {
setFanState(targetState);
}
}
} else {
Serial.println("❌ Failed to read from DHT11!");
}
}
}
7

MQTTX连接

打开MQTTX客户端新建连接,输入名称以及服务器ip地址,完成之后点击右上角的连接。

8

添加订阅

点击添加订阅按钮,订阅主题。

9

运行效果


阅读记录0
点赞0
收藏0
禁止 本文未经作者允许授权,禁止转载
猜你喜欢
评论/提问(已发布 0 条)
评论 评论
收藏 收藏
分享 分享
pdf下载 下载
pdf下载 举报