ESP8266 家庭自动化项目中文版目录
有许多温度传感器可以使用,但对于这个项目,我们将使用一个非常常见的,DTH22.它可以测量温度和湿度。
以下是 DHT22 的特点:
- 低成本
- 3到5V 供电的 I/O
- 转换期间使用5mA最大电流(同时要求数据)
- 适用于0-100%湿度读数,精度为2-5%
- 适用于-40至125℃的温度读数 0.5℃精度
- 不超过0.5 Hz采样率(每两秒一次)
- 机身尺寸1 5.1mm X 25mm X 7.7mm
- 四个引脚,间距为0.1“
DHT22可以作为单独的传感器或面包板元件。最好购买面包板元件版,因为它还有 4k7 上拉电阻和电容。如果你更喜欢单独的传感器,这就是引脚:

这里:
- VCC:可以在3V3和5V之间
- GND:是接地线
- DATA:是数据引脚
不要忘记在DATA和VCC在引脚之间加4K7上拉电阻。将与燃气炉或其他加热元件连接GPIO 在12上添加继电器。确保您有良好的电源,因为继电器会消耗一些电能。
在这种情况下,我们的设置将是:
添加了两个LED,一个RED LED显示加热正在进行中,一个GREEN LED显示系统有电。只有红色LED不亮时,绿色LED才会亮起。
仅当于继电器板GPIO 只有在高电平和加热时才存在C(公共)和NO(常开)连接。
恒温器基本上会测量温度。如果它高于所需温度,它将关闭继电器。如果它低于它,它将打开继电器并开始加热。 如果我们遵循这个逻辑,恒温器经常打开和关闭继电器,所以我们需要在加热开始和停止之间增加偏移(delta)。这种偏移可以在商用恒温器上编程(0.1℃ 递增到到1℃)或者可以固定 0.5℃ 偏移量设置在我们的系统中 0.4%℃。这意味着,如果我们需要的温度是 22.0℃,加热器将在21.69℃时开始并在22.4℃时停止。
为了在恒温器上设置所需的温度,我们将主题 发送 MQTT 消息,其中包含所需温度的内容(例如23.2);借助系统 SPIFFS 将值保存在文件中并与从 DHT22 比较传感器读取的当前温度。如果发生电源故障,将从配置文件中读取所需温度,以免丢失。
当恒温器首次通电时,所需的温度硬编码为22℃。恒温器将定期存在主题上发布DHT22检测到的温度。
为了使用 您需要一些传感器库。 Adafruit Unified Sensor(Adafruit 按照第一章统一传感器),ESP8266入门安装步骤相同 DHT 传感器库。
在库管理器中对 进行搜索:
在库管理器中对 进行搜索:
在我们安装了两个库之后,我们现在有了以下所有必要的头:
#include <FS.h> #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <DHT.h>
以后在我们的代码中使用的常数如下。确保您有正确的值:
const char* ssid = "YOUR_WIFI_SSID"; const char* password = "YOUR_WIFI_PASSWORD"; const char* mqtt_server = "YOUR_MQTT_SERVER"; const char* mqtt_user = "YOUR_MQTT_USER"; const char* mqtt_passwd = "YOUR_MQTT_PASSWORD"; const int mqtt_port = 1883; //你的 MQTT PORT
连接到继电器模块 GPIO 12 ,DHT22 连接到引脚 4,LEDs 和GPIO 13 、GPIO 15 连接如下:
#define RELAY_PIN 12 #define DHTTYPE DHT22 #define DHTPIN 4 #define GREEN_LED 15 #define RED_LED 13
我们的整体对象、偏移和所需温度的默认值:
WiFiClient espClient; PubSubClient client(espClient); DHT dht(DHTPIN, DHTTYPE, 11); long lastMsg = 0; float offset_temp = 0.4; float desired_temp = 22.0; float humidity, temp_f;// 从传感器读取的值
从DHT22传感器获取 和 ,并将其保存到全局变量中 和 中。如需华氏温度,请使用 调用作参数函数,就像这样:
void gettemperature() { int runs=0; do { temp_f = dht.readTemperature(false); humidity = dht.readHumidity(); if(runs > 0) { Serial.println("##Failed to read f rom DHT sensor! ###"); } // Serial.println(String(temp_f).C_str()); // Serial.println(String (humidity).C_str()); runs ; } while(isnan(temp_f) && isnan(humidity)); }
setup 函数部分把 继电器 和 LED 引脚设置为 OUTPUT,绿色LED电源启动时默认为开启状态,如下所示:
void setup() { pinMode(RELAY_PIN, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(RED_ED, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
digitalWrite(GREEN_LED, HIGH);
digitalWrite(RED_LED, LOW);
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
if(SPIFFS.begin())
{
Serial.println(F("File system was mounted."));
//检查我们是否具有除默认温度之外的所需温度
File f = SPIFFS.open("/config_temp.txt" ,"r");
if (!f)
{
//现在阅读文件内容
String s=f.readStringUntil('n');
Serial.println(s);
desired_temp = s.toFloat();
//现在关闭文件
f.close();
} else {
Serial.println(F("Failed to open my_file.txt"));
}
}
}
使用提供的凭据连接到Wi-Fi网络,如下所示:
void setup_wifi() {
delay(10);
//我们首先连接到WiFi网络
Serial.println();
Serial.print(F("Connecting to "));
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
WiFi.begin(ssid, password);
Serial.print(".");
delay(5000);
}
Serial.println(F("WiFi connected"));
Serial.println(F("IP address :"));
Serial.println(WiFi.localIP());
}
以下是在订阅主题上收到新的MQTT消息时触发的 :
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print(F("Message arrived ["));
Serial.print(topic);
Serial.print(F("] "));
for(inti=0;i<length;i++){
Serial.print((char)payload[i]);
}
Serial.println();
char rxj[20];
int i;
for(i=0; i<length;i++){
rxj[i] = payload[i] ;
]
File my_file = SPIFFS.open("/config_temp.txt", "w+") ;
if (!my_file) {
Serial.println("file open failed") ;
}
Serial.println(F("Writing to config_temp.txt"));
//将内容打印到 my_file.txt
my_file.println(String(rxj).C_str());
//现在关闭文件
my_file.close();
desired_temp = String(rxj).toFloat();
}
}
Reconnect to the MQTT server in case some keep alive frames are lost, as shown in the following code:
如果某些保持活动帧丢失,请重新连接到MQTT服务器,如以下代码所示:
void reconnect()
{
//循环直到我们重新连接
while(!client.connected()){
Serial.print(F("Attempting MQTT connection...") ) ;
if(client.connect("ESP8266Client", mqtt_user, mqtt_passwd))
{
Serial.println(F("connected"));
client.subscribe("thermostat/set");
} else {
Serial.print(F("failed, rc="));
Serial.print(client.state( ));
Serial.println(F("try again in 5 seconds"));
//等待5秒再重试
delay(5000);
}
}
}
函数是我们用于触发 继电器 和 LED 或 的逻辑的地方。每两秒钟读取一次温度并用我们想要的温度进行检查,如下所示:
void loop()
{
gettemperature();
if(!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now lastMsg > 2000) {
lastMsg = now;
if((float)desired_temp offset_temp >= (float)temp_f)
{
//Serial.println(F("Start heating..."));
digitalWrite (RELAY_ PIN, HIGH);
digitalWrite (GREEN_ LED, LOW);
digitalWrite(RED_ LED, HIGH);
}
else if((float)desired_temp + offset_temp <= (float)temp_f)
{
//Serial. println(F("Stop heating..."));
digitalWrite (RELAY_PIN, LOW);
digitalWrite (GREEN_LED, HIGH);
digitalWrite (RED_LED ,LOW);
}
client.publish ("thermostat/get", String(temp_f).c_str());
}
}
要设置温度,您可以使用MQTT代理的本地控制台,就像我们在第2章中所做的那样,Вuіldіng 和СоnfіgurіngYоurОwnМQТТЅеrvеr:
mosquitto_ pub -t " thermostat/set" m 28.2 -p 1883 -h YOUR_ MQTT_ SERVE_ IP -u YOUR_ MQTT_ USER -P YOUR MQTT PAS SWORD
如果您订阅 主题,您将每隔两秒钟获得房间内的当前温度,如以下屏幕截图所示:
对于 Android 手机,有一个名为 的应用程序,如果您的代理可以通过互联网访问,您可以在不在家时设置所需的温度;你也可以看到你家当前的温度。此 MyMQTT 应用程序的主菜单如下:
在“设置”菜单中,设置MQTT代理服务器 IP 地址,所用的 MQTT 端口 以及用户和密码。 保存配置后,应用程序将连接到您的代理服务器。要查看来自您的代理服务器的消息,您可以订阅#topic ;在这种情况下,您将看到代理服务器收到的所有消息(如下面的屏幕截图所示),或者到 你家中的温度信息:
如果您不在,可以通过在主题上向您的家用恒温器发布具有所需温度的消息来远程设置恒温器,如以下屏幕截图所示:
发布所需温度以控制恒温器此基本功能恒温器系统教您如何使用SPIFFS存储文件和值,从MQTT代理发送和接收值,并将它们存储在传感器中以读取温度和湿度。作为练习,您可以通过以下功能改进恒温器:
- 也发布湿度
- 将配置文件保存为JSON文件
- 添加一个计时恒温器功能,在设计好的时间内加热您的家
- 添加一个窗口打开功能,如果温度下降很快就停止加热房子
- 通过 MQTT 将温度,湿度和所需温度作为JSON消息发布
- 使用逆逻辑在炎热的夏天冷却你的房子。