Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
onenet
星火1号_spark_星火一号_开发板
[RT-Thread x 大学生夏令营] 简易桌面气象站
发布于 2023-07-25 21:15:18 浏览:1065
订阅该版
[tocm] 本项目演示如何使用 RT-Thread 星火 1 号 开发板以及Onenet中国移动物联网开放平台实现桌面气象站的搭建。初次使用本例程的用户请先阅读本文档。 ## 简介 本项目的主要功能是通过板载的温度、湿度和光照传感器监测环境数据,并在 LCD 屏幕上显示,自动连接 wifi 上传到 Onenet 平台。通过卡尔曼滤波器对所采集到的数据进行处理,通过按键设定阈值并使用 LED 矩阵灯、 LED 灯和蜂鸣器实现温度、湿度和光照的可视化与报警。 ![绘图1.png](https://s2.loli.net/2023/07/25/NkH9D2T1uMzZ7rX.png) ## 硬件介绍 ### 开发板 ![RTT.png](https://s2.loli.net/2023/07/25/IRYWvlDtZ6Bw4Cb.png) 使用 RT-Thread 星火 1 号 开发板开发本项目,各模块在开发板中位置如图所示。 ### LED ![led_pin.png](https://s2.loli.net/2023/07/25/urYyVkCawodANRz.png) ![led_circuit.png](https://s2.loli.net/2023/07/25/EFQTfNw1LnyM6tY.png) 如上图所示,RBG-LED 属于共阳 LED ,阴极分别与单片机的引脚连接,其中红色 LED 对应 PF12 引脚。单片机引脚输出低电平即可点亮 LED ,输出高电平则会熄灭 LED。 ### LED Matrix ![led_en.png](https://s2.loli.net/2023/07/25/bJGkzN1IDLdfwAp.png) ![led_data.png](https://s2.loli.net/2023/07/25/2trnhUBguDNOJR9.png) ![led_matrix.png](https://s2.loli.net/2023/07/25/TlO39rQKU76IJ84.png) 如上图所示,LED MATRIX 使用的是 SK6805 RGB 三色 LED, 驱动时使用串行信号。 ### 蜂鸣器 ![beep_pin.png](https://s2.loli.net/2023/07/25/mNj8szZnLhiGP2d.png) ![beep_circurt.png](https://s2.loli.net/2023/07/25/mg8flOncaITZkFe.png) 蜂鸣器连接单片机引脚与原理图如上图所示。 ### LCD ![lcd.png](https://s2.loli.net/2023/07/25/1tpRZuNCDz6yK3s.png) 星火 1 号开发板板载的是一块 1.3 寸,分辨率为 240x240 的 LCD 显示屏,显示效果十分细腻。显示屏的驱动芯片是 ST7789 v3, 通信接口使用的是 8080 并口,通过 fsmc 模拟出驱动时序和单片机进行通讯。使用了 8 根数据线传输数据,一根地址选择线作为芯片的使能信号。 ### 温湿度传感器 ![AHT21.png](https://s2.loli.net/2023/07/25/DcEUtS2bXTAWdIp.png) ![aht21_circuit.png](https://s2.loli.net/2023/07/25/IzxVigLy1obheDW.png) 如上图所示,单片机通过软件 iic I2C3(soft) scl(PE0)、 I2C3(soft) sda(PE1) 对传感器 aht10 发送命令、读取数据等。 该传感器输入电压范围为 1.8v - 3.3v,测量温度与湿度的量程、精度如下表所示: | 功能 | 量程 | 精度 | 单位 | | :----: | :----: | :----: | :----: | | 温度 | -40 - 85 | ±0.5 | 摄氏度 | | 相对湿度 | 0 - 100 | ±3 | % | ### 接近与光强传感器 ![ap3216c.png](https://s2.loli.net/2023/07/25/njGqykBHUNhceob.png) ![ap3216c_circuit.png](https://s2.loli.net/2023/07/25/lqyUjWCa4YLXM6p.png) 如上图所示,单片机通过 I2C2(soft) scl(PF1)、 I2C2(soft) sda(PF0) 对传感器 ap3216c 发送命令、读取数据等, AP_INT(PG13) 为硬件中断引脚。 该传感器能够实现如下功能: * 光照强度:支持 4 个量程 * 接近感应:支持 4 种增益 * 中断触发:光照强度及接近感应同时支持 高于阈值 或 低于阈值 的两种硬件中断触发方式 ### Onenet上传 Onenet 上传需要依赖 星火 1 号 板卡上的 WiFi 模块完成网络通信,因此请确保硬件平台上的 WiFi 模组可以正常工作。 ## 软件介绍 ### 数据要素 #### 初始化 同时初始化传感器 ap3216c 和 aht10 ,分别传入参数。 i2c2 和 i2c3 为传感器挂载的 i2c 总线的名称;初始化若失败,则返回空,程序不会被执行,若成功,则返回传感器设备对象。 ```c int main(void) { /* initialize ap3216c */ const char *i2c_bus_name_ap = "i2c2"; rt_thread_mdelay(1000); dev_ap = ap3216c_init(i2c_bus_name_ap); if (dev_ap == RT_NULL) { LOG_E("The sensor initializes failure."); return 0; } /* initialize aht10 */ const char *i2c_bus_name_aht = "i2c3"; rt_thread_mdelay(1000); dev_aht = aht10_init(i2c_bus_name_aht); if (dev_aht == RT_NULL) { LOG_E(" The sensor initializes failure"); return 0; } ``` ### 数据采集 创建一个线程进行温湿度与光照值的读取。 ```c void sensor_entry() { while(1){ /* read brightness */ brightness = ap3216c_read_ambient_light(dev_ap); brightness = kalman_filter(brightness, &p_t_b, &p_t_b_, &K_b, &R_b, &lux_b, &lux_b_); // LOG_D("current brightness: %d.%d(lux).", (int)brightness, ((int)(10 * brightness) % 10)); /* read humidity */ humidity = aht10_read_humidity(dev_aht); humidity = kalman_filter(humidity, &p_t_h, &p_t_h_, &K_h, &R_h, &lux_h, &lux_h_); // LOG_D("humidity : %d.%d %%", (int)humidity, (int)(humidity * 10) % 10); /* read temperature */ temperature = aht10_read_temperature(dev_aht); temperature = kalman_filter(temperature, &p_t_t, &p_t_t_, &K_t, &R_t, &lux_t, &lux_t_); // LOG_D("temperature: %d.%d", (int)temperature, (int)(temperature * 10) % 10); rt_thread_mdelay(1000); } } ``` ### LCD 显示 创建一个线程实现温湿度与光照值在 LCD 上的显示。 ![微信图片_20230725150108.png](https://s2.loli.net/2023/07/25/5q7rvxUEWpKFVbd.png) ```c void screen_entry() { lcd_set_color(WHITE, BLACK); while(1) { lcd_clear(WHITE); lcd_show_image(0, 0, 240, 240, image_1); //show brightness on the sun lcd_set_color(0xff4b, BLACK); if (brightness < 100){ lcd_show_string(125, 53, 24, "%d.%d", (int)brightness, ((int)(10 * brightness) % 10)); } else{ lcd_show_string(125, 53, 24, "%d", (int)brightness); } //show the humidity on the cloud lcd_set_color(0xc77e, BLACK); lcd_show_string(160, 90, 24, "%d.%d", (int)humidity, ((int)(10 * humidity) % 10)); //show the temperature on the thermometer lcd_set_color(0xc8c3, WHITE); lcd_show_string(50, 200, 16, "%d.%d", (int)temperature, ((int)(10 * temperature) % 10)); //show the humidity threshold on the top right lcd_set_color(0xef9d, BLACK); lcd_show_string(220, 13, 16, "%d", humidity_thre); //show the humidity threshold on the top left lcd_show_string(5, 13, 16, "%d", temperature_thre); rt_thread_mdelay(1000); } } ``` ### 蜂鸣器的阈值报警 创建一个线程,当温度与湿度超过阈值时,蜂鸣器报警。 ```c void beep_entry(){ while(1){ if((temperature > 30) & (humidity > 70)){ rt_pin_write(PIN_BEEP, PIN_HIGH); // LOG_D("beep on"); } else{ rt_pin_write(PIN_BEEP, PIN_LOW); // LOG_D("beep off"); } rt_thread_mdelay(1000); } } ``` ### LED 灯阈值闪烁 创建一个线程,当光照强度发生变化时,LED 灯的闪烁频率发生变化。 ```c void blink_r_entry(){ int delay = 500; while (1) { if(brightness < 100){ delay = 1000; } else if(brightness > 500){ delay = 250; } else{ delay = 500; } /* LED ON */ rt_pin_write(LED_R, PIN_LOW); // LOG_D("led on"); rt_thread_mdelay(delay); /* LED OFF */ rt_pin_write(LED_R, PIN_HIGH); // LOG_D("led off"); rt_thread_mdelay(delay); } } ``` ### LED Matrix 可视化 创建俩个 led matrix demo 线程。 `led_matrix_example_entry_outer`控制外圈 LED 灯,当温度未超过阈值时显示为绿色闪烁,温度超过阈值时显示为白色闪烁;`led_matrix_example_entry_inner`控制内圈 LED 灯,当湿度未超过阈值时显示为蓝色闪烁,温度超过阈值时显示为红色不闪烁。 `led_matrix_example_entry_outer`线程代码如下: ```c static void led_matrix_outer(RGBColor_TypeDef GREN, int count){ int i=EXTERN_LED_6; switch (count) { case 0: Set_LEDColor(i, GREN); break; case 1: Set_LEDColor(i, DARK); break; default: return ; break; } RGB_Reflash(); rt_thread_delay(200); for (int j = 1; j < 6; j++) { switch (count) { case 0: Set_LEDColor(i-j, GREN); Set_LEDColor(i+j, GREN); break; case 1: Set_LEDColor(i-j, DARK); Set_LEDColor(i+j, DARK); break; default: return ; break; } RGB_Reflash(); rt_thread_delay(200); } switch (count) { case 0: Set_LEDColor(i-6, GREN); break; case 1: Set_LEDColor(i-6, DARK); break; default: return ; break; } RGB_Reflash(); rt_thread_delay(200); } static void led_matrix_example_entry_outer() { int count = 0; while (1){ if (temperature > 30){ led_matrix_outer(PINK, count); } else{ led_matrix_outer(GREN, count); } count = (count+1) % 2; } } ``` `led_matrix_example_entry_inner`线程代码如下: ```c static void led_matrix_example_entry_inner() { int count1=0; while(1) { if (humidity > 90){ Set_LEDColor(EXTERN_LED_18, RD); Set_LEDColor(EXTERN_LED_17, RD); Set_LEDColor(EXTERN_LED_16, RD); Set_LEDColor(EXTERN_LED_15, RD); Set_LEDColor(EXTERN_LED_14, RD); Set_LEDColor(EXTERN_LED_13, RD); Set_LEDColor(EXTERN_LED_12, RD); RGB_Reflash(); rt_thread_delay(200); } else { switch (count1) { case 0: Set_LEDColor(EXTERN_LED_18, BLU); Set_LEDColor(EXTERN_LED_17, BLU); Set_LEDColor(EXTERN_LED_16, BLU); Set_LEDColor(EXTERN_LED_15, BLU); Set_LEDColor(EXTERN_LED_14, BLU); Set_LEDColor(EXTERN_LED_13, BLU); Set_LEDColor(EXTERN_LED_12, BLU); RGB_Reflash(); rt_thread_delay(200); break; case 1: Set_LEDColor(EXTERN_LED_18, DARK); Set_LEDColor(EXTERN_LED_17, DARK); Set_LEDColor(EXTERN_LED_16, DARK); Set_LEDColor(EXTERN_LED_15, DARK); Set_LEDColor(EXTERN_LED_14, DARK); Set_LEDColor(EXTERN_LED_13, DARK); Set_LEDColor(EXTERN_LED_12, DARK); RGB_Reflash(); rt_thread_delay(200); break; default: return ; break; } count1 = (count1+1) % 2; } } } ``` ### 按键功能 利用按键实现温湿度阈值的改变,其中上下按键控制湿度阈值,左右按键控制温度阈值。 首先对按键引脚进行定义: ```c #define PIN_UP GET_PIN(C, 5) #define PIN_DOWN GET_PIN(C, 1) #define PIN_LEFT GET_PIN(C, 0) #define PIN_RIGHT GET_PIN(C, 4) ``` 编写中断回调函数 ```c void irq_callback(void *args) { rt_uint32_t sign = (rt_uint32_t) args; switch (sign) { case PIN_UP : humidity_thre = humidity_thre + 1; break; case PIN_DOWN : humidity_thre = humidity_thre - 1; break; case PIN_LEFT : temperature_thre = temperature_thre - 1; break; case PIN_RIGHT : temperature_thre = temperature_thre + 1; break; default: LOG_E("error sign= %d !", sign); break; } } ``` 判断按键按下情况并调用中断回调函数: ```c //设置引脚模式 rt_pin_mode(PIN_UP, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_DOWN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_LEFT, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_RIGHT, PIN_MODE_INPUT_PULLUP); // 设置按键中断模式与中断回调函数 rt_pin_attach_irq(PIN_UP, PIN_IRQ_MODE_FALLING, irq_callback, (void *) PIN_UP); rt_pin_attach_irq(PIN_DOWN, PIN_IRQ_MODE_FALLING, irq_callback, (void *) PIN_DOWN); rt_pin_attach_irq(PIN_LEFT, PIN_IRQ_MODE_FALLING, irq_callback, (void *) PIN_LEFT); rt_pin_attach_irq(PIN_RIGHT, PIN_IRQ_MODE_FALLING, irq_callback, (void *) PIN_RIGHT); // 使能中断 rt_pin_irq_enable(PIN_UP, PIN_IRQ_ENABLE); rt_pin_irq_enable(PIN_DOWN, PIN_IRQ_ENABLE); rt_pin_irq_enable(PIN_LEFT, PIN_IRQ_ENABLE); rt_pin_irq_enable(PIN_RIGHT, PIN_IRQ_ENABLE); ``` ### 卡尔曼滤波 卡尔曼滤波算法(KF)是序贯数据同化的一种,是由Kalman针对随机过程状态估计提出的。KF的基本思想是利用前一时刻的状态估计值和当前时刻的观测值来获得动态系统当前时刻状态变量的最优估计,包括预报和分析两个步骤。其算法流程如下图所示,大致分为三步。 ![Snipaste_2023-07-24_16-34-22.png](https://s2.loli.net/2023/07/25/XYhvonkuDx5yfi1.png) #### 参数定义 ![para_define.png](https://s2.loli.net/2023/07/25/uvZmVTOqGcrUK93.png) #### 参数初始化 计算卡尔曼增益 ![k_calcu.png](https://s2.loli.net/2023/07/25/PsSfTOWw1aK4hZp.png) #### 第一步:更新 包括状态更新和协方差更新 状态更新: ![state_update.png](https://s2.loli.net/2023/07/25/MJwP2ZmSvt4B3hO.png) 协方差更新: ![covarient_update.png](https://s2.loli.net/2023/07/25/qtjWHM2Rkcg9XSF.png) #### 第二步:预测 包括状态预测和协方差预测 状态预测: ![state_pred.png](https://s2.loli.net/2023/07/25/bXKtY4yVdN8wri2.png) 协方差预测: ![covarient_pred.png](https://s2.loli.net/2023/07/25/ihfBuHJvx5D42pa.png) #### 第三步:系统迭代 下图描述了卡尔曼滤波算法的具体迭代逻辑。 ![Snipaste_2023-07-24_16-32-20.png](https://s2.loli.net/2023/07/25/sQpA7uZjM4t1XHg.png) 其代码如下: ```c float kalman_filter(float new_lux,float* p_t, float* p_t_, float* K, float* R, float* lux, float* lux_) { /* 状态估计 */ *lux_ = *lux; //先验估计,此次估计值=上次的最优估计 *p_t_ = *p_t; //此次的估计协方差 = 上次的最优估计协方差 /* 修正估计*/ *K = *p_t_/(*p_t_ + *R); //更新 K *lux = *lux_ + (*K)*(new_lux - *lux_);//更新最优估计值,即得到当前最优估计值 *p_t = (1-*K)*(*p_t_); return *lux; } ``` ### wifi 连接及 OneNET 数据可视化 调用 Scan 接口扫描周围环境中的 AP(Access Point ,即无线访问热点) ;同时自动连接 wifi (名字: Redmi , 密码: 12345678 ) ```c rt_wlan_connect("Redmi", "12345678"); ``` 接着通过 MQTT 协议将数据上传到 OneNET 平台: ```c onenet_mqtt_init(); rt_thread_init(&upload, "upload", upload_entry, NULL, upload_stack, sizeof(upload_stack), 21, 5); rt_thread_startup(&upload); ``` 将温湿度与光照值通过卡尔曼滤波后上传至OneNET平台,数值随时间变化如图所示。 温度: ![1.png](https://s2.loli.net/2023/07/25/TtKercG4D7FUvEi.png) 湿度: ![2.png](https://s2.loli.net/2023/07/25/8u3496Kw1zj7pOn.png) 光照: ![3.png](https://s2.loli.net/2023/07/25/2ZKT8fvlXOeGjEh.png) ## 运行结果 温湿度: ![Snipaste_2023-07-24_17-55-54.png](https://s2.loli.net/2023/07/25/mLo8zxqAPYnbWpw.png) 光照: ![Snipaste_2023-07-24_17-56-12.png](https://s2.loli.net/2023/07/25/yGX4YofiEVag8rC.png) LCD 显示: ![微信图片_20230725150108.png](https://s2.loli.net/2023/07/25/5q7rvxUEWpKFVbd.png) 云端上传: ![1.png](https://s2.loli.net/2023/07/25/TtKercG4D7FUvEi.png) ## 注意事项 需要更改 pin 脚,防止 LCD 与 LED 冲突。 ## 引用参考 - 设备与驱动:[PIN 设备](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/pin/pin) - onenet 软件包:[https://github.com/RT-Thread-packages/onenet](https://github.com/RT-Thread-packages/onenet)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
IanYe
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
studio中onenet包使能自动注册设备功能,编译缺少代码
2
rt-thread如何上传GPS的经纬度到onenet?
3
MQTT 在“ read 0:1, break “后断开重连
4
ONENET+esp8266连接报错
5
有哪位实现了ONENET包获取onenet数据源数据吗
6
请问一下使用BC26对接ONENET的步骤是什么呀
7
AT Client receive failed???
8
onenet示例程序运行异常
9
如何使用OneNet软件包上传2个以上数据流
10
OneNET 浮点数据上传,但小数部分却被截掉
推荐文章
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
I2C_IIC
ESP8266
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
SFUD
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
xusiwei1236
8
个答案
2
次被采纳
踩姑娘的小蘑菇
1
个答案
2
次被采纳
用户名由3_15位
7
个答案
1
次被采纳
bernard
4
个答案
1
次被采纳
RTT_逍遥
3
个答案
1
次被采纳
本月文章贡献
聚散无由
2
篇文章
15
次点赞
catcatbing
2
篇文章
5
次点赞
Wade
2
篇文章
3
次点赞
Ghost_Girls
1
篇文章
6
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部