一、物料
二、接线
蜂鸣器 长针接GPIO4针脚,对应D2,短针接G
继电器 DC+ 接5v的vcc+ DC- 接5v的vcc-, IN接 esp8266的电平信号GPIO口(自定义一个输出针脚),DC-接esp8266的G脚
因为继电器需要5V电源,这里做了单独供电。继电器的信号控制接入IN口,DC-接开发板G脚
vcc形成回路, 电平信号与G脚形成回路
三、逻辑原理
esp8266配网接入wifi后,使用mqtt 订阅远程服务器频道,远程客户端向服务器mqtt频道发送指令,服务器将指令推送给mqtt的订阅终端。esp8266接受到mqtt消息后,解读消息,并执行电平信号的控制继电器打开和关闭
四、接线图
五、源码
PubSubClient 用于mqtt服务
WiFiManager 用于wifi配网
ESP8266WebServer 用于esp作为作为web服务,为配网提供web ui
ESP8266WiFi 和 ESP8266HTTPClient 用于链接wifi和链接远程http服务器
首次写入程序后,使用手机链接wifi: AutoConnectAP 会自动弹出配置网络的页面,选择一个wifi配置好后,以后在当前环境不用再进行配置
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h> //mqtt库
// 测试HTTP请求用的URL。注意网址前面必须添加"http://"
#define URL "http://www.example.com/"
const char* mqttServer = "broker.emqx.io";
WiFiClient client;
PubSubClient mqttClient(client);
int ledOut = 5; //esp8266 D1 作为继电器的电平信号
#define buzzerOut 4 //esp8266 D2 通过PWM脉冲调制控制(无源)蜂鸣器电压的连续改变,实现蜂鸣器的鸣响
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // 设置板上LED引脚为输出模式
digitalWrite(LED_BUILTIN, LOW); // 启动后关闭板上LED
Serial.begin(9600); //初始化串口设置
// 建立WiFiManager对象
WiFiManager wifiManager;
// 自动连接WiFi。以下语句的参数是连接ESP8266时的WiFi名称
wifiManager.autoConnect("AutoConnectAP");
Serial.print("WiFi Connected!");
pinMode(buzzerOut, OUTPUT); //蜂鸣器
pinMode(ledOut, OUTPUT); //led 二极管
digitalWrite(buzzerOut, LOW);
digitalWrite(ledOut, LOW);
httpClientRequest(); //发送一个http请求
mqttClient.setServer(mqttServer, 1883); // 设置MQTT服务器和端口号
mqttClient.setCallback(receiveCallback); // 设置MQTT订阅回调函数
// 连接MQTT服务器
connectMQTTServer();
}
void loop() {
if (mqttClient.connected()) { // 如果开发板成功连接服务器
mqttClient.loop(); // 保持客户端心跳
} else { // 如果开发板未能成功连接服务器
connectMQTTServer(); // 则尝试连接服务器
}
}
// 发送HTTP请求并且将服务器响应通过串口输出
void httpClientRequest() {
//重点1 创建 HTTPClient 对象
HTTPClient httpClient;
//重点2 通过begin函数配置请求地址。此处也可以不使用端口号和PATH而单纯的
httpClient.begin(client, URL);
Serial.print("URL: ");
Serial.println(URL);
//重点3 通过GET函数启动连接并发送HTTP请求
int httpCode = httpClient.GET();
Serial.print("Send GET request to URL: ");
Serial.println(URL);
//重点4. 如果服务器响应HTTP_CODE_OK(200)则从服务器获取响应体信息并通过串口输出
//如果服务器不响应HTTP_CODE_OK(200)则将服务器响应状态码通过串口输出
if (httpCode == HTTP_CODE_OK) {
// 使用getString函数获取服务器响应体内容
String responsePayload = httpClient.getString();
Serial.println("Server Response Payload: ");
Serial.println(responsePayload);
} else {
Serial.println("Server Respose Code:");
Serial.println(httpCode);
}
//重点5. 关闭ESP8266与服务器连接
httpClient.end();
}
//链接mqtt
void connectMQTTServer() {
// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
String clientId = "esp8266-" + WiFi.macAddress();
// 连接MQTT服务器
if (mqttClient.connect(clientId.c_str())) {
Serial.println("MQTT Server Connected.");
Serial.print("Server Address: ");
Serial.println(mqttServer);
Serial.print("ClientId:");
Serial.println(clientId);
subscribeTopic(); // 订阅指定主题
} else {
Serial.print("MQTT Server Connect Failed. Client State:");
Serial.println(mqttClient.state());
delay(3000);
}
}
// 发布信息
void pubMQTTmsg() {
static int value; // 客户端发布信息用数字
// 建立发布主题。主题名称以Taichi-Maker-为前缀,后面添加设备的MAC地址。
// 这么做是为确保不同用户进行MQTT信息发布时,ESP8266客户端名称各不相同,
String topicString = "Taichi-Maker-Pub-" + WiFi.macAddress();
char publishTopic[topicString.length() + 1];
strcpy(publishTopic, topicString.c_str());
// 建立发布信息。信息内容以Hello World为起始,后面添加发布次数。
String messageString = "Hello World " + String(value++);
char publishMsg[messageString.length() + 1];
strcpy(publishMsg, messageString.c_str());
// 实现ESP8266向主题发布信息
if (mqttClient.publish(publishTopic, publishMsg)) {
Serial.println("Publish Topic:");
Serial.println(publishTopic);
Serial.println("Publish message:");
Serial.println(publishMsg);
} else {
Serial.println("Message Publish Failed.");
}
}
// 订阅指定主题
void subscribeTopic() {
// 建立订阅主题。主题名称以Taichi-Maker-Sub为前缀,后面添加设备的MAC地址。
// 这么做是为确保不同设备使用同一个MQTT服务器测试消息订阅时,所订阅的主题名称不同
String topicString = "Taichi-Maker-Sub-" + WiFi.macAddress();
char subTopic[topicString.length() + 1];
strcpy(subTopic, topicString.c_str());
// 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
if (mqttClient.subscribe(subTopic)) {
Serial.println("Subscrib Topic:");
Serial.println(subTopic);
} else {
Serial.print("Subscribe Fail...");
}
}
// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message Received [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println("");
Serial.print("Message Length(Bytes) ");
Serial.println(length);
if ((char)payload[0] == '1') { // 如果收到的信息以“1”为开始
digitalWrite(LED_BUILTIN, LOW); // 则点亮LED。
Serial.println("LED ON");
illumeON(); //继电器打开
Serial.println("继电器开启");
mingX(); //蜂鸣器鸣叫
} else {
digitalWrite(BUILTIN_LED, HIGH); // 否则熄灭LED。
Serial.println("LED OFF");
illumeOFF(); //继电器关闭
Serial.println("继电器关闭");
}
}
//继电器打开
void illumeON() {
digitalWrite(ledOut, HIGH); //led on
}
//继电器关闭
void illumeOFF() {
digitalWrite(ledOut, LOW); //检测了60次后,还是没有人,并且电平是高的时候,设置为低电平(关闭继电器)
}
//蜂鸣器
void mingX() {
digitalWrite(buzzerOut, HIGH); //输出HIGH电平,停止发声
delay(50); //等待50毫秒
digitalWrite(buzzerOut, LOW); //输出LOW电平,发声
}
六、演示效果
https://www.bilibili.com/video/BV1su4y1r7Ry?t=6.9
本文链接:https://blog.nnwk.net/article/166
有问题请留言。版权所有,转载请在显眼位置处保留文章出处,并留下原文连接
Leave your question and I'll get back to you as soon as I see it. All rights reserved. Please keep the source and links
友情链接:
子卿全栈
全部评论