前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ESP32与MQTT:物联网通信的完美搭档

ESP32与MQTT:物联网通信的完美搭档

作者头像
Hello工控
发布于 2025-06-08 07:55:01
发布于 2025-06-08 07:55:01
35100
代码可运行
举报
文章被收录于专栏:Hello工控Hello工控
运行总次数:0
代码可运行

ESP32 是由 Espressif 开发的一系列低成本低功耗系统级芯片(SoC)微控制器,包括 Wi-Fi 和蓝牙无线功能以及双核处理器。如果你熟悉 ESP8266,那么 ESP32 就是它的继任者,拥有许多新功能。

物联网领域,基于ESP32开发是一个非常不错的选择,广泛用于智能家居、智能农业及工业物联网等行业。

图片
图片

MQTT作为物联网通信技术的首选,两者结合,简直完美!我们这期讨论如何在ESP32中应用MQTT?

图片
图片

ESP32

为什么要使用ESP32,以下是它的主要优点:

  • 低成本
  • 价格实惠:在几大电商平台,可以以几十块的价格购买 ESP32,这使其对普通公众来说非常容易获取。
  • 高性能处理能力
    • 双核处理器:ESP32 配备了双核 Xtensa LX6 微处理器,主频高达 240MHz,能够同时处理多个任务,提高系统的响应速度和效率。例如,在复杂的传感器数据处理和通信任务中,双核可以分别处理不同的任务,一个核心处理传感器数据采集,另一个核心处理网络通信,互不干扰。
    • 丰富的外设接口:它支持多种外设接口,如 SPI、I2C、UART、I2S 等,可以方便地连接各种传感器、存储器和其他外设,满足不同应用场景的需求。
  • 强大的无线通信能力
    • Wi-Fi 和蓝牙双模:ESP32 支持 2.4GHz 802.11 b/g/n Wi-Fi 和蓝牙 4.2 BLE,能够实现高速无线数据传输和低功耗蓝牙通信。这使得设备可以通过 Wi-Fi 连接到互联网,同时利用蓝牙与其他设备进行近距离通信,如智能手机、智能手表等。
    • 良好的网络连接性:它支持多种网络协议,如 TCP/IP、HTTP、MQTT 等,可以方便地与云平台或其他物联网设备进行通信,实现设备之间的数据交互和协同工作。
  • 低功耗设计
    • 多种低功耗模式:ESP32 提供了多种低功耗模式,如睡眠模式、深度睡眠模式和轻睡眠模式,可以根据不同的应用场景和任务需求灵活选择,有效降低设备的功耗。例如,在传感器节点中,设备可以在大部分时间处于深度睡眠模式,仅在需要采集数据和传输数据时唤醒,大大延长了电池的使用寿命。
    • 高效的电源管理:它内置了高效的电源管理系统,能够自动调节芯片的工作电压和电流,进一步降低功耗。这对于需要长时间运行且依赖电池供电的物联网设备来说非常重要。
  • 高集成度和小尺寸
    • 高度集成:ESP32 将微处理器、无线通信模块、多种外设接口和电源管理等功能集成在一个芯片上,大大减少了外部元件的数量和电路板的面积,降低了硬件成本和设计复杂度。
    • 小尺寸封装:它采用了多种小尺寸封装形式,如 QFN、BGA 等,适合用于对空间要求较高的小型物联网设备,如智能手环、智能标签等。
  • 丰富的开发资源和社区支持
    • 开源开发环境:Espressif 提供了开源的开发环境,如 ESP-IDF(Espressif IoT Development Framework),支持多种编程语言,如 C、Python 等,方便开发者进行开发和调试。
    • 强大的社区支持:ESP32 拥有一个活跃的开发者社区,社区成员分享了大量的代码示例、开发经验和解决方案,开发者可以方便地获取技术支持和帮助,加速开发进程。
图片
图片

ESP32如何应用MQTT?

我们在应用之前,首先要了解MQTT的几个核心概念:

MQTT通信的核心:Topic主题

MQTT发布和订阅架构

MQTT 客户端和MQTT 代理!!!

图片
图片

通过整理我们这期介绍两种平台来如何使用 ESP32 通过 MQTT 协议向 MQTT 代理发送和接收数据:

