Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
2024-RSOC
【2024-RSOC】DAY5:星火一号+阿里云开发
发布于 2024-07-27 21:57:41 浏览:129
订阅该版
[tocm] ## 软件包的来源 我们在配置RT-Thread时总会需要一些软件包,这些软件包来自[RT-Thread 软件包中心](https://packages.rt-thread.org/index.html)。 ![image-20240726232414633.png](https://oss-club.rt-thread.org/uploads/20240727/57876f7d789ccf792024916c02de6511.png.webp) ## 相关知识学习:MQTT 软件包仓库提供了支持阿里云的MQTT协议的软件包`ali-iotkit`。 MQTT协议为一种轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎,能够实现传感器、执行器和其它设备之间的高效通信。 ![MQTT运行框架.png](https://oss-club.rt-thread.org/uploads/20240727/980ceeee9d115f5cf033f6152de0c53f.png.webp) 注意几个名词: **Client:**客户端,即我们使用的设备。 **Server:**服务端 **Topic Name:**主题名,附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。 **Subscription:** 订阅,订阅相应的主题名来获取对应的信息。 **Publish:**发布,在对应主题上发布新的消息。 这里我们使用阿里云[物联网平台](https://www.aliyun.com/product/iot/iot_instc_public_cn)搭建Demo ![image-20240725184110285.png](https://oss-club.rt-thread.org/uploads/20240727/79c9e84ced6bacba0b4f7fe474718109.png.webp) 登录后进入控制台,执行以下步骤: + 开通公共实例 + 创建产品 + 创建设备 > 这里的产品名称,设备名称、类型等可以随便填写。 ## 相关知识学习:温湿度传感器AHT21 星火一号开发板板载温湿度传感器AHT21,采用I2C方式传输数据。 启动该扩展需要执行以下操作: + 启动板载AHT21 ![image-20240727175926294.png](https://oss-club.rt-thread.org/uploads/20240727/2aeea698adbdd3d1078a9bddf2b7c3ea.png.webp) + 使能kprintf-full软件包(为了输出浮点数) ![image-20240727200214737.png](https://oss-club.rt-thread.org/uploads/20240727/3d1cdd614438c4f3b2ee324f5c7eeaf0.png.webp) 首先,根据AHT10的软件包,我们研究了AHT10的读取流程: 初始化:`aht10_init(AHT10_I2C_BUS)`,同时获取设备句柄 读取温湿度: ```c float Humi = aht10_read_humidity(Dev); float Temp = aht10_read_temperature(Dev); ``` ## 相关知识学习:文件系统 星火一号板载一个W25Q64,本篇文章中将采用该FLASH进行Demo制作。 RT-Thread使用DFS来构建文件虚拟系统,全称为 Device File System,即设备虚拟文件系统,文件系统的名称使用类似 UNIX 文件、文件夹的风格,目录结构如下图所示: ![](https://www.rt-thread.org/document/site/rt-thread-version/rt-thread-standard/programming-manual/filesystem/figures/fs-dir.png) RT-Thread的文件系统通过以下方式使能: + 开启板上文件系统 ![image-20240727200053727.png](https://oss-club.rt-thread.org/uploads/20240727/7c23a5a5d0c0af93ecc68894e4d5ac64.png.webp) + 选定板载W25Q64为文件系统载体,同时启动自动挂载。 ![image-20240727200214737.png](https://oss-club.rt-thread.org/uploads/20240727/3d1cdd614438c4f3b2ee324f5c7eeaf0.png.webp) + 启用旧接口支持 ![image-20240727200358924.png](https://oss-club.rt-thread.org/uploads/20240727/8afec91d8fbf5373eec120b90a6c7800.png.webp) + 启用ELM FATS支持 ![image-20240727200617830.png](https://oss-club.rt-thread.org/uploads/20240727/ae9f535b5e63a5b813a22cad95d82cbd.png) + 修改最大扇区至4096 ![image-20240727200731940.png](https://oss-club.rt-thread.org/uploads/20240727/6a99addffd85b79b439d3f2a3344e3e4.png) + 保存前记得检查一下SPI是否锁定,因为W25Q64使用SPI进行读写。 关于接口,参考以下示例: ```c //记得在menuconfig中开启支持旧版本功能(Support legacy version) #include
#include
#include
#include
//需要添加软件包进这里 //定义要写入的内容 char String[] = "Hello, RT-Thread.Welcom to RSOC!"; //定义接受文件内容的缓冲区 char buffer[100] = {}; void FileSystem_Test(void *parameter) { //文件描述符 int fd; //用只写方式打开文件,如果没有该文件,则创建一个文件 fd = open("/fal/FileTest.txt", O_WRONLY | O_CREAT); //如果打开成功 if (fd >= 0) { //写入文件 write(fd, String, sizeof(String)); rt_kprintf("Write done.\n"); //关闭文件 close(fd); } else { rt_kprintf("File Open Fail.\n"); } //用只读方式打开文件 fd = open("/fal/FileTest.txt", O_RDONLY); if (fd>= 0) { //读取文件内容 rt_uint32_t size = read(fd, buffer, sizeof(buffer)); if (size < 0) { rt_kprintf("Read File Fail.\n"); return ; } //输出文件内容 rt_kprintf("Read from file test.txt : %s \n", buffer); //关闭文件 close(fd); } else { rt_kprintf("File Open Fail.\n"); } } //导出命令 MSH_CMD_EXPORT(FileSystem_Test, FileSystem_Test); static void readdir_sample(void) { DIR *dirp; struct dirent *d; /* 打开 / dir_test 目录 */ dirp = opendir("/fal"); if (dirp == RT_NULL) { rt_kprintf("open directory error!\n"); } else { /* 读取目录 */ while ((d = readdir(dirp)) != RT_NULL) { rt_kprintf("found %s\n", d->d_name); } /* 关闭目录 */ closedir(dirp); } } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(readdir_sample, readdir sample); ``` ## Demo思路 ![Demo思路.png](https://oss-club.rt-thread.org/uploads/20240727/0334a0605f092900f05ff9da67f4e2a0.png) ## AHT-DFS实现 先放代码: ```c #include
#include
#include
#include "aht10.h" #include
#define AHT10_I2C_BUS "i2c3" #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 2048 #define THREAD_TIMESLICE 5 rt_thread_t AHT10 = RT_NULL; void AHT10_DFS_Th(void *parameter) { // AHT设备指针 aht10_device_t Dev = RT_NULL; // Humi:湿度值,Temp:温度值 float Humi, Temp; // 初始化设备 Dev = aht10_init(AHT10_I2C_BUS); if (Dev == RT_NULL) { rt_kprintf("AHT10_init Fail"); return; } int count=1; int fd; fd = open("/fal/Data.txt", O_WRONLY | O_CREAT); while (count<10) { // 读取温湿度值 Humi = aht10_read_humidity(Dev); Temp = aht10_read_temperature(Dev); rt_kprintf("Humi: %f, Temp: %f\n", Humi, Temp); if (fd < 0) { rt_kprintf("open file failed\n"); } else { char buf[100]; rt_snprintf(buf, sizeof(buf), "Humi: %f, Temp: %f, Count: %d\n", Humi, Temp,count++); write(fd, buf, rt_strlen(buf)); } rt_thread_mdelay(100); } close(fd); } void AHT10_DFS(void) { AHT10 = rt_thread_create("AHT10", AHT10_DFS_Th, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (AHT10 != RT_NULL) { rt_thread_startup(AHT10); } else { rt_kprintf("AHT10_Thread Create Fail"); } } // 导出Shell命令 MSH_CMD_EXPORT(AHT10_DFS, DFS with AHT10 sample.); ``` 几个note: + 在RT-Thread中,单精度浮点数最好使用`float`创建 + `rt_snprintf`本来是将字符串写入特定指针的,但是这里利用其格式化的功能做了一个字符串拼接 + 文件指针使用`int`格式创建,就离谱,但RT-Thread就是不支持`FILE*`这个东西 + 运行后会报LOG_W,说找不到RTC时钟,~~放心,没报错就是正常的~~,因为我们的星火一号没有这个东西,而文件写入需要使用。 ## AHT-MQTT实现 首先我们要打开rw007,记得修改引脚。 上代码: ```c #include "rtthread.h" #include "dev_sign_api.h" #include "mqtt_api.h" #include
#include
#include
#define AHT10_I2C_BUS "i2c3" char DEMO_PRODUCT_KEY[IOTX_PRODUCT_KEY_LEN + 1] = {0}; char DEMO_DEVICE_NAME[IOTX_DEVICE_NAME_LEN + 1] = {0}; char DEMO_DEVICE_SECRET[IOTX_DEVICE_SECRET_LEN + 1] = {0}; void *HAL_Malloc(uint32_t size); void HAL_Free(void *ptr); void HAL_Printf(const char *fmt, ...); int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1]); int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1]); int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]); uint64_t HAL_UptimeMs(void); int HAL_Snprintf(char *str, const int len, const char *fmt, ...); #define EXAMPLE_TRACE(fmt, ...) \ do \ { \ HAL_Printf("%s|%03d :: ", __func__, __LINE__); \ HAL_Printf(fmt, ##__VA_ARGS__); \ HAL_Printf("%s", "\r\n"); \ } while (0) static void example_message_arrive(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) { iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt)msg->msg; switch (msg->event_type) { case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: /* print topic name and topic message */ EXAMPLE_TRACE("Message Arrived:"); EXAMPLE_TRACE("Topic : %.*s", topic_info->topic_len, topic_info->ptopic); EXAMPLE_TRACE("Payload: %.*s", topic_info->payload_len, topic_info->payload); EXAMPLE_TRACE("\n"); break; default: break; } } static int example_subscribe(void *handle) { int res = 0; const char *fmt = "/%s/%s/thing/event/property/post_reply"; char *topic = NULL; int topic_len = 0; topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1; topic = HAL_Malloc(topic_len); if (topic == NULL) { EXAMPLE_TRACE("memory not enough"); return -1; } memset(topic, 0, topic_len); HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME); res = IOT_MQTT_Subscribe(handle, topic, IOTX_MQTT_QOS0, example_message_arrive, NULL); if (res < 0) { EXAMPLE_TRACE("subscribe failed"); HAL_Free(topic); return -1; } HAL_Free(topic); return 0; } static int example_publish(void *handle,float temp,float hum) { int res = 0; const char *fmt = "/sys/%s/%s/thing/event/property/post"; char *topic = NULL; int topic_len = 0; char payload[500] = {0}; rt_snprintf(payload, sizeof(payload),"{\"id\":1721998174165,\"params\":{\"Temperature\":%f,\"Humidity\":%f},\"version\":\"1.0\",\"method\":\"thing.event.property.post\"}",temp,hum); topic_len = strlen(fmt) + strlen(DEMO_PRODUCT_KEY) + strlen(DEMO_DEVICE_NAME) + 1; topic = HAL_Malloc(topic_len); if (topic == NULL) { EXAMPLE_TRACE("memory not enough"); return -1; } memset(topic, 0, topic_len); HAL_Snprintf(topic, topic_len, fmt, DEMO_PRODUCT_KEY, DEMO_DEVICE_NAME); res = IOT_MQTT_Publish_Simple(0, topic, IOTX_MQTT_QOS0, payload, strlen(payload)); if (res < 0) { EXAMPLE_TRACE("publish failed, res = %d", res); HAL_Free(topic); return -1; } HAL_Free(topic); return 0; } static void example_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg) { EXAMPLE_TRACE("msg->event_type : %d", msg->event_type); } void mqtt_example_main(void *parameter) { float Humi, Temp; aht10_device_t Dev = RT_NULL; Dev = aht10_init(AHT10_I2C_BUS); if (Dev == RT_NULL) { rt_kprintf("AHT10_init Fail"); return; } if (Dev == RT_NULL) { rt_kprintf("AHT10_init Fail"); return; } void *pclient = NULL; int res = 0; int loop_cnt = 0; iotx_mqtt_param_t mqtt_params; HAL_GetProductKey(DEMO_PRODUCT_KEY); HAL_GetDeviceName(DEMO_DEVICE_NAME); HAL_GetDeviceSecret(DEMO_DEVICE_SECRET); EXAMPLE_TRACE("mqtt example"); memset(&mqtt_params, 0x0, sizeof(mqtt_params)); mqtt_params.handle_event.h_fp = example_event_handle; pclient = IOT_MQTT_Construct(&mqtt_params); if (NULL == pclient) { EXAMPLE_TRACE("MQTT construct failed"); return; } while (1) { Humi = aht10_read_humidity(Dev); Temp = aht10_read_temperature(Dev); if (0 == loop_cnt % 20) { example_publish(pclient,Temp,Humi); } // res = example_subscribe(pclient); // if (res < 0) // { // IOT_MQTT_Destroy(&pclient); // return; // } IOT_MQTT_Yield(pclient, 200); loop_cnt += 1; } } #define THREAD_PRIORITY 25 #define THREAD_STACK_SIZE 4096 #define THREAD_TIMESLICE 5 rt_thread_t MQTT_Thread; void MQTT_Creat_Thread(void) { // 创建线程 MQTT_Thread = rt_thread_create("MQTT_Thread", mqtt_example_main, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); // 创建成功就启动 if (MQTT_Thread != RT_NULL) { rt_thread_startup(MQTT_Thread); } else { rt_kprintf("MQTT_Thread_Thread Create Fail"); } } // 导出Shell命令 MSH_CMD_EXPORT(MQTT_Creat_Thread, This Function will creat a MQTT thread.); ``` 这段代码由MQTT的sample修改而来,去掉了订阅功能,插入了温湿度读取的代码并魔改了发送函数。 几个note: + 能跑的代码尽量不要动 + RW007因为和W25Q64共用一个SPI,所以建议main文件内写入拉低WIFI引脚电压的代码,并辅以多次重置,避免高电压给FLASH干宕机了: ```c #define WIFI_PIN GET_PIN(F, 10) void WIFI_CS_PULL_DOWN(void) { rt_pin_mode(WIFI_PIN, PIN_MODE_OUTPUT); rt_pin_write(WIFI_PIN, PIN_LOW); } INIT_BOARD_EXPORT(WIFI_CS_PULL_DOWN); ``` + 记得在menuconfig里配置你的阿里云密钥 + WIFI连接要等到提示已获取到IP之后才算好,否则会报LOG_E
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
Lzh200
这家伙很懒,什么也没写!
文章
4
回答
0
被采纳
0
关注TA
发私信
相关文章
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
at_device
ulog
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
张世争
8
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
KunYi
6
个答案
1
次被采纳
本月文章贡献
程序员阿伟
6
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部