ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

RT-Thread Studio实战(3)— 温湿度数据上云与可视化

RT-Thread Studio实战(3)— 温湿度数据上云与可视化 1. 环境准备与硬件连接在开始温湿度数据上云之前我们需要先准备好开发环境和硬件设备。我推荐使用RT-Thread Studio作为开发工具它集成了RT-Thread操作系统和丰富的软件包能大大简化开发流程。硬件方面你需要准备以下设备一块支持RT-Thread的开发板如STM32系列温湿度传感器如AHT10、SHT30或DHT11网络模块ESP8266 Wi-Fi模块或4G模块杜邦线若干首先在RT-Thread Studio中新建一个项目选择适合你开发板的芯片型号。我最近在一个项目中使用的是STM32F407芯片实测下来稳定性不错。创建项目后我们需要在RT-Thread Settings中启用必要的组件打开硬件配置页面启用I2C或GPIO根据你的传感器接口类型在软件包中心搜索并添加温湿度传感器驱动如sht3x或aht10软件包添加网络协议栈和AT设备组件提示如果使用I2C接口的传感器记得检查开发板的I2C引脚定义我在第一次使用时因为引脚搞错导致读取失败。2. 传感器数据采集实战2.1 传感器驱动配置以AHT10传感器为例我们需要在RT-Thread Settings中进行配置进入硬件选项卡找到AHT10(i2c)选项并启用检查I2C总线编号是否与硬件连接一致保存配置后系统会自动下载相关驱动软件包配置完成后可以在sensor_port.c文件中看到传感器初始化代码已经被自动添加到系统初始化流程中。这里有个小技巧如果你发现传感器无法正常工作可以先用RT-Thread提供的sensor命令测试msh sensor probe i2c1 msh sensor read2.2 数据采集代码实现新建一个app_sensor.c文件编写数据采集线程。下面是我在实际项目中使用的代码框架#include rtthread.h #include sensor.h #define SENSOR_DEVICE_NAME aht10 static void sensor_thread_entry(void *parameter) { rt_device_t dev RT_NULL; struct rt_sensor_data data; dev rt_device_find(SENSOR_DEVICE_NAME); rt_device_open(dev, RT_DEVICE_FLAG_RDONLY); while (1) { if (rt_device_read(dev, 0, data, 1) 1) { rt_kprintf(Temp:%.1fC, Humi:%.1f%%\n, data.data.temp, data.data.humi); } rt_thread_mdelay(5000); // 5秒采集一次 } } static int sensor_init(void) { rt_thread_t tid rt_thread_create(sensor, sensor_thread_entry, RT_NULL, 1024, 25, 10); if (tid) rt_thread_startup(tid); return RT_EOK; } INIT_APP_EXPORT(sensor_init);这段代码创建了一个独立的线程来周期性地读取传感器数据。在实际项目中你可能需要根据需求调整采集频率。我建议开始时设置为5秒一次稳定后再根据实际情况优化。3. 数据上云方案实现3.1 网络连接配置数据采集完成后我们需要将其上传到云端。首先确保网络模块正常工作。以ESP8266为例在RT-Thread Settings中启用AT组件添加AT Device软件包选择ESP8266型号配置Wi-Fi账号密码和串口参数配置完成后系统会自动生成网络初始化代码。你可以在main.c中添加以下测试代码验证网络连接#include arpa/inet.h void network_test(void) { int sock socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_addr; server_addr.sin_family AF_INET; server_addr.sin_port htons(80); server_addr.sin_addr.s_addr inet_addr(183.2.172.185); if (connect(sock, (struct sockaddr *)server_addr, sizeof(server_addr)) 0) { rt_kprintf(Network test success!\n); } closesocket(sock); }3.2 数据协议封装为了将数据上传到云端我们需要将其封装成JSON格式。RT-Thread提供了cJSON库使用起来非常方便#include cJSON.h char *create_sensor_json(float temp, float humi) { cJSON *root cJSON_CreateObject(); cJSON_AddStringToObject(root, device, room_101); cJSON_AddNumberToObject(root, temp, temp); cJSON_AddNumberToObject(root, humi, humi); char *json_str cJSON_Print(root); cJSON_Delete(root); return json_str; }这个函数会生成类似这样的JSON字符串{ device: room_101, temp: 25.3, humi: 56.2 }3.3 云端平台对接现在主流的物联网平台都提供了设备接入SDK。以阿里云IoT平台为例在RT-Thread Settings中添加ali-iotkit软件包配置设备三元组ProductKey、DeviceName、DeviceSecret实现数据上报回调函数下面是数据上报的核心代码#include iot_import.h #include iot_export.h void upload_to_cloud(float temp, float humi) { char *json_str create_sensor_json(temp, humi); int res IOT_MQTT_Publish(NULL, /sys/a1B2c3D4/device1/thing/event/property/post, json_str, strlen(json_str), 0, 0); if (res 0) { rt_kprintf(Upload failed: %d\n, res); } else { rt_kprintf(Upload success!\n); } rt_free(json_str); }在实际项目中你可能需要处理网络断开重连、数据缓存等问题。我建议添加一个消息队列来缓冲数据防止网络波动导致数据丢失。4. 数据可视化实现4.1 云端规则引擎配置数据上传到云端后我们可以通过规则引擎将其转发到各种可视化服务。以阿里云为例进入物联网平台控制台创建数据转发规则将设备数据转发到DataV配置数据格式映射关系4.2 本地可视化方案如果你希望实现本地可视化可以使用LVGL或Persimmon UI。下面是一个简单的LVGL温度计实现#include lvgl.h void create_temp_gauge(lv_obj_t *parent) { lv_obj_t *gauge lv_gauge_create(parent, NULL); lv_gauge_set_range(gauge, -20, 50); lv_gauge_set_critical_value(gauge, 40); lv_obj_set_size(gauge, 200, 200); lv_obj_align(gauge, NULL, LV_ALIGN_CENTER, 0, 0); // 更新温度值 lv_gauge_set_value(gauge, 0, 25); }4.3 移动端监控对于移动端监控你可以使用物联网平台提供的App SDK或者自己开发一个简单的HTTP接口#include webclient.h void start_http_server(void) { struct webclient_session *session webclient_session_create(1024); webclient_get(session, http://192.168.1.100/api/sensor); if (session-resp_status 200) { char buf[256]; int len webclient_read(session, buf, sizeof(buf)); rt_kprintf(Response: %.*s\n, len, buf); } webclient_close(session); }5. 项目优化与问题排查在实际部署过程中我遇到过几个典型问题数据上报频率过高导致网络拥堵解决方案是添加数据缓存和批量上报机制传感器数据异常波动通过添加滑动平均滤波算法解决设备频繁掉线调整MQTT的keepalive参数和重连策略这里分享一个数据滤波的实现#define FILTER_SIZE 5 typedef struct { float buffer[FILTER_SIZE]; int index; } filter_t; float filter_add_value(filter_t *filter, float value) { filter-buffer[filter-index] value; if (filter-index FILTER_SIZE) filter-index 0; float sum 0; for (int i 0; i FILTER_SIZE; i) { sum filter-buffer[i]; } return sum / FILTER_SIZE; }对于低功耗设备还需要特别注意电源管理。我在一个电池供电的项目中通过以下方式优化功耗使用传感器的中断功能替代轮询调整Wi-Fi模块的休眠策略优化线程优先级和调度策略最后建议在项目中添加完善的日志系统方便后期维护#include ulog.h void sensor_log(float temp, float humi) { ulog_output(LOG_LVL_DBG, LOG_TAG, RT_TRUE, temp:%.1f, humi:%.1f, temp, humi); // 存储到文件系统 int fd open(/log/sensor.log, O_WRONLY | O_CREAT | O_APPEND); if (fd 0) { char buf[64]; int len sprintf(buf, [%d] temp:%.1f, humi:%.1f\n, rt_tick_get(), temp, humi); write(fd, buf, len); close(fd); } }
返回列表