关键词:ESP32、MQTT、Wi-Fi、物联网、EMQX、远程控制
项目源码GitHub 仓库


一、前言

在上一篇文章中,我实现了 ESP32 的 low power 优化,待机电流从 80mA 降到 2mA。但设备还是“离线”的——数据只能本地看,不能远程监控。

为了让设备真正“上云”,我给项目加上了 Wi-Fi 和 MQTT 功能。最终效果:

  • 光照数据每 3 秒上报到云端

  • 手机/电脑可以远程控制 LED 开关

  • 支持断线重连,稳定运行


二、方案选型

组件 选择 理由
Wi-Fi ESP32 内置 无需额外硬件
MQTT Broker EMQX 公共服务器 免费、稳定、无需注册
数据格式 JSON 通用、易解析
控制命令 纯文本 简单、轻量

三、代码实现

3.1 Wi-Fi 连接

c

#include "esp_wifi.h"
#include "esp_event.h"

#define WIFI_SSID      "你的WiFi名称"
#define WIFI_PASS      "你的WiFi密码"

static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } 
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        // 断线重连
        esp_wifi_connect();
    } 
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI("WIFI", "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
    }
}

static 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_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));
    
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
        },
    };
    
    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());
}

3.2 MQTT 连接与数据上报

c

#include "mqtt_client.h"

#define MQTT_BROKER_URI "mqtt://broker.emqx.io"

static esp_mqtt_client_handle_t mqtt_client = NULL;

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, 
                                int32_t event_id, void *event_data)
{
    esp_mqtt_event_handle_t event = event_data;
    
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI("MQTT", "MQTT connected");
            // 订阅控制主题
            esp_mqtt_client_subscribe(mqtt_client, "/esp32/light/control", 0);
            break;
            
        case MQTT_EVENT_DATA:
            // 处理远程控制命令
            if (strncmp(event->data, "LED_ON", event->data_len) == 0) {
                // 控制 LED 亮
            } else if (strncmp(event->data, "LED_OFF", event->data_len) == 0) {
                // 控制 LED 灭
            }
            break;
            
        default:
            break;
    }
}

void mqtt_publish_sensor_data(int voltage, int bright, const char* state)
{
    if (mqtt_client == NULL) return;
    
    char payload[128];
    snprintf(payload, sizeof(payload),
             "{\"voltage\":%d,\"bright\":%d,\"state\":\"%s\"}",
             voltage, bright, state);
    
    esp_mqtt_client_publish(mqtt_client, "/esp32/light/sensor", payload, 0, 1, 0);
}

3.3 集成到任务中

在 Sensor 任务中,每次采集完数据就调用上报函数:

c

void sensor_task(void *pvParameters)
{
    while (1) {
        // 采集光照数据...
        
        // 上报到云端
        mqtt_publish_sensor_data(voltage, is_bright, state_str);
        
        vTaskDelay(pdMS_TO_TICKS(3000));
    }
}

四、编译配置

在 CMakeLists.txt 中添加 MQTT 组件:

cmake

REQUIRES driver nvs_flash esp_timer freertos esp_wifi mqtt

五、测试验证

5.1 烧录运行

bash

idf.py build
idf.py -p COM3 flash monitor

串口输出:

text

I (xxx) WIFI: Got IP: 172.20.10.2
I (xxx) MQTT: MQTT connected
I (xxx) MQTT: Subscribed to /esp32/light/control
I (xxx) SENSOR_TASK: State: DARK, Voltage: 500mV

5.2 MQTT 客户端测试

  1. 下载 MQTTX 或 MQTT Explorer

  2. 连接到 broker.emqx.io:1883

  3. 订阅主题 /esp32/light/sensor,看到 JSON 数据:

json

{"voltage":500,"bright":0,"state":"DARK "}
  1. 发布 LED_ON 到 /esp32/light/control,LED 亮起 


六、踩坑记录

坑 1:Wi-Fi 和低功耗冲突

现象:进入 light sleep 后 Wi-Fi 频繁断开

原因:主动调用 esp_light_sleep_start() 会让 Wi-Fi 也暂停

解决:删除主动睡眠,配置电源管理让系统自动睡眠

c

esp_pm_config_esp32_t pm_config = {
    .light_sleep_enable = true,
    .max_freq_mhz = 80,
    .min_freq_mhz = 40,
};
esp_pm_configure(&pm_config);

坑 2:MQTT 发布 JSON 格式

现象:MQTTX 报 JSON 解析错误

原因:发送的是纯文本,但客户端默认用 JSON 模式

解决:在 MQTTX 里把 Payload Format 改成 Plaintext,或者保持 JSON 格式上报


七、总结

通过这次优化,我实现了:

功能 效果
Wi-Fi 连接 自动连接,断线重连
MQTT 数据上报 每 3 秒 JSON 格式上报
远程控制 LED_ON / LED_OFF 命令
电源管理 保持 Wi-Fi 的同时降低功耗

最终效果:设备从“本地系统”升级为“物联网系统”,可以远程监控和控制。


八、项目链接


九、参考资料


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