图片
图片
  • Arduino IDE
  • VS Code + ESP-IDF
图片
图片

Arduino IDE

首先,我们需要安装Arduino开发环境:

图片
图片

基本的步骤:

  • 将 ESP32 板连接到本地网络
  • 确定好网络OK
  • 将 ESP32 连接到 MQTT 代理
  • 将 MQTT 消息发布到 MQTT 主题
图片
图片

我们这里不做详细说明,有开发经验的朋友欢迎补充,具体的可以参考文末的链接【1】。

当然,我们把内部的代码贴在下方:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 * This ESP32 code is created by esp32io.com
 *
 * This ESP32 code is released in the public domain
 *
 * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-mqtt
 */

#include <WiFi.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>

#define CLIENT_ID "ESP32-001"  // CHANGE IT AS YOU DESIRE

const char WIFI_SSID[] = "YOUR_WIFI_SSID";              // CHANGE TO YOUR WIFI SSID
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";           // CHANGE TO YOUR WIFI PASSWORD
const char MQTT_BROKER_ADRRESS[] = "192.168.0.26";  // CHANGE TO MQTT BROKER'S IP ADDRESS
const int MQTT_PORT = 1883;
const char MQTT_USERNAME[] = "";  // CHANGE IT IF REQUIRED
const char MQTT_PASSWORD[] = "";  // CHANGE IT IF REQUIRED

// The MQTT topics that this device should publish/subscribe
#define PUBLISH_TOPIC "esp32-001/send"
#define SUBSCRIBE_TOPIC "esp32-001/receive"

#define PUBLISH_INTERVAL 5000  // 4 seconds

WiFiClient network;
MQTTClient mqtt = MQTTClient(256);

unsigned long lastPublishTime = 0;

void setup() {
  Serial.begin(9600);

  // set the ADC attenuation to 11 dB (up to ~3.3V input)
  analogSetAttenuation(ADC_11db);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.println("ESP32 - Connecting to Wi-Fi");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  connectToMQTT();
}

void loop() {
  mqtt.loop();

  if (millis() - lastPublishTime > PUBLISH_INTERVAL) {
    sendToMQTT();
    lastPublishTime = millis();
  }
}

void connectToMQTT() {
  // Connect to the MQTT broker
  mqtt.begin(MQTT_BROKER_ADRRESS, MQTT_PORT, network);

  // Create a handler for incoming messages
  mqtt.onMessage(messageHandler);

  Serial.print("ESP32 - Connecting to MQTT broker");

  while (!mqtt.connect(CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();

  if (!mqtt.connected()) {
    Serial.println("ESP32 - MQTT broker Timeout!");
    return;
  }

  // Subscribe to a topic, the incoming messages are processed by messageHandler() function
  if (mqtt.subscribe(SUBSCRIBE_TOPIC))
    Serial.print("ESP32 - Subscribed to the topic: ");
  else
    Serial.print("ESP32 - Failed to subscribe to the topic: ");

  Serial.println(SUBSCRIBE_TOPIC);
  Serial.println("ESP32  - MQTT broker Connected!");
}

void sendToMQTT() {
  StaticJsonDocument<200> message;
  message["timestamp"] = millis();
  message["data"] = analogRead(0);  // Or you can read data from other sensors
  char messageBuffer[512];
  serializeJson(message, messageBuffer);

  mqtt.publish(PUBLISH_TOPIC, messageBuffer);

  Serial.println("ESP32 - sent to MQTT:");
  Serial.print("- topic: ");
  Serial.println(PUBLISH_TOPIC);
  Serial.print("- payload:");
  Serial.println(messageBuffer);
}

void messageHandler(String &topic, String &payload) {
  Serial.println("ESP32 - received from MQTT:");
  Serial.println("- topic: " + topic);
  Serial.println("- payload:");
  Serial.println(payload);

  // You can process the incoming data as json object, then control something
  /*
  StaticJsonDocument<200> doc;
  deserializeJson(doc, payload);
  const char* message = doc["message"];
  */
}

上述ESP32 代码的作用是:

  • 连接到 MQTT 代理
  • 订阅一个主题
  • 定期发布消息到另一个主题
图片
图片

VS CODE+ESP-IDF

下面我们将介绍如何使用 ESP32 作为 ESP-IDF mqtt_client 库的 MQTT 客户端。

图片
图片

主要的步骤:

  • 首先,我们将看到如何将 ESP32 作为客户端连接到 Mosquito MQTT 代理。
  • 其次,我们将学习如何使用 ESP-IDF 中可用的 mqtt_client 库将 ESP32 连接到 MQTT 代理,订阅不同的主题,以及如何在不同的主题上发布消息。
  • 为了演示,我们将使用 MQTTx 客户端桌面应用程序。我们将使用 MQTTx 订阅 MQTT 主题并发布消息。

我们将在 Raspberry Pi 上安装 Mosquitto MQTT 代理,但你也可以在你的 WindowsLinux 机器上安装它。当然,也可以选择其他的代理:

Top 5 免费开源MQTT Brokers代理!!!

详细的步骤可参考文末的链接【2】,我们这里把主题代码贴在下方:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "esp_log.h"
#include "mqtt_client.h"
static const char *TAG = "MQTT_EXAMPLE";
#define  EXAMPLE_ESP_WIFI_SSID "YOUR_SSID"
#define  EXAMPLE_ESP_WIFI_PASS "YOUR_PASSWORD"

uint32_t MQTT_CONNEECTED = 0;
static void mqtt_app_start(void);
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    switch (event->event_id)
    {
    case SYSTEM_EVENT_STA_START:
        esp_wifi_connect();
        ESP_LOGI(TAG, "Trying to connect with Wi-Fi\n");
        break;
    case SYSTEM_EVENT_STA_CONNECTED:
        ESP_LOGI(TAG, "Wi-Fi connected\n");
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        ESP_LOGI(TAG, "got ip: startibg MQTT Client\n");
        mqtt_app_start();
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        ESP_LOGI(TAG, "disconnected: Retrying Wi-Fi\n");
        esp_wifi_connect();
        break;
    default:
        break;
    }
    return ESP_OK;
}
void wifi_init(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .password = EXAMPLE_ESP_WIFI_PASS,
	     .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start());
}
/*
 * @brief Event handler registered to receive MQTT events
 *
 *  This function is called by the MQTT client event loop.
 *
 * @param handler_args user data registered to the event.
 * @param base Event base for the handler(always MQTT Base in this example).
 * @param event_id The id for the received event.
 * @param event_data The data for the event, esp_mqtt_event_handle_t.
 */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        MQTT_CONNEECTED=1;

        msg_id = esp_mqtt_client_subscribe(client, "/topic/test1", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        msg_id = esp_mqtt_client_subscribe(client, "/topic/test2", 1);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        MQTT_CONNEECTED=0;
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}
esp_mqtt_client_handle_t client = NULL;
static void mqtt_app_start(void)
{
    ESP_LOGI(TAG, "STARTING MQTT");
    esp_mqtt_client_config_t mqttConfig = {
        .uri = "mqtt://192.168.1.4:1883"};

    client = esp_mqtt_client_init(&mqttConfig);
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
    esp_mqtt_client_start(client);
}
void Publisher_Task(void *params)
{
  while (true)
  {
    if(MQTT_CONNEECTED)
    {
        esp_mqtt_client_publish(client, "/topic/test3", "Helllo World", 0, 0, 0);
        vTaskDelay(15000 / portTICK_PERIOD_MS);
    }
  }
}
void app_main(void)
{
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    wifi_init();
    xTaskCreate(Publisher_Task, "Publisher_Task", 1024 * 5, NULL, 5, NULL);
}

详细代码:

https://github.com/ESP32Tutorials/esp32-mqtt-pub-sub-esp-idf

关于本期内容,重要是实践,要完全搞懂这些,可以参考下方详细的链接,包含上述没有细化的内容。

参考链接:

  1. https://esp32io.com/tutorials/esp32-mqtt
  2. https://esp32tutorials.com/esp32-mqtt-client-publish-subscribe-esp-idf/
  3. https://randomnerdtutorials.com/getting-started-with-esp32/
  4. https://www.theengineeringprojects.com/2021/11/esp32-mqtt.html
  5. https://microcontrollerslab.com/esp32-mqtt-publish-subscribe-arduino-ide/
  6. https://www.arduino.cc/en/software/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hello工控 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验