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的几个核心概念:
通过整理我们这期介绍两种平台来如何使用 ESP32 通过 MQTT 协议向 MQTT 代理发送和接收数据:
-
Arduino IDE
-
VS Code + ESP-IDF
Arduino IDE
首先,我们需要安装Arduino开发环境:
基本的步骤:
-
将 ESP32 板连接到本地网络
-
确定好网络OK -
将 ESP32 连接到 MQTT 代理 -
将 MQTT 消息发布到 MQTT 主题
我们这里不做详细说明,有开发经验的朋友欢迎补充,具体的可以参考文末的链接【1】。
当然,我们把内部的代码贴在下方:
/** 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*/const char WIFI_SSID[] = "YOUR_WIFI_SSID"; // CHANGE TO YOUR WIFI SSIDconst char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // CHANGE TO YOUR WIFI PASSWORDconst char MQTT_BROKER_ADRRESS[] = "192.168.0.26"; // CHANGE TO MQTT BROKER'S IP ADDRESSconst int MQTT_PORT = 1883;const char MQTT_USERNAME[] = ""; // CHANGE IT IF REQUIREDconst char MQTT_PASSWORD[] = ""; // CHANGE IT IF REQUIRED// The MQTT topics that this device should publish/subscribeWiFiClient 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 brokermqtt.begin(MQTT_BROKER_ADRRESS, MQTT_PORT, network);// Create a handler for incoming messagesmqtt.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() functionif (mqtt.subscribe(SUBSCRIBE_TOPIC))Serial.print("ESP32 - Subscribed to the topic: ");elseSerial.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 sensorschar 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 作为客户端连接到 Mosquito MQTT 代理。 -
其次,我们将学习如何使用 ESP-IDF 中可用的 mqtt_client 库将 ESP32 连接到 MQTT 代理,订阅不同的主题,以及如何在不同的主题上发布消息。 -
为了演示,我们将使用 MQTTx 客户端桌面应用程序。我们将使用 MQTTx 订阅 MQTT 主题并发布消息。
static const char *TAG = "MQTT_EXAMPLE";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://esp32io.com/tutorials/esp32-mqtt
-
https://esp32tutorials.com/esp32-mqtt-client-publish-subscribe-esp-idf/
-
https://randomnerdtutorials.com/getting-started-with-esp32/
-
https://www.theengineeringprojects.com/2021/11/esp32-mqtt.html
-
https://microcontrollerslab.com/esp32-mqtt-publish-subscribe-arduino-ide/
-
https://www.arduino.cc/en/software/
-
【视频课程】Codesys V3.5系列入门课程(141人已学习) -
【视频课程】Codesys SoftMotion软运动控制基础课程(42人已学习) -
【视频课程】Codesys SoftMotion电子齿轮课程(14人已学习) -
【视频课程】Codesys SoftMotion电子凸轮CAM课程(9人已学习) -
【视频课程】Codesys Library自定义库的制作(23人已学习) -
——–END——–