ESP32-C3 应用 篇(实例一、通过MQTT协议连接ONENET上报传感器数据,云平台下发灯光调色)_esp32 实例(1)

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取

4.全彩RGB LED控制
ESP32-C3入门教程 基础篇(五、RMT应用 — SK6812全彩RGB LED灯驱动测试)

5.周期上报数据
ESP32-C3入门教程 基础篇(六、TIMG 硬件定时器 与 软件定时器)

6.WiFi配网
ESP32-C3入门教程 网络 篇(一、 Wi-Fi 使用入门 — 初始化及STA、AP模式)
ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)

7.MQTT连接云平台
ESP32-C3入门教程 网络 篇(三、 MQTT 协议基础介绍及测试)

我们还没有讲解 ESP-IDF 的工程结构,本文虽然是综合应用实例,目的在于实现一个完成的小项目实例,对于工程代码文件结构,规范性没有处理,示例是以简单的形式呈现,特此申明! 勿杠!

当初计划是使用阿里云,但是我想到自己的手机阿里云还是新用户,新用户会有采购优惠,不能浪费了= =, 所以为了优惠这里抛弃了阿里云,采用OneNet。

一、整体框架设计

首先明白,本实例的核心部分就是 MQTT 的通信,所以整体的框架是基于 MQTT 的Demo 进行修改,
在以此为基本框架的基础上增加我们需要的组件,功能,函数。

1.1 配网添加(Smart_config )

删除 MQTT Demo中关于配网的操作,使用 Smart_config 配网方式,直接拷贝 Smart_config Demo中的函数:
在这里插入图片描述
Smart_Config的初始化函数,回调函数,任务函数都直接复制Smart_config Demo中的即可,但是得注意 其中的任务smartconfig_example_task 配网结束后需要删除,节约空间,如下图:
在这里插入图片描述

1.2 周期上报数据(Timer)

周期上报数据使用硬件定时器方式,使能一个 自动重装载的定时器,在定时器中断函数中改变状态位,提醒需要上报数据,需要的代码比定时器 demo 中的简单,只需要需要的功能,如下:
在这里插入图片描述

1.3 光照度采集(ADC)

光照度采集使用的事ADC采样,只需要简单的在 主函数中使能了ADC,直接采用单次采样的方式,加上一下数据处理,结合上面的定时器,就能实现一个周期上报功能:
在这里插入图片描述

测试效果:
在这里插入图片描述

1.4 温湿度采集(I2C)

温湿度的采集,还是根据 ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)中的内容,添加对应的 sht21.c 和 sht21.h 文件,然后在周期任务处调用测试:
在这里插入图片描述
测试效果:
在这里插入图片描述

1.5 按键(GPIO)

按键操作目的在于,当产品需要配网的时候,手动删除以前的配网信息,按键的操作在
ESP32-C3入门教程 基础篇(二、GPIO中断、按键驱动测试) 有过说明,同时在 ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)也有过说明,这里主要的用法和Wi-Fi配网教学篇中的一样,按键会主动删除曾经有过的配网信息,导致产品重新进入配网:
在这里插入图片描述
测试效果:
在这里插入图片描述
重启以后重新配网能够回归正常。

完成程序的框架设计搭建,接下来就要进场云平台的产品创建。

二、ONENET平台设置

在 OneNET平台,进入控制台,找到对应的MQTT 物联网套件:
在这里插入图片描述

2.1 添加产品 和设备

在这里插入图片描述

产品添加成功,此时可以点击如下图片立即添加设备:
在这里插入图片描述

如果当时没有立即添加,可以在产品概况的(左边栏目),设备列表里面找到关于设备的相关信息,进行添加设备:
在这里插入图片描述

添加完成后,可以看到设备离线,然后一些基本信息:
在这里插入图片描述

2.2 为设备添加数据流

找到设备
在这里插入图片描述

2.3 云平台协议参数说明

前面完成了云平台的设置,我们可以通过PC客户端先对云平台进行一个测试,在这之前,需要先了解一下ONENET MQTT协议规范的基本介绍,通过如下网站可以查找到所有需要的ONENET MQTT介绍:

OneNET MQTT 协议规范文档说明
在这里插入图片描述

2.3.1 ONENET MQTT服务器地址
mqtts.heclouds.com 	 1883

OneNET MQTT 服务器地址

在这里插入图片描述

2.3.2 clientld、username、password

在这里插入图片描述
更加详细的介绍如下图:
在这里插入图片描述

2.3.3 password 获取方法

连接除了clientld、username,还需要password 。 ONENET的 password 需要使用费 token 算法 获取:

ONENET token 算法说明
ONENET token工具下载
在这里插入图片描述
1、products/产品ID/devices/设备名称
在这里插入图片描述
2、时间戳

通过这个的工具获取: 在线 时间戳转换工具

在这里插入图片描述
填入工具之中:
在这里插入图片描述
3、key
在这里插入图片描述
4、生成密码
在这里插入图片描述

通过 MQTT.fx 配置连接云平台,按照如下配置进行设置:

在这里插入图片描述

配置完成以后,点击connect,在ONENET上可以看到设备在线状态:
在这里插入图片描述

2.4 订阅Topic

ONENET平台 与设备 Topic 的约定,不能随意的定义自己的Topic,有对应的规定:
在这里插入图片描述
有如下一些Topic:
在这里插入图片描述
比如,我们订阅一个上报结果,类似如图所示:
在这里插入图片描述

2.5 发送数据至云平台

我们上面完成了数据上报结果订阅,那么有关于任何数据点上报的结果,我们都能收到消息,我们使用工具来尝试一下给平台发送数据:
在这里插入图片描述
在 MQTT.fx 中,数据格式使用 Json 格式发送:
在这里插入图片描述

点击发布,我们可以通过订阅的消息看到消息已经发送,在云平台也能看到数据上报成功:
在这里插入图片描述

2.6 云平台下发命令

接收平台下发的命令,就是订阅设备所有命令相关消息:
在这里插入图片描述

在云平台点击下发命令,如下图,然后写入cmd,在MQTT.fx 中我们订阅过消息,所以能够收到命令:
在这里插入图片描述
测试完成,到时候我们将会使用这个命令来控制板子上的RGB灯。

三、整体调整测试

3.1 结合平台的基本调整

在前面其实有提到过 topic 的说明,设备发布消息到非法topic ,平台会断开设备连接:
在这里插入图片描述

所以在整体修改的过程中需要注意,不要有其他的无用的测试Topic 。

在前面修改完成的整体程序框架中,根据平台的测试结果,修改一些必要的地方:

一些基本的定义:
在这里插入图片描述MQTT配置部分代码:
在这里插入图片描述
周期上报的逻辑:
在这里插入图片描述

3.2 .url 和 .host

在此期间测试有一个问题:
在这里插入图片描述
实际上这里有个概念没有搞清楚:
在这里插入图片描述

此处的内容可参考博文:网址(url),域名,ip地址,dns,hosts之间的关系

3.3 周期上报效果

最终测试结果,周期上报板子上传感器数值,在云平台可以看到周期上报的结果:

在这里插入图片描述
在这里插入图片描述

3.4 下行命令处理(RMT应用)

下行命令处理,我们这里是基于订阅了云平台的 CMD 命令,但是对于这个下行的命令,目前看到也并没有一个标准的格式指定。这里目的是为了演示,所以我们怎么简单怎么来。
我们自己把下行需要处理的命令格式定位: mycmd:XXXXX。
比如:mycmd:ledred mycmd:ledblue。
这样,我们通过接受到的消息经常简单的数据处理以后,做出对应的动作。
(具体的执行可参考源码)
在这里插入图片描述

测试结果, 切换成蓝灯:

在这里插入图片描述

测试结果,切换成红灯:
在这里插入图片描述

附录(源码)

这里上一下app_main.c文件源码,其实只要看过我的教学博文,下面这个文件的代码都是有分析说明的,包括本文上面也对每个部分的功能有单独说明。整个应用工程的代码,我上传到了资源:

本博文工程源码

app_main.c

/\* MQTT (over TCP) Example

 This example code is in the Public Domain (or CC0 licensed, at your option.)

 Unless required by applicable law or agreed to in writing, this
 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 CONDITIONS OF ANY KIND, either express or implied.
\*/

#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"
/\*
smartconfig
\*/
#include "esp\_smartconfig.h" 
#include "freertos/event\_groups.h"
// #include "esp\_wpa2.h"
/\*
定时器
\*/
#include "driver/timer.h" 
/\*
ADC
\*/
#include "driver/adc.h"
#include "driver/gpio.h" 
/\*
I2C
\*/  
#include "sht21.h"
/\*
button
\*/
#include "my\_button.h"
/\*
RMT
\*/
#include "driver/rmt.h"
#include "led\_strip.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"

#define TIMER\_SCALE (TIMER\_BASE\_CLK / 16) // convert counter value to seconds


#define ONENET\_MqttServer "mqtts.heclouds.com"

#define ONENET\_clientld "esp32-device1" //name
#define ONENET\_UserName "493136" //ID
#define ONENET\_Password "version=2018-10-31&res=products%2F493136%2Fdevices%2Fesp32-device1&et=1741490120&method=md5&sign=wscxn0OWnKxbxQ7mae3CLQ%3D%3D"

//设备上传数据的post主题
#define ONENET\_TOPIC\_PROP\_POST "$sys/" ONENET\_UserName "/" ONENET\_clientld "/dp/post/json"

#define ONENET\_TOPIC\_DP\_Publish "$sys/493136/esp32-device1/dp/post/json"
#define ONENET\_TOPIC\_DP\_Sub "$sys/493136/esp32-device1/dp/post/json/+"
#define ONENET\_TOPIC\_CMD\_Sub "$sys/493136/esp32-device1/cmd/#"

//这是post上传数据使用的模板
#define ONENET\_POST\_BODY\_FORMAT "{\"id\":123,\"dp\":%s}"

static EventGroupHandle_t s_wifi_event_group;

static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char \*TAG = "MQTT";
static const char \*TAG2 = "smartconfig";

// static EventGroupHandle\_t s\_cmd\_event\_group;
static const int RED_BIT = BIT3;
static const int BLUE_BIT = BIT4;

bool send_cycle = false;

typedef struct {
    int timer_group;
    int timer_idx;
    int alarm_interval;
    bool auto_reload;
} example\_timer\_info\_t;

#define RMT\_TX\_NUM 8 //WS2812 control pin
#define RMT\_TX\_CHANNEL RMT\_CHANNEL\_0
#define EXAMPLE\_CHASE\_SPEED\_MS (10)
#define LED\_STRIP\_NUM 1
#define COLOR\_RED 9
#define COLOR\_GREE 8
#define COLOR\_BULE 10
#define COLOR\_PURPLE 11
#define COLOR\_ORANGE 12

#define Lamp\_Open 13
#define lamp\_close 14
#define lamp\_speed\_Up 15
#define lamp\_speed\_down 16

#define ligth\_down 18
#define ligth\_up 19
struct WS2812\_COLOR
{
	uint8\_t lamp;
	uint8\_t ligth_rank;
	uint8\_t lamp_speed;
	uint32\_t red;
	uint32\_t green;
	uint32\_t blue;
};

static led\_strip\_t \*strip;

struct WS2812\_COLOR WS2812_RGB;

/\*\*
 \* @brief A sample structure to pass events from the timer ISR to task
 \*
 \*/
typedef struct {
    example\_timer\_info\_t info;
    uint64\_t timer_counter_value;
} example\_timer\_event\_t;



static void smartconfig\_example\_task(void \* parm);
static void led\_cmd\_task(void \* parm);

void RGB16for10(struct WS2812\_COLOR \*RGB, uint32\_t reb_16)
{
	uint32\_t rgb_16 = reb_16;
	RGB->blue = rgb_16 & 0Xff;

	rgb_16 = rgb_16 >> 8;
	RGB->green = rgb_16 & 0xff;

	rgb_16 = rgb_16 >> 8;

	RGB->red = rgb_16 & 0xff;
}

void set\_rgb(uint32\_t rgb_24bit, uint8\_t ligth_rank)
{
	RGB16for10(&WS2812_RGB, rgb_24bit);
	ligth_rank = 21 - ligth_rank;
	for (int i = 0; i < LED_STRIP_NUM; i++)
	{
		strip->set\_pixel(strip, i, WS2812_RGB.red / ligth_rank, WS2812_RGB.green / ligth_rank, WS2812_RGB.blue / ligth_rank);
	}

	strip->refresh(strip, 10);
}

void init\_led()
{
	rmt\_config\_t config = RMT\_DEFAULT\_CONFIG\_TX(RMT_TX_NUM, RMT_TX_CHANNEL);
	// set counter clock to 40MHz
	config.clk_div = 2;
	ESP\_ERROR\_CHECK(rmt\_config(&config));
	ESP\_ERROR\_CHECK(rmt\_driver\_install(config.channel, 0, 0));

	// install ws2812 driver
	led\_strip\_config\_t strip_config = LED\_STRIP\_DEFAULT\_CONFIG(1, (led\_strip\_dev\_t)config.channel);
	strip = led\_strip\_new\_rmt\_ws2812(&strip_config);
	if (!strip)
	{
		ESP\_LOGE(TAG, "install WS2812 driver failed");
	}
	// Clear LED strip (turn off all LEDs)
	ESP\_ERROR\_CHECK(strip->clear(strip, 100));
    
}


