问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

使用MQTT实现ESP8266开发板数据交互

创作时间:
作者:
@小白创作中心

使用MQTT实现ESP8266开发板数据交互

引用
CSDN
1.
https://m.blog.csdn.net/weixin_48895167/article/details/143367415

本文将介绍如何使用MQTT协议实现ESP8266开发板与传感器的数据交互。通过温湿度传感器、水位传感器和继电器的组合,可以构建一个功能丰富的物联网应用。

硬件准备工作

  • ESP8266开发板
  • 温湿度传感器(DHT11)
  • 水位传感器
  • 继电器模块

接线工作

  1. 水位传感器接线:
  • ESP8266的3V接水位检测模块的“+”
  • GND接“-”
  • A0接“S”
  1. 温湿度传感器接线:
  • ESP8266的D4接温湿度传感器的“DATA”
  • GND对“G”
  • VCC对"3V"
  1. 继电器模块接线:
  • 继电器的GND连接esp8266的G
  • 继电器In1连接esp8266的D1
  • Vcc接3V

软件准备工作

  • Arduino IDE(用于编写C代码)
  • IntelliJ IDEA(用于编写Java代码,JDK版本>=1.8)
  • MQTT服务器(下载地址:https://www.emqx.io/downloads)

代码实现

首先需要在ESP8266板子上写入通信协议,比如MQTT、TCP、UDP等,根据需求选择。

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

// WiFi配置
const char* ssid = "wifi名称";
const char* password = "wifi密码";
const char* mqtt_server = "mqtt服务器地址";

// DHT11传感器配置
#define DHTPIN 2
#define DHTTYPE DHT11

// 水位传感器配置
#define WATER_LEVEL_PIN A0

// 继电器配置
#define RELAY_PIN_1 5
#define RELAY_PIN_2 4

bool relay1State = false;
bool relay2State = false;

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
int value = 0;

// DHT传感器对象
DHT dht(DHTPIN, DHTTYPE);

// 继电器状态标志
bool relayState = false;

void setup() {
  // 设置双路继电器引脚为输出模式
  pinMode(RELAY_PIN_1, OUTPUT);
  pinMode(RELAY_PIN_2, OUTPUT);
  // 初始状态下关闭双路继电器
  digitalWrite(RELAY_PIN_1, HIGH);
  digitalWrite(RELAY_PIN_2, HIGH);
  
  Serial.begin(115200);
  setup_wifi();
  // 设置MQTT服务器地址和端口,并设置回调函数
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  // 初始化DHT11传感器
  dht.begin();
}

void setup_wifi() {
  delay(10);
  // 开始连接到指定的WiFi网络
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  // 循环等待直到连接到WiFi
  while (WiFi.status()!= WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// MQTT消息回调函数
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    Serial.print(" (ASCII: ");
    Serial.print((int)payload[i]);
    Serial.println(")");
  }
  Serial.println();
  
  // 正确的声明位置
  char* charPayload = new char[length + 1];
  for (int i = 0; i < length; i++) {
    charPayload[i] = (char)payload[i];
  }
  charPayload[length] = '\0';
  
  // 如果消息第一个字符是'1',打开内置LED
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on
  }
  else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off
  }
  
  // 检查是否是控制继电器的消息
  if (strcmp(topic, "relay_topic") == 0) {
    // 控制第一路继电器
    if (strcmp(charPayload, "relay1_on") == 0) {
      digitalWrite(RELAY_PIN_1, LOW);
      relay1State = true;
      Serial.println("Relay 1 is turned on");
    } else if (strcmp(charPayload, "relay1_off") == 0) {
      digitalWrite(RELAY_PIN_1, HIGH);
      relay1State = false;
      Serial.println("Relay 1 is turned off");
    }
    // 控制第二路继电器
    if (strcmp(charPayload, "relay2_on") == 0) {
      digitalWrite(RELAY_PIN_2, LOW);
      relay2State = true;
      Serial.println("Relay 2 is turned on");
    } else if (strcmp(charPayload, "relay2_off") == 0) {
      digitalWrite(RELAY_PIN_2, HIGH);
      relay2State = false;
      Serial.println("Relay 2 is turned off");
    }
  }
  delete[] charPayload;
}

void reconnect() {
  // 循环直到重新连接到MQTT服务器
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // 尝试连接到MQTT服务器
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      // 连接成功后,发布一条消息并订阅相关主题
      client.publish("outTopic", "hello world");
      client.subscribe("relay_topic");
      // 重新发布继电器状态(示例)
      if (relayState) {
        client.publish("relay_status", "relay_on");
      }
      else {
        client.publish("relay_status", "relay_off");
      }
    }
    else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // 等待5秒后重试连接
      delay(5000);
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  long now = millis();
  if (now - lastMsg > 2500) {
    lastMsg = now;
    ++value;
    // 获取温湿度数据
    float humidity = dht.readHumidity();
    float temperature = dht.readTemperature();
    if (!isnan(humidity) && !isnan(temperature)) {
      // 创建一个JSON文档对象,用于构建JSON数据
      StaticJsonDocument<200> jsonDoc;
      jsonDoc["temperature"] = temperature;
      jsonDoc["humidity"] = humidity;
      // 获取水位传感器数据并转换为百分比
      int waterLevelRaw = analogRead(WATER_LEVEL_PIN);
      int waterLevelPercentage = (waterLevelRaw * 100) / 1024;
      jsonDoc["waterLevelPercentage"] = waterLevelPercentage;
      // 分配足够的空间来存储JSON字符串
      char jsonMsg[200];
      serializeJson(jsonDoc, jsonMsg);
      Serial.print("Publish JSON message: ");
      Serial.println(jsonMsg);
      // 发布JSON格式的温湿度和水位百分比数据到MQTT主题
      client.publish("sensor/temperature_humidity_waterlevel", jsonMsg);
    }
  }
}

运行步骤

  1. 使用USB线将电脑与ESP8266开发板连接,确保供电和下载功能正常。
  2. 将上述代码烧录到ESP8266开发板中。
  3. 启动MQTT服务器(如EMQX),默认访问地址为http://127.0.0.1:18083/,默认账号密码为admin/public。
  4. 在MQTT客户端中订阅sensor/temperature_humidity_waterlevel主题,即可接收温湿度和水位数据。
  5. 若要控制继电器,向relay_topic主题发送relay1_onrelay1_off等指令。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号