ESP8266 家庭自动化项目中文版目录
有很多温度传感器可以使用,但对于这个项目,我们将使用一个非常常见的,DTH22。它可以测量温度和湿度。
以下是 DHT22 的特点:
DHT22可以作为单独的传感器或面包板元件。最好购买面包板元件版,因为它还有 4k7 上拉电阻和一个电容。如果你更喜欢单独的传感器这就是引脚:
DHT22 pinout
这里:
不要忘记在DATA和VCC引脚之间添加4K7上拉电阻。用于与燃气炉或其他加热元件的连接,将在GPIO 12上添加一个继电器。确保您有一个良好的电源,因为继电器将消耗一些电能。
在这种情况下,我们的设置将是:
Final circuit for thermostat添加了两个LED,一个RED LED显示加热正在进行,一个GREEN LED显示系统有电。只有当红色LED不亮时,绿色LED才会亮起。
在继电器板上,仅当GPIO 12为高电平且正在进行加热时,才存在C(公共)和NO(常开)之间的连接。
信息:对220V电力感到满意,并确保我们选择能够保持消耗功率的继电器。
基本上恒温器将测量温度,如果它高于所需的温度,它将关闭继电器,如果它低于它,它将打开继电器开始加热。
如果我们按照这样的逻辑,恒温器会经常打开和关闭继电器,所以我们需要在加热的开始和停止之间添加一个偏移量(delta)。在商用恒温器上,可以对这个偏移进行编程(在0.1℃ 递增到到1℃)或者可以固定为 0.5℃
在我们的系统中,偏移量将设置为 0.4%℃。这意味着,如果我们所需的温度是 22.0℃,加热器将在21.69℃时开始并在22.4℃时停止。
为了在我们的恒温器上设置所需的温度,我们将向主题 thermostat/set 发送 MQTT 消息,其中包含所需温度的内容(例如23.2);系统将借助 SPIFFS 将值保存在文件中,并将其与从 DHT22 传感器读取的当前温度进行比较。如果发生电源故障,将从配置文件中读取所需的温度,以使其不会丢失。
当恒温器第一次通电时,所需温度硬编码至22℃。恒温器将定期在 thermostat/get 主题上发布DHT22检测到的温度。
为了使用 DHT22 传感器,您需要一些库。安装 Adafruit Unified Sensor(Adafruit 统一传感器),然后按照与第1章,ESP8266入门相同的步骤安装 DHT 传感器库。
在库管理器中对 Adafruit Unified Sensor 进行搜索:
在库管理器中对 DHT22 进行搜索:
我们安装了两个库之后现在我们有了所有必要的头如下:
#include
#include
#include
#include
稍后将在我们的代码中使用的常量如下。确保您具有正确的值:
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;// 从传感器读取的值
gettemperature() 从DHT22传感器获取 温度 和 湿度,并将它们保存到全局变量的 humidity 和 temp_f 中。如果你需要华氏温度,请用 true 作为一个参数去调用 dht.readTemperature() 函数,像这样 readTemperature(true);:
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_LED, 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());
}
以下是在订阅主题 thermostart/set 上收到新的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
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);
}
}
}
loop 函数是我们用于触发 继电器 和 LED ON 或 OFF 的逻辑的地方。每两秒钟读取一次温度并用我们想要的温度进行检查,如下所示:
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
如果您订阅 thermostat/get 主题,您将每隔两秒钟获得房间内的当前温度,如以下屏幕截图所示:
Room temperature received from MQTT broker对于 Android 手机,有一个名为 MyMQTT 的应用程序,如果您的代理可以通过互联网访问,您可以在不在家时设置所需的温度;你也可以看到你家当前的温度。此 MyMQTT 应用程序的主菜单如下:
MyMQTT main screen在“设置”菜单中,设置MQTT代理服务器 IP 地址,所用的 MQTT 端口 以及用户和密码。
保存配置后,应用程序将连接到您的代理服务器。要查看来自您的代理服务器的消息,您可以订阅#topic ;在这种情况下,您将看到代理服务器收到的所有消息(如下面的屏幕截图所示),或者到 thermostart/get 主题 接受你家中的温度信息:
如果您不在,可以通过在主题 thermostat/set 上向您的家用恒温器发布具有所需温度的消息来远程设置恒温器,如以下屏幕截图所示:
发布所需温度以控制恒温器此基本功能恒温器系统教您如何使用SPIFFS存储文件和值,从MQTT代理发送和接收值,并将它们存储在传感器中以读取温度和湿度。作为练习,您可以通过以下功能改进恒温器: