OpenHarmony有氧拳击之设备端开发
一、简介
在一个风和日丽,阳光明媚的下午,码农们都像往常一样正在专注地码代码。突然前面的小哥哥站起来,手握开发板,来回出拳。这是怎么回事?
原来这是一款拳击互动游戏,本文将带你一同解开其中的奥秘。开发者从中不仅能体验到学习知识的愉悦,还能享受到健身的乐趣。依托OpenAtom OpenHarmony(以下简称“OpenHarmony”)3.2 Beta1操作系统,样例分为应用端和设备端两部分。本文主要介绍设备端的实现,后续会分享应用端的开发。
设备端:采用小熊派BearPi-HM Nano(Hi3861)开发板,处理加速度计传感器数据。
应用端:采用润和DAYU200(RK3568)开发板,主要处理显示及音效。
如下图,左侧为设备端,右侧为应用端:开发者手握设备端小熊派开发板,观察屏幕,根据应用端APP显示,在指定的时间完成挥拳动作;挥拳信息经无线传递到应用端,应用端APP对挥拳时机有相应的计分规则,最后统计出总分。

二、原理
相比正常状态下,挥拳动作会引起手臂较大的加速度变化。根据这个特征,我们使用BearPi-HM_Nano开发板的扩展模块E53_SC2,它内部集成了MPU6050传感器,能够读取加速度的大小。
做挥拳动作实验,统计数据,得到挥拳时加速度的阈值。程序执行时,把实时的数据与阈值进行比较,判断是否触发了挥拳动作。再经过无线通信,实时把数据发送到应用端。
三、加速度计传感器使用说明
设备端的开发关键在对加速度计传感器的使用,主要涉及两点:1、重力加速度g的理解;2、如何把MPU6050寄存器的数据转化为有单位的数据?
1、样例使用的加速度传感器是MPU6050,它有±2g、±4g、±8g和±16g四个量程可以选择。一个g是指一个重力加速度,代表9.8米/秒²大小。举个例子:假如设备从高处掉落,其加速计测量到的加速度将为0g,因为传感器没有受到力的挤压,处在失重状态;假如设备水平放在桌面上,则加速计测量出的加速度为1g(9.8米/秒²),我们可以理解为受到1g的压力;
2、MPU6050采用16位的ADC采样。16位的ADC采样是什么意思?举个例子:如果量程选择(通过寄存器选择)是±2g,16位的ADC采样,表示的含义是用65536(即2的16次方)种情况去表达-2到+2g的情况。如下datasheet截图显示,AFS_SEL=0,表示±2g量程,当数据寄存器的数据为16384,对应表示受到1g的力。例如:数据寄存器读取到的值为X,对应受到的力的大小为Y,则Y=X/16384,单位是g。

