赞
踩
既有适合小白学习的零基础资料,也有适合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 进行修改,
在以此为基本框架的基础上增加我们需要的组件,功能,函数。
删除 MQTT Demo中关于配网的操作,使用 Smart_config 配网方式,直接拷贝 Smart_config Demo中的函数:
Smart_Config的初始化函数,回调函数,任务函数都直接复制Smart_config
Demo中的即可,但是得注意 其中的任务smartconfig_example_task
配网结束后需要删除,节约空间,如下图:
周期上报数据使用硬件定时器方式,使能一个 自动重装载的定时器,在定时器中断函数中改变状态位,提醒需要上报数据,需要的代码比定时器 demo 中的简单,只需要需要的功能,如下:
光照度采集使用的事ADC采样,只需要简单的在 主函数中使能了ADC,直接采用单次采样的方式,加上一下数据处理,结合上面的定时器,就能实现一个周期上报功能:
测试效果:
温湿度的采集,还是根据 ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)中的内容,添加对应的 sht21.c 和 sht21.h 文件,然后在周期任务处调用测试:
测试效果:
按键操作目的在于,当产品需要配网的时候,手动删除以前的配网信息,按键的操作在
ESP32-C3入门教程 基础篇(二、GPIO中断、按键驱动测试) 有过说明,同时在 ESP32-C3入门教程 网络 篇(二、 Wi-Fi 配网 — Smart_config方式 和 BlueIF方式)也有过说明,这里主要的用法和Wi-Fi配网教学篇中的一样,按键会主动删除曾经有过的配网信息,导致产品重新进入配网:
测试效果:
重启以后重新配网能够回归正常。
完成程序的框架设计搭建,接下来就要进场云平台的产品创建。
在 OneNET平台,进入控制台,找到对应的MQTT 物联网套件:
产品添加成功,此时可以点击如下图片立即添加设备:
如果当时没有立即添加,可以在产品概况的(左边栏目),设备列表里面找到关于设备的相关信息,进行添加设备:
添加完成后,可以看到设备离线,然后一些基本信息:
找到设备
前面完成了云平台的设置,我们可以通过PC客户端先对云平台进行一个测试,在这之前,需要先了解一下ONENET MQTT协议规范的基本介绍,通过如下网站可以查找到所有需要的ONENET MQTT介绍:
mqtts.heclouds.com 1883
更加详细的介绍如下图:
连接除了clientld、username,还需要password 。 ONENET的 password 需要使用费 token 算法 获取:
ONENET token 算法说明
ONENET token工具下载
1、products/产品ID/devices/设备名称
2、时间戳
通过这个的工具获取: 在线 时间戳转换工具
填入工具之中:
3、key
4、生成密码
通过 MQTT.fx 配置连接云平台,按照如下配置进行设置:
配置完成以后,点击connect,在ONENET上可以看到设备在线状态:
ONENET平台 与设备 Topic 的约定,不能随意的定义自己的Topic,有对应的规定:
有如下一些Topic:
比如,我们订阅一个上报结果,类似如图所示:
我们上面完成了数据上报结果订阅,那么有关于任何数据点上报的结果,我们都能收到消息,我们使用工具来尝试一下给平台发送数据:
在 MQTT.fx 中,数据格式使用 Json 格式发送:
点击发布,我们可以通过订阅的消息看到消息已经发送,在云平台也能看到数据上报成功:
接收平台下发的命令,就是订阅设备所有命令相关消息:
在云平台点击下发命令,如下图,然后写入cmd,在MQTT.fx 中我们订阅过消息,所以能够收到命令:
测试完成,到时候我们将会使用这个命令来控制板子上的RGB灯。
在前面其实有提到过 topic 的说明,设备发布消息到非法topic ,平台会断开设备连接:
所以在整体修改的过程中需要注意,不要有其他的无用的测试Topic 。
在前面修改完成的整体程序框架中,根据平台的测试结果,修改一些必要的地方:
一些基本的定义:
MQTT配置部分代码:
周期上报的逻辑:
在此期间测试有一个问题:
实际上这里有个概念没有搞清楚:
此处的内容可参考博文:网址(url),域名,ip地址,dns,hosts之间的关系
最终测试结果,周期上报板子上传感器数值,在云平台可以看到周期上报的结果:
下行命令处理,我们这里是基于订阅了云平台的 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);   **既有适合小白学习的零基础资料,也有适合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)**
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。