Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
LED
onenet
星火1号_spark_星火一号_开发板
[RT-Thread × 大学生夏令营] 基于OneNET服务器的LED阵列游戏的数字孪生系统 rt-thread 华工夏令营 24组
发布于 2023-07-26 11:48:40 浏览:616
订阅该版
**RT-Thread** 夏令营实践作品设计文档 **组号:24** **项目名称:基于OneNET服务器的LED阵列游戏的数字孪生系统** **1.** **技术方案** **1.1 外设与软件包的使用** 本项目使用到的外设有19灯等距全彩LED、4个轻触按键、240*240并行LCD和RW007高速wifi。需要对板载设备驱动进行如下配置: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/68dc5675cb38339c7db730f9a5558342.png.webp) 本项目使用到的软件包有RW007高速WiFi模块驱动、OneNET连接中国移动云平台以及它的依赖包cJSON和Paho MQTT。需要对RW007的引脚和OneNET的产品和设备信息进行如下配置: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/0fb1cd074183c5400a103d064ea08f58.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/f8e346abd25f895565d0ce0ead9ca684.png.webp) **1.2 程序框架** 如下图所示,本项目的目的为实现轻触按键和数字孪生对LCD与LED阵列的控制: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/8e356f43df3d17ffc7ffd282902bacfb.png.webp) 系统创新性:实现了PC端与开发板之间的软硬件同步协同,可以认为构建了单片机按钮功能的数字孪生模型 **1.3 功能设计** ①开发板上电后,利用LED阵列和LCD实现项目的欢迎动画展示: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/4f00756e710939d7202129f3d16398e4.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/a10f9d7f4e951c51dd43c96c060b34f0.png.webp) ②欢迎结束后,进入项目的初始界面。我们设计的游戏为一款吃豆人游戏,闪烁的LED表示吃豆人当前所在的位置,亮着的红灯代表地图上还没吃到的豆子,而灭了的LED则代表该点的豆子已经被吃到。如下图所示,游戏一开始吃豆人位于正中间的LED上: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/65ef982700d74a17ea5e0f3051c09795.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/283ff09dd379e73106b3f028a6131d3e.png.webp) 打开RT-Thread Studio终端,显示WIFI已自动连接好、mqtt协议已初始化且onenet指针已分配好空间: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/3947a3f8515f7f34c19b66a796bd42c0.png.webp) ③如下图所示,可以通过OneNET云平台的数字可视化平台的四个虚拟按键以数字孪生的形式对吃豆人进行控制,也可以通过轻触按键进行控制,吃豆人的移动规则见1.6操作指南。: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/80f53ae0a7b2ab4b7bd5b5d9fcc0ce42.png.webp ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/e0acbd5523910e263ecdbaeadb419a62.png.webp) 如下图所示,当控制吃豆人向左移动时,LCD显示LEFT,吃豆人移动到新的位置上,原位置的LED熄灭: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/99d22547c7a085280d194c7320f24e89.png.webp) 若通过OneNET云平台的数字可视化平台的四个虚拟按键以数字孪生的形式对吃豆人进行控制,终端上还会显示该操作: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/79ba587a32a007984f49d01680dd32bb.png.webp) ④如下图所示,当吃豆人将地图上全部的豆子都吃完后,LED阵列和LCD将展示通关动画,并自动复位开启下一把游戏: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/ff0578246b5609493972c5c1d7f66b09.png.webp) **1.4 代码设计** **1.4.1 准备阶段** 包括头文件的包含、宏的定义、枚举设置以及用于指示的全局变量: ```c #include
#include
#include
#include
#include
#include
#include
#include
#include
#define DBG_ENABLE #define DBG_COLOR #define DBG_SECTION_NAME "onenet.sample" #define DBG_TAG "main" #define DBG_LVL DBG_LOG #include
/* 配置 KEY 输入引脚 */ #define PIN_LEFT GET_PIN (C, 0) #define PIN_DOWN GET_PIN (C, 1) #define PIN_RIGHT GET_PIN (C, 4) #define PIN_UP GET_PIN (C, 5) enum { EXTERN_LED_0, EXTERN_LED_1, EXTERN_LED_2, EXTERN_LED_3, EXTERN_LED_4, EXTERN_LED_5, EXTERN_LED_6, EXTERN_LED_7, EXTERN_LED_8, EXTERN_LED_9, EXTERN_LED_10, EXTERN_LED_11, EXTERN_LED_12, EXTERN_LED_13, EXTERN_LED_14, EXTERN_LED_15, EXTERN_LED_16, EXTERN_LED_17, EXTERN_LED_18, }; enum { EXTERN_KEY_LEFT = 1, EXTERN_KEY_DOWN, EXTERN_KEY_RIGHT, EXTERN_KEY_UP, }; int current_state = EXTERN_LED_18; int key_press = 0; int key_direction = 0; ``` **1.4.2 线程入口函数** ①以命令行的设计形式,实现对OneNET云平台的数字可视化平台的四个虚拟按键下发指令的接收与响应: ```C #ifdef FINSH_USING_MSH #include
/* onenet mqtt command response callback function */ static void onenet_cmd_rsp_cb (uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size) { LOG_D ("received data is %s ",recv_data); if (strcmp (recv_data,"up") == 0) { rt_kprintf ("receive up command"); key_press = 1; key_direction = EXTERN_KEY_UP; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "UP"); } if (strcmp (recv_data,"down") == 0) { rt_kprintf ("receive down command"); key_press = 1; key_direction = EXTERN_KEY_DOWN; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "DOWN"); } if (strcmp (recv_data,"left") == 0) { rt_kprintf ("receive left command"); key_press = 1; key_direction = EXTERN_KEY_LEFT; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "LEFT"); } if (strcmp (recv_data,"right") == 0) { rt_kprintf ("receive right command"); key_press = 1; key_direction = EXTERN_KEY_RIGHT; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "RIGHT"); } memset (recv_data,0,strlen (recv_data)); } /* set the onenet mqtt command response callback function */ int onenet_set_cmd_rsp (int argc, char **argv) { onenet_set_cmd_rsp_cb (onenet_cmd_rsp_cb); return 0; } MSH_CMD_EXPORT (onenet_set_cmd_rsp, set cmd response function); #endif /* FINSH_USING_MSH */ ``` ②动态线程,通过按键消抖的方法来实现对轻触按键下发指令的接收与响应: rt_thread_t key_press_thread; ```C rt_thread_t key_press_thread; static void key_press_entry () { while (1) { rt_thread_mdelay (10); if (rt_pin_read (PIN_LEFT) == PIN_LOW) { rt_thread_mdelay (50); if (rt_pin_read (PIN_LEFT) == PIN_LOW) { key_press = 1; key_direction = EXTERN_KEY_LEFT; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "LEFT"); } } else if (rt_pin_read (PIN_DOWN) == PIN_LOW) { rt_thread_mdelay (50); if (rt_pin_read (PIN_DOWN) == PIN_LOW) { key_press = 1; key_direction = EXTERN_KEY_DOWN; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "DOWN"); } } else if (rt_pin_read (PIN_RIGHT) == PIN_LOW) { rt_thread_mdelay (50); if (rt_pin_read (PIN_RIGHT) == PIN_LOW) { key_press = 1; key_direction = EXTERN_KEY_RIGHT; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "RIGHT"); } } else if (rt_pin_read (PIN_UP) == PIN_LOW) { rt_thread_mdelay (50); if (rt_pin_read (PIN_UP) == PIN_LOW) { key_press = 1; key_direction = EXTERN_KEY_UP; lcd_clear (WHITE); lcd_show_string (50, 104, 32, "UP"); } } } } ``` ③动态线程,实现没有按键按下时当前位置LED的闪烁、按键对LED阵列的控制逻辑以及游戏通关的判断和动画展示: ```c rt_thread_t led_key_thread; static void led_key_entry () { rt_thread_mdelay (7000); while (1) { while (!key_press) { Set_LEDColor (current_state, DARK); RGB_Reflash (); rt_thread_mdelay (500); Set_LEDColor (current_state, LT_RED); RGB_Reflash (); rt_thread_mdelay (500); } switch (key_direction) { case EXTERN_KEY_LEFT: { Set_LEDColor (current_state, DARK); RGB_Reflash (); switch (current_state) { case (EXTERN_LED_0): current_state = EXTERN_LED_11; break; case (EXTERN_LED_1): current_state = EXTERN_LED_0; break; case (EXTERN_LED_2): current_state = EXTERN_LED_12; break; case (EXTERN_LED_3): current_state = EXTERN_LED_13; break; case (EXTERN_LED_4): current_state = EXTERN_LED_14; break; case (EXTERN_LED_5): current_state = EXTERN_LED_6; break; case (EXTERN_LED_6): current_state = EXTERN_LED_7; break; case (EXTERN_LED_7): current_state = EXTERN_LED_8; break; case (EXTERN_LED_12): current_state = EXTERN_LED_17; break; case (EXTERN_LED_13): current_state = EXTERN_LED_18; break; case (EXTERN_LED_14): current_state = EXTERN_LED_15; break; case (EXTERN_LED_15): current_state = EXTERN_LED_8; break; case (EXTERN_LED_16): current_state = EXTERN_LED_9; break; case (EXTERN_LED_17): current_state = EXTERN_LED_10; break; case (EXTERN_LED_18): current_state = EXTERN_LED_16; break; default: break; } } break; case EXTERN_KEY_DOWN: { Set_LEDColor (current_state, DARK); RGB_Reflash (); switch (current_state) { case (EXTERN_LED_0): current_state = EXTERN_LED_12; break; case (EXTERN_LED_1): current_state = EXTERN_LED_2; break; case (EXTERN_LED_2): current_state = EXTERN_LED_3; break; case (EXTERN_LED_3): current_state = EXTERN_LED_4; break; case (EXTERN_LED_8): current_state = EXTERN_LED_7; break; case (EXTERN_LED_9): current_state = EXTERN_LED_8; break; case (EXTERN_LED_10): current_state = EXTERN_LED_9; break; case (EXTERN_LED_11): current_state = EXTERN_LED_17; break; case (EXTERN_LED_12): current_state = EXTERN_LED_18; break; case (EXTERN_LED_13): current_state = EXTERN_LED_15; break; case (EXTERN_LED_14): current_state = EXTERN_LED_5; break; case (EXTERN_LED_15): current_state = EXTERN_LED_6; break; case (EXTERN_LED_17): current_state = EXTERN_LED_16; break; case (EXTERN_LED_18): current_state = EXTERN_LED_15; break; default: break; } } break; case EXTERN_KEY_RIGHT: { Set_LEDColor (current_state, DARK); RGB_Reflash (); switch (current_state) { case (EXTERN_LED_0): current_state = EXTERN_LED_1; break; case (EXTERN_LED_6): current_state = EXTERN_LED_5; break; case (EXTERN_LED_7): current_state = EXTERN_LED_6; break; case (EXTERN_LED_8): current_state = EXTERN_LED_15; break; case (EXTERN_LED_9): current_state = EXTERN_LED_16; break; case (EXTERN_LED_10): current_state = EXTERN_LED_17; break; case (EXTERN_LED_11): current_state = EXTERN_LED_0; break; case (EXTERN_LED_12): current_state = EXTERN_LED_2; break; case (EXTERN_LED_13): current_state = EXTERN_LED_3; break; case (EXTERN_LED_14): current_state = EXTERN_LED_4; break; case (EXTERN_LED_15): current_state = EXTERN_LED_14; break; case (EXTERN_LED_16): current_state = EXTERN_LED_18; break; case (EXTERN_LED_17): current_state = EXTERN_LED_12; break; case (EXTERN_LED_18): current_state = EXTERN_LED_13; break; default: break; } } break; case EXTERN_KEY_UP: { Set_LEDColor (current_state, DARK); RGB_Reflash (); switch (current_state) { case (EXTERN_LED_2): current_state = EXTERN_LED_1; break; case (EXTERN_LED_3): current_state = EXTERN_LED_2; break; case (EXTERN_LED_4): current_state = EXTERN_LED_3; break; case (EXTERN_LED_5): current_state = EXTERN_LED_14; break; case (EXTERN_LED_6): current_state = EXTERN_LED_15; break; case (EXTERN_LED_8): current_state = EXTERN_LED_9; break; case (EXTERN_LED_9): current_state = EXTERN_LED_10; break; case (EXTERN_LED_12): current_state = EXTERN_LED_0; break; case (EXTERN_LED_14): current_state = EXTERN_LED_13; break; case (EXTERN_LED_15): current_state = EXTERN_LED_18; break; case (EXTERN_LED_16): current_state = EXTERN_LED_17; break; case (EXTERN_LED_17): current_state = EXTERN_LED_11; break; case (EXTERN_LED_18): current_state = EXTERN_LED_12; break; default: break; } } break; default: break; } if (!Get_LEDColor (0).R && !Get_LEDColor (1).R && !Get_LEDColor (2).R && !Get_LEDColor (3).R && !Get_LEDColor (4).R && !Get_LEDColor (5).R && !Get_LEDColor (6).R && !Get_LEDColor (7).R && !Get_LEDColor (8).R && !Get_LEDColor (9).R && !Get_LEDColor (10).R && !Get_LEDColor (11).R && !Get_LEDColor (12).R && !Get_LEDColor (13).R && !Get_LEDColor (14).R && !Get_LEDColor (15).R && !Get_LEDColor (16).R && !Get_LEDColor (17).R && !Get_LEDColor (18).R) { lcd_show_string (20, 108, 24, "LOVE! RT-Thread!"); for (int count_1 = 0; count_1 <= 2; count_1++) { switch (count_1) { case 0: led_matrix_fill (LT_RED); break; case 1: led_matrix_fill (LT_GREEN); break; case 2: led_matrix_fill (LT_BLUE); break; default: return; break; } RGB_Reflash (); rt_thread_mdelay (100); for (int j = EXTERN_LED_18; j > EXTERN_LED_0; j--) { switch (count_1) { case 0: Set_LEDColor (j, DARK); break; case 1: Set_LEDColor (j, DARK); break; case 2: Set_LEDColor (j, DARK); break; default: return; break; } RGB_Reflash (); rt_thread_mdelay (100); } } led_matrix_fill (LT_RED); RGB_Reflash (); current_state = EXTERN_LED_18; } key_press = 0; key_direction = 0; } } ``` ④动态线程,实现项目的欢迎动画展示: ```c rt_thread_t led_matrix_thread; static void led_matrix_entry () { lcd_show_string (20, 108, 24, "LOVE! RT-Thread!"); for (int count = 0; count <= 2; count++) { for (int i = EXTERN_LED_0; i <= EXTERN_LED_18; i++) { switch (count) { case 0: Set_LEDColor (i, LT_RED); break; case 1: Set_LEDColor (i, LT_GREEN); break; case 2: Set_LEDColor (i, LT_BLUE); break; default: return; break; } RGB_Reflash (); rt_thread_mdelay (100); } } led_matrix_fill (LT_WHITE); RGB_Reflash (); rt_thread_mdelay (1000); led_matrix_fill (LT_RED); RGB_Reflash (); } ``` ⑤动态线程,实现WIFI的自动连接、mqtt协议的初始化以及为onenet指针分配空间: ```C rt_thread_t wifi_init_thread; static void wifi_init_entry () { rt_wlan_connect ("P40Pro", "23456789"); onenet_mqtt_init (); onenet_set_cmd_rsp_cb (onenet_cmd_rsp_cb); } ``` **1.4.3 主函数** 对轻触按键外设进行配置,以及上述五个线程的创建与启动: ```C int main (void) { /* 设置 KEY0 引脚的模式为输入上拉模式 */ rt_pin_mode (PIN_LEFT, PIN_MODE_INPUT_PULLUP); rt_pin_mode (PIN_DOWN, PIN_MODE_INPUT_PULLUP); rt_pin_mode (PIN_RIGHT, PIN_MODE_INPUT_PULLUP); rt_pin_mode (PIN_UP, PIN_MODE_INPUT_PULLUP); led_matrix_thread = rt_thread_create ("led matrix", led_matrix_entry, RT_NULL, 1024, 4, 20); if (led_matrix_thread == RT_NULL) { rt_kprintf ("led matrix thread create failed!\n"); return 0; } rt_thread_startup (led_matrix_thread); led_key_thread = rt_thread_create ("led key", led_key_entry, RT_NULL, 1024, 5, 20); if (led_key_thread == RT_NULL) { rt_kprintf ("led key thread create failed!\n"); return 0; } rt_thread_startup (led_key_thread); key_press_thread = rt_thread_create ("key press", key_press_entry, RT_NULL, 1024, 6, 20); if (key_press_thread == RT_NULL) { rt_kprintf ("key press thread create failed!\n"); return 0; } rt_thread_startup (key_press_thread); wifi_init_thread = rt_thread_create ("wifi init", wifi_init_entry, RT_NULL, 1024, 7, 20); if (wifi_init_thread == RT_NULL) { rt_kprintf ("wifi init thread create failed!\n"); return 0; } rt_thread_startup (wifi_init_thread); return 0; } ``` **1.5 OneNET云平台的搭建** 如下图所示,设计了OneNET云平台的数字可视化平台界面,将开关的开启和关闭指令分别设置为left、down、right和up,通过多协议接入连接到开发板上。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/9fcc86a950ee0e8735977a1526643a92.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/bd0decee2a4cb8c94bd6ae4627a73ac9.png.webp) **1.6 操作指南** 如下图所示,LED阵列使用的是SK6805 RGB三色LED, 由19个LED组成,驱动时使用串行信号。 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/b018e317f4c99cec21f88faa45cb61d7.png.webp) LED阵列在开发板中的位置以及对应的ID号如下图所示: ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/71aef695ade8799aa8960b9da6331b0c.png.webp ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20230726/6646b3bacb6a175079cccffb57def995.png.webp) 按键对LED阵列的控制方式如下表所示(X表示无法通过): | led Direction | **LEFT** | **DOWN** | **RIGHT** | **UP** | | -------------- | -------- | -------- | --------- | ------ | | **0** | **11** | **12** | **1** | **X** | | **1** | **0** | **2** | **X** | **X** | | **2** | **12** | **3** | **X** | **1** | | **3** | **13** | **4** | **X** | **2** | | **4** | **14** | **X** | **X** | **3** | | **5** | **6** | **X** | **X** | **14** | | **6** | **7** | **X** | **5** | **15** | | **7** | **8** | **X** | **6** | **X** | | **8** | **X** | **7** | **15** | **9** | | **9** | **X** | **8** | **16** | **10** | | **10** | **X** | **9** | **17** | **X** | | **11** | **X** | **17** | **0** | **X** | | **12** | **17** | **18** | **2** | **0** | | **13** | **18** | **14** | **3** | **X** | | **14** | **15** | **5** | **4** | **13** | | **15** | **8** | **6** | **14** | **18** | | **16** | **9** | **X** | **18** | **17** | | **17** | **10** | **16** | **12** | **11** | | **18** | **16** | **15** | **13** | **12** | 2. **人员分配 ** 何思成:OneNET云平台的数字可视化平台和程序接口的设计、以及多协议接入的准备 林扬航:源程序的设计,主要包括轻触按键的线程、LED阵列变化的线程等 张旭泽:资料收集、PPT展示、视频拍摄等 **3.** **时间规划** 7.22 项目功能的构思 7.23 OneNET模块、轻触按键模块和LED阵列模块的设计 7.24 不同模块间的整合与程序改进 7.25 视频拍摄、制作PPT、编写设计文档以及程序的开源 7.26 进行答辩展示
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
NovaSame
这家伙很懒,什么也没写!
文章
1
回答
0
被采纳
0
关注TA
发私信
相关文章
1
应用开发如何包含头文件
2
STM32F03RC跑RTT标准版 没有运行
3
为什么 Count 的值不连续和间隔为 7?
4
请求LED.C/H文件
5
RT-thread 如何被当做“单片机”,控制小灯的亮灭?
6
ART-PI Smart User 运行LED 程序崩溃
7
agile led软件包怎么使用
8
AT32F423开发板呼吸灯无作用,只有一个灯亮
9
studio中onenet包使能自动注册设备功能,编译缺少代码
10
rt-thread如何上传GPS的经纬度到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
篇文章
2
次点赞
Ghost_Girls
1
篇文章
6
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部