static void log\_error\_if\_nonzero(const char \* message, int error_code)
{
    if (error_code != 0) {
        ESP\_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

static int single\_read(void \*arg)
{
    int adc1_reading[1] = {0};
    adc1_reading[0] = adc1\_get\_raw(ADC1_CHANNEL_0);
    // vout = (adc1\_reading[0] \* 2500.00)/4095.00;
    // ESP\_LOGI(TAG\_CH[0], "%x vout mv is %f", adc1\_reading[0],vout);
    return  adc1_reading[0];
}


static bool IRAM_ATTR system\_timer\_callback(void\* arg)
{
    BaseType_t high_task_awoken = pdFALSE;
    send_cycle = true;
    return high_task_awoken == pdTRUE; // return whether we need to yield at the end of ISR
}

static void 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) {
        xTaskCreate(smartconfig_example_task, "smartconfig\_example\_task", 4096, NULL, 3, NULL);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp\_wifi\_connect();
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
        ESP\_LOGI(TAG2, "Scan done");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP\_LOGI(TAG2, "Found channel");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
        ESP\_LOGI(TAG2, "Got SSID and password");

        smartconfig\_event\_got\_ssid\_pswd\_t \*evt = (smartconfig\_event\_got\_ssid\_pswd\_t \*)event_data;
        wifi\_config\_t wifi_config;
        uint8\_t ssid[33] = { 0 };
        uint8\_t password[65] = { 0 };
        uint8\_t rvd_data[33] = { 0 };

        bzero(&wifi_config, sizeof(wifi\_config\_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if (wifi_config.sta.bssid_set == true) {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        ESP\_LOGI(TAG2, "SSID:%s", ssid);
        ESP\_LOGI(TAG2, "PASSWORD:%s", password);
        if (evt->type == SC_TYPE_ESPTOUCH_V2) {
            ESP\_ERROR\_CHECK( esp\_smartconfig\_get\_rvd\_data(rvd_data, sizeof(rvd_data)) );
            ESP\_LOGI(TAG2, "RVD\_DATA:");
            for (int i=0; i<33; i++) {
                printf("%02x ", rvd_data[i]);
            }
            printf("\n");
        }

        ESP\_ERROR\_CHECK( esp\_wifi\_disconnect() );
        ESP\_ERROR\_CHECK( esp\_wifi\_set\_config(WIFI_IF_STA, &wifi_config) );
        printf("ready to connect!\r\n");
        esp\_wifi\_connect();
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
        xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
    }
}

static esp\_err\_t mqtt\_event\_handler\_cb(esp\_mqtt\_event\_handle\_t event)
{
    esp\_mqtt\_client\_handle\_t client = event->client;
    int msg_id;
    char cmdbuf[20];
    // your\_context\_t \*context = event->context;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP\_LOGI(TAG, "MQTT\_EVENT\_CONNECTED");
            // msg\_id = esp\_mqtt\_client\_publish(client, "/topic/qos1", "data\_3", 0, 1, 0);
            // ESP\_LOGI(TAG, "sent publish successful, msg\_id=%d", msg\_id);


![img](https://img-blog.csdnimg.cn/img_convert/67c71fdb9edc231498e0cac2b2f09d00.png)
![img](https://img-blog.csdnimg.cn/img_convert/50570adff26ce8b2c6096e6c10ce8ca7.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

_EVENT_CONNECTED:
            ESP\_LOGI(TAG, "MQTT\_EVENT\_CONNECTED");
            // msg\_id = esp\_mqtt\_client\_publish(client, "/topic/qos1", "data\_3", 0, 1, 0);
            // ESP\_LOGI(TAG, "sent publish successful, msg\_id=%d", msg\_id);


[外链图片转存中...(img-NwF6XU6a-1715870390168)]
[外链图片转存中...(img-AiQQZstB-1715870390168)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

ESP32主板控制器支持WiFi和蓝牙双模通信,外围兼容低功耗硬件设计,深度睡眠模式下功耗仅为10uA。主控器支持USB和外接3.7V锂电池两种供电方式,可实现双电源下自动切换电源功能,并支持USB和外接DC两种充电方式。体积小巧,接口方便,上手简单,可直接应用物联网低功耗项目。 在编程方面,ESP32主板控制器支持Arduino、idf(linux)、micropython等多种方式,并且,对于Arduino IDE做了引脚映射,可以直接传递Dx来配置引脚,使用方式上兼容UNO,从而降低了使用的门槛。 请注意:ESP32仍然针对开发人员,并不是所有的外设都具有示例代码的完整功能,还有一些bug需要被发现和修复。在Arduino IDE下,IO管脚功能以及I2C/SPI可以直接调用,其他功能依旧在开发中。 实物截图: 技术规格: 工作电压:3.3V 输入电压:3.3V~5V 支持低功耗:10uA 支持最大放电电流:600mA@3.3V LDO 支持最大充电电流:500mA 支持USB充电 处理器:Tensilica LX6双核处理器(一核处理高速连接;一核独立应用开发) 主频:240MHz SRAM:520KB Flash:16Mbit Wi-Fi标准:FCC/CE/TELEC/KCC Wi-Fi协议:802.11 b/g/n/d/e/i/k/r (802.11n,速度高达150 Mbps),A-MPDU和A-MSDU聚合,支持0.4us防护间隔 频率范围:2.4~2.5 GHz 蓝牙协议:符合蓝牙v4.2 BR/EDR和BLE标准 蓝牙音频:CVSD和SBC音频低功耗:10uA 工作电流:80mA(平均) 频率范围:2.4~2.5GHz 支持Arduino一键下载 支持micropython 片上时钟:40MHz晶振、32.768KHz晶振 数字I/O:10(arduino默认) 模拟输入:5(arduino默认) SPI:1(arduino默认) I2C:1(arduino默认) I2S:1(arduino默认) LED_BUILTIN:D9 接口方式:FireBeetle系列兼容 工作温度:-40℃~+85℃ 模块尺寸:24 × 53(mm)/0.94 x 2.09(inches) 安装孔尺寸:内径3.1mm/外径6mm 可能感兴趣的项目设计: ESP32 兼容WiFi开发板应用及资料开源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值