四、代码解析
设备端代码主要分为两个线程:1、传感器数据处理线程;2、TCP通信线程;它们之间通过事件的方式进行同步通信。
1、传感器数据处理线程主要函数说明:
//E53_SC2模块MPU6050传感器数据处理主要流程
static void DataHandleTask(void)
{
uint8_t ret;
ret = E53SC2Init();//MPU6050传感器初始化及配置,配置为+—8g量程
if (ret != 0) {
printf("E53_SC2 Init failed!\r\n");
return;
}
while (1) {
ret = E53SC2ReadData(&data);//MPU6050传感器寄存器数据读取
if (ret != 0) {
printf("E53_SC2 Read Data!\r\n");
return;
}
AccDataHandle(&data);//MPU6050传感器数据处理,转化为单位为g的数据
if (myCaldata.Accel[ACCEL_X_AXIS] < 0) {
myCaldata.Accel[ACCEL_X_AXIS] = myCaldata.Accel[ACCEL_X_AXIS] * -1.0;
}
if (myCaldata.Accel[ACCEL_Y_AXIS] < 0) {
myCaldata.Accel[ACCEL_Y_AXIS] = myCaldata.Accel[ACCEL_Y_AXIS] * -1.0;
}
if (myCaldata.Accel[ACCEL_Z_AXIS] < 0) {
myCaldata.Accel[ACCEL_Z_AXIS] = myCaldata.Accel[ACCEL_Z_AXIS] * -1.0;
}
//判断实时数据是否大于拳击阈值Boxing_ACC,大于则设置事件
if (myCaldata.Accel[ACCEL_X_AXIS] > Boxing_ACC || myCaldata.Accel[ACCEL_Y_AXIS] > Boxing_ACC || myCaldata.Accel[ACCEL_Z_AXIS] > Boxing_ACC) {
printf("MPU set flg\r\n");
osEventFlagsSet(g_eventFlagsId, FLAGS_MSK1);//触发拳击事件
}
usleep(Delay_10ms);
}
}
#define MAX_POS_NUM 32767
#define LSB 4096.0
//MPU6050传感器数据处理,转化为单位为g的数据
int AccDataHandle(E53SC2Data *dat)
{ //量程为+-8g,所以分辨率为4096
if (dat->Accel[ACCEL_X_AXIS] < MAX_POS_NUM) {
myCaldata.Accel[ACCEL_X_AXIS] = dat->Accel[ACCEL_X_AXIS]/LSB;
} else {
myCaldata.Accel[ACCEL_X_AXIS] =(-1)* (dat->Accel[ACCEL_X_AXIS]-MAX_POS_NUM)/LSB;
}
if (dat->Accel[ACCEL_Y_AXIS] < MAX_POS_NUM) {
myCaldata.Accel[ACCEL_Y_AXIS] = dat->Accel[ACCEL_Y_AXIS]/LSB;
} else {
myCaldata.Accel[ACCEL_Y_AXIS] = (-1)*(dat->Accel[ACCEL_Y_AXIS]-MAX_POS_NUM)/LSB;
}
if (dat->Accel[ACCEL_Z_AXIS] < MAX_POS_NUM) {
myCaldata.Accel[ACCEL_Z_AXIS] = dat->Accel[ACCEL_Z_AXIS]/LSB;
} else {
myCaldata.Accel[ACCEL_Z_AXIS] =(-1)*(dat->Accel[ACCEL_Z_AXIS]- MAX_POS_NUM)/LSB;
}
return 0;
}
2、TCP通信线程主要函数说明:
在本样例的网络通信中,小熊派BearPi-HM Nano(Hi3861)开发板作为客户端,润和DAYU200(RK3568)开发板作为服务端。它们之间采用TCP机制通信。
如下代码:建立好TCP通信后,常规状态下通信线程处在阻塞态,当拳击事件触发后,则会发送信息给服务端:
static void TCPClientTask(void)
{
// 在sock_fd 进行监听,在 new_fd 接收新的链接
int sock_fd;
uint32_t flags;
struct sockaddr_in send_addr; // 服务器的地址信息
socklen_t addr_length = sizeof(send_addr);
char recvBuf[recvLen];
memset(recvBuf, '\0', sizeof(recvBuf));
// 连接Wifi
WifiConnect(CONFIG_WIFI_SSID, CONFIG_WIFI_PWD);
// 创建socket
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("create socket failed!\r\n");
exit(1);
}
// 初始化预连接的服务端地址
send_addr.sin_family = AF_INET;
send_addr.sin_port = htons(CONFIG_SERVER_PORT);
send_addr.sin_addr.s_addr = inet_addr(CONFIG_SERVER_IP);
addr_length = sizeof(send_addr);
//连接
connect(sock_fd,(struct sockaddr *)&send_addr, addr_length);
printf("TCPClient connect success\r\n"); while (1) {
memset(recvBuf, '\0', sizeof(recvBuf));
//等待事件是否触发
flags = osEventFlagsWait(g_eventFlagsId, FLAGS_MSK1, osFlagsWaitAny, osWaitForever);
printf("TCP get flag\r\n");
sprintf(sendbuf,"right\r\n");
send(sock_fd, sendbuf, strlen(sendbuf), 0);//tcp发出触发信息
// 线程休眠一段时间
usleep(Delay_100ms);//100ms
}
closesocket(sock_fd);
}
五、代码构建、编译及烧录
1、OpenHarmony 3.2 Beta1源码下载,地址参考文章结尾处链接;
2、在源码根目录下的vendor目录下,新建team_x文件夹;
3、把boxing文件夹,拷贝到team_x目录下,如下图所示:

4、在源码目录下,输入hb set,然后选择当前文件路径,即输入.(点),然后通过方向键选取team_x下的boxing,如下图:

5、输入hb build -f,开始编译,编译成功后,会在根目录下的out/bearpi_hm_nano/boxing目录生成Hi3861_wifiiot_app_allinone.bin,如下图:


6、用HiBurn工具烧录程序,烧录参考链接在文章结尾处;
烧录成功后,可以本地验证项目是否成功:
1、电脑端使用网络调试助手软件,建立TCP服务端,电脑端建立服务端需要注意以下几点:
(1)电脑与BearPi-HM Nano开发板连入同一个Wi-Fi热点,如图:电脑与开发板都连入热点"YYYYYY";
(2)BearPi-HM Nano开发板程序设置的IP,电脑的IP,网络调试助手服务端的IP,三者保持一致,如下图"192.168.1.100";
(3)点击网络调试助手的"连接"按钮,即先启动服务端。

2、BearPi-HM Nano开发板串口接入电脑,设置波特率为115200;
3、复位BearPi-HM Nano开发板,复位后,串口会打印Wi-Fi连接成功、TCP连接成功等信息,如下图(右侧);
4、手握开发板,尝试出拳(即挥动开发板)。能看到网络助手的TCP服务端窗口,成功接收到同步挥拳信息“right”,如下图(左侧):

六、总结
本文主要讲述了拳击互动游戏中,关于设备端的开发,使用小熊派BearPi-HM Nano(Hi3861)开发板硬件,在小熊派相关基础例程上做了二次开发。本设备端开发,使用了OpenHarmony的线程、事件、GPIO、IIC、TCP通信等相关基础知识,再结合加速度计传感器的使用,实现与应用端同步交互的功能。
本样例是OpenHarmony知识体系工作组(相关链接在文章末尾)为广大开发者分享的样例。知识体系工作组结合日常生活,给开发者规划了各种场景的Demo样例,如智能家居场景、影音娱乐场景、运动健康场景等;欢迎广大开发者一同参与OpenHarmony的开发,更加完善样例,相互学习,相互进步。
七、参考连接
本样例代码下载链接:
https://gitee.com/openharmony-sig/knowledge_demo_entainment/tree/master/dev/team_x/boxing
OpenHarmony知识体系共建开发仓:
https://gitee.com/openharmony-sig/knowledge/blob/master/docs/co-construct_demos/README_zh.md
OpenHarmony学习路径:
https://growing.openharmony.cn/mainPlay/learnPath
小熊派BearPi-HM Nano开发板学习路径:
https://growing.openharmony.cn/mainPlay/learnPathMaps?id=19
https://gitee.com/bearpi/bearpi-hm_nano/tree/master
润和DAYU200(RK3568)开发板介绍:
https://gitee.com/hihope_iot/docs/blob/master/HiHope_DAYU200/docs/README.md
https://growing.openharmony.cn/mainPlay/learnPathMaps?id=27

