esp8266 配网后使用mqtt进行远程信号控制

9/16/2023 2:07:47 PM
648
0

一、物料

  1. 面包板 x1
  2. 无源蜂鸣器 x1
  3. 继电器 x1
  4. esp8266 x1
  5. 电灯泡组件x1
  6. 杜邦线 公对母 若干
  7. 5V  DCx1
  8. 线路电线若干
  9. 交流电接线x1

二、接线

蜂鸣器 长针接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

全部评论



提问