OpenHarmony有氧拳击之设备端开发的更多相关文章
- web移动端开发技巧与注意事项汇总
一.meta的使用 1.<meta name="viewport" content="width=device-width,initial-scale=1.0, m ...
- 移动端开发viewport深入理解(转)
一.viewport的概念 移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,就是浏览器上用来显示网页的那部分区域,但viewport不局限于浏览器可视区域 的大小,它 ...
- 移动端开发概览【webview和touch事件】
作为一个前端,而且作为一个做移动端开发的前端,那意味着你要有三头六臂,跟iOS开发哥哥一起打酱油,跟Android开发哥哥一起修bug... Android vs Ios 我在webkit内核的chr ...
- Twitter Bootstrap 3.0 正式发布,更好地支持移动端开发
Twitter Bootstrap 3.0 终于正式发布了.这是一个圆滑的,直观的和强大的移动优先的前端框架,用于更快,更容易的 Web 开发.几乎一切都已经被重新设计和重建,更好的支持移动端设备. ...
- 移动端开发,几个你可能不知道的CSS单位属性。
1. rem "em" 单位是我们开发中比较常用到的,它表示以当前元素的父元素的单位大小为基准来设置当前元素的大小:“rem” 中的 “r” 代表 “root”,它表示以根(即“h ...
- 移动端开发(一. Viewport(视窗))
手机与浏览器 移动端开发主要针对手机,ipad等移动设备,随着地铁里的低头族越来越多,移动端开发在前端的开发任务中站的比重也越来越大.各种品牌及尺寸的手机也不尽相同.尺寸不同就算了分辨率,视网膜屏 ...
- 11-移动端开发教程-zepto.js入门教程
Zepto.js是一个轻量级的针对现代浏览器的JavaScript库, 它与jquery有着类似的api. 如果你会用jquery,那么你也会用zepto. 1. Why Zepto.js? API类 ...
- web移动端开发技巧
一.meta的使用 1.<meta name="viewport" content="width=device-width,initial-scale=1.0, m ...
- 移动端开发注意事项——meta、rem以及弹性盒
移动端开发注意事项——meta.rem以及弹性盒 随着人们对移动端的依赖程度的增强,前端开发对移动端的需求也越来越强烈.那么,在移动端开发中,有哪些事项是需要注意的呢? meta标签 在常规的pc端开 ...
- 移动端开发demo—移动端web相册(一)
本文主要是介绍开发移动端web相册这样一案例用到的前置知识. 一.移动端样式 移动端更接近手机原生的方式. 如下是一个angular mobile的demo的例子: 移动端demo做成这样的好处: 在 ...
随机推荐
- web模块化
CommonJS-----是一种后端js规范,是nodejs遵循的一种编写js模块的规范引入模块-------require('模块路径')定义模块 ------ exports.模块名= funct ...
- 【Azure 事件中心】Event Hubs如何获取其中存放的历史消息
问题描述 使用Azure Event Hub服务,除了正常的生产,消费消息以外,如果想拿到Event Hub中存储的历史消息?有什么方法呢? 问题解答 获取 Event Hubs 存储的历史消息,首先 ...
- 有了 ETL 数据神器 dbt,表数据秒变 NebulaGraph 中的图数据
本文搭配同主题分享视频阅读更佳,<多数据源的数据治理实践> 如果你装好某款数据库产品,比如:分布式图数据库 NebulaGrpah,跃跃欲试的第一步是不是就让它干活搞数据呢?好的,现在问题 ...
- Java 韩顺平老师的课,记的(前6章)笔记
https://www.bilibili.com/video/BV1fh411y7R8/?p=110&spm_id_from=333.880.my_history.page.click& ...
- Android switch语句报错Constant expression required
方案一 :可以用 if来替代 如下 原因:在Android Studio中使用JDK17以上版本,会出现switch语句报错"Constant expression required&qu ...
- CYQ.Data 支持 KingbaseES人大金仓数据库
KingbaseES人大金仓数据库介绍: KingbaseES是一种关系型数据库管理系统,也被称为人大金仓数据库.KingbaseES 是北京人大金仓信息技术股份有限公司研发的,具有自主知识产权的通用 ...
- “田由甲” - Kafka重复消费线上问题暴雷
Kafka作为一款高性能.分布式的消息队列系统,在大数据领域被广泛应用.然而,在使用Kafka时,重复消费问题是一个常见的挑战,可能会对系统的数据一致性和业务逻辑造成影响.我知道Kafka这个名词时还 ...
- 解决Abp设置DefaultLanguage默认语言不生效的问题
@ 目录 现象 原因分析 解决问题 现象 默认地,Abp的语言提供程序将返回的CultureInfo为En,在一些默认实现的接口(比如/api/TokenAuth/Authenticate)返回的错误 ...
- docsify + GitHub Page免费搭建个人博客
docsify生成文档 docsify是一个动态生成文档网站的工具.通过编辑MarkDown文件就能实现简约清爽的文档页面. 先在Github创建项目 创建项目成功后,把项目克隆到本地(以自己的实际地 ...
- 基于python的每日固定时间执行实例解析
一 概念 datetime模块属性如下所示: 二 源码解析 该源码中,对时间库datetime应用十分到位,可以看作如下所示: import datetime import threading d ...