C#+ WPF 实现蓝牙转WIFI计步上位机

news/2025/1/7 17:04:17/文章来源:https://www.cnblogs.com/1312mn/p/18650335

前言

一个WIFI上位机,接收底层MPU6050数据,途中转蓝牙从机透传,到蓝牙主机直连WIFI,PC端UDP通信,实现三轴加速度数据传送和计步功能。

项目介绍

本项目基于.NET平台,使用WPF开发了一个应用程序,用于实现MPU6050传感器数据从蓝牙模块传输到主机,并通过WiFi以UDP协议接收这些数据并进行可视化展示。

具体而言,MPU6050作为从设备通过蓝牙连接到主控设备(蓝牙主机),再由主控设备经由WiFi网络将数据以UDP包的形式发送至服务器或客户端进行处理和图形化显示。

项目运行环境

1、开发平台

项目基于.NET Framework,采用 WPF 开发用户界面。

2、集成开发环境

Visual Studio 2019,确保已安装 C# 开发工作负载以支持项目开发与运行。

3、启动项目

获取源代码后,通过打开 BluetoothPC.sln 解决方案文件即可。确保所有依赖项正确配置后,直接运行解决方案,应用程序应能正常启动。

4、用户界面特色

应用程序配备了一个直观且美观的用户界面,图标设计精心,提供优秀的用户体验和视觉享受。

项目设计流程

1、设计框架

前台XAML的UI设计不过多介绍,主要看设计需求,逃不开模板、触发器、动画、样式之类的技术。

后台C#在UI主线程下开了三个子线程:

1、UDP数据监听接收线程。

2、三轴数据UI更新线程。

3、计步和进度条数据更新线程。

因没有碰到多个线程访问同一个UI控件或写同一个UI控件,所以没用到锁,但内部加了异步延迟,让UI更新顺滑一些。

2、服务器连接设计

UDP端IP地址和端口号需正常且有效,加了错误弹窗,若出现下图请重新输入:

3、三轴加速度显示

有硬件:成功连接上之后需配合底层硬件,这里是接收UDP发过来的3轴加速度值。

无硬件:如果没有硬件也行,自行找个网络调试助手,开个UDP服务,本机连接就行,发送的数据需包含以下格式:

任意字符(:1.23938 mG)任意字符。

解释:

发送过来的数据必须包含在 :xxxx mG 内,冒号和mG不能少,可任意多组,每组代表一轴数据。

4、计步显示

利用三轴加速度提供的数据处理步数。需打开左下角计步控制按钮。

打开后弹出提示:

本计步算法仅支持手臂摆动的峰峰值计步,若有更好的算法请分享,万分感谢!!!

计步程序如下

/** valueNum - 存放三轴数据(x,y,z)的个数* tempValue - 用于存放计算阈值的波峰波谷差值的数组(在这个方法里存放值数组长度为5)* isDirectionUp - 是否上升的标志位* continueUpCount - 持续上升的次数* continueUpFormerCount - 上一点的持续上升的次数,为了记录波峰的上升次数* lastStatus - 上一点的状态,上升还是下降* peakOfWave - 波峰值* valleyOfWave - 波谷值* timeOfThisPeak - 此次波峰的时间* timeOfLastPeak - 上次波峰的时间* timeOfNow - 当前的时间* gravityOld - 上次传感器的值* initialValue - 动态阈值需要动态的数据,这个值用于这些动态数据的阈值,这个值是由大量数据得来的* ThreadValue - 初始阈值,这个值是由大量数据得来的* minValue - 初始最小值 计算出来的xyz数值乘重力加速度(9.8),此为手机拿在手里(不摆臂)(由自己多次测试得出的值)* maxValue - 初始最大值 自己设定的最大值(我们定位2)乘重力加速度(9.8),此为手机拿在手里(不摆臂)(由自己多次测试得出的值)* g - 重力加速度(9.8)* thisSteps 步数
*/
private int valueNum = 5;
//private double[] tempValue;
private List<double> tempValue = new List<double>();
private Boolean isDirectionUp = false;
private int continueUpCount = 0;
private int continueUpFormerCount = 0;
private Boolean lastStatus = false;
private double peakOfWave = 0;
private double valleyOfWave = 0;
private double timeOfThisPeak = 0;
private double timeOfLastPeak = 0;
private double timeOfNow = 0;
private double gravityOld = 0;
private double initialValue = 1.7;
private double ThreadValue = 2.0;
private double minValue = 11;
private double maxValue = 19.6;
private double g = 9.8;
private double thisSteps = 0;   
//当前步数private double StepsCopy = 0;   
//步数复制/// <summary>
/// 监测新的步数 如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步
/// 符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
/// </summary>
/// <param name="_values">加速传感器三轴的平均值</param>
public void detectorNewStep(double _values)
{if (gravityOld == 0){gravityOld = _values;}else{if (detectorPeak(_values, gravityOld)){timeOfLastPeak = timeOfThisPeak;timeOfNow = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds);//时间差大于200ms,小于2sif (((timeOfNow - timeOfLastPeak) >= 200) && ((timeOfNow - timeOfLastPeak) <= 2000) && ((peakOfWave - valleyOfWave) >= ThreadValue)){timeOfThisPeak = timeOfNow;//增加步数thisSteps++;//增加步数复制StepsCopy++;}if(((timeOfNow - timeOfLastPeak) >= 200) && ((peakOfWave - valleyOfWave) >= initialValue)){timeOfThisPeak = timeOfNow;double _diffWaveVal = peakOfWave - valleyOfWave;ThreadValue = peak_Valley_Thread(_diffWaveVal);}}gravityOld = _values;}
}
/// <summary>
/// 监测波峰
/// 以下四个条件判断为波峰
/// 1.目前点为下降的趋势:isDirectionUp为false
/// 2.之前的点为上升的趋势:lastStatus为true
/// 3.到波峰为止,持续上升大于等于2次
/// 4.波峰值大于minValue,小于maxValue
/// 记录波谷值
/// 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
/// 2.所以要记录每次的波谷值,为了和下次的波峰作对比
/// </summary>
/// <param name="_newValue"></param>
/// <param name="_oldValue"></param>
/// <returns></returns>
public Boolean detectorPeak(double _newValue, double _oldValue)
{lastStatus = isDirectionUp;if (_newValue >= _oldValue){isDirectionUp = true;continueUpCount++;}else{continueUpFormerCount = continueUpCount;continueUpCount = 0;isDirectionUp = false;}if (!isDirectionUp && lastStatus && (continueUpFormerCount >= 2 && (_oldValue >= minValue && _oldValue < maxValue))){//满足上面波峰的四个条件,此时为波峰状态peakOfWave = _oldValue;return true;}else if (!lastStatus && isDirectionUp){//满足波谷条件,此时为波谷状态valleyOfWave = _oldValue;return false;}else{return false;}
}
/// <summary>
/// 阈值的计算
/// 1.通过波峰波谷的差值计算阈值
/// 2.记录4个值,存入tempValue[] 数组中
/// 3.在将数组传入函数averageValue中计算阈值
/// </summary>
/// <param name="_value"></param>
/// <returns></returns>
public double peak_Valley_Thread(double _value)
{double _tempThread = ThreadValue;List<double> _tempValue = new List<double>(tempValue);if (tempValue.Count < valueNum){tempValue.Add(_value);}else{//tempValue数组长度=valueNum=5_tempThread = averageValue(tempValue);_tempValue.RemoveAt(0);_tempValue.Add(_value);tempValue = _tempValue;}return _tempThread;
}
/// <summary>
/// 梯度化阈值
/// 1.计算数组的均值
/// 2.通过均值将阈值梯度化在一个范围里
/// 这些数据是通过大量的统计得到的
/// </summary>
/// <param name="_value"></param>
/// <returns></returns>
public double averageValue(List<double> _value)
{if (_value.Count != 0){double _ave = 0;foreach (double i in _value)_ave += i;_ave = _ave / _value.Count;if(_ave >= 8){_ave = 4.3;}else if (_ave >= 7 && _ave < 8){_ave = 3.3;}else if (_ave >= 4 && _ave < 7){_ave = 2.3;}else if (_ave >= 3 && _ave < 4){_ave = 2.0;}else{_ave = 1.7;}return _ave;}else{return 1.7;}
}

计步效果如下所示:

开启步数控制按钮后总步数累加,进度条进度为50步,每到达50步距离弹出提示框,计步结束也弹提示框通知。

5、倾力UI按钮设计

设计了一组拟物化按钮,目前无任何功能,有需要的小伙伴自行更改设计功能。

项目地址

Gitee:https://gitee.com/tytokongjian/StepCountingUpperPC

总结

以上仅展示了蓝牙转WIFI计步上位机的部分功能。更多实用特性和详细信息,请大家访问项目地址。

希望通过本文能为上位机机开发方面提供有价值的参考。欢迎在评论区留言交流,分享您的宝贵经验和建议。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!优秀是一种习惯,欢迎大家留言学习!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/864862.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

水位监测识别报警摄像机

智能水位监测识别报警摄像机是保障水域安全的重要利器。其高效准确的监测能力和及时有效的报警功能,将为城市水域管理和安全防范提供重要支持,有助于减少因水灾而造成的损失。摄像头通过实时捕捉水面画面,并将数据传输至中央处理器进行分析。一旦系统检测到水位异常,如水位…

SQL Server Profiler的trc文件生成阻止.240108

很奇葩,sqlserver自动生成trc文件,每分钟一个,重启服务器也没用。解决思路:查询现在正在跑的trace进程select * from sys.fn_trace_getinfo(0);关闭C2审计功能EXEC sp_configure c2 audit mode, 0;重启数据库服务 再次查看,已经没了。然后删除数据盘所有的trc文件。EXEC s…

cas5配置redis.240108

​POM文件加载redis依赖,重新maven clean package<dependency><groupId>org.apereo.cas</groupId><artifactId>cas-server-support-redis-ticket-registry</artifactId><version>${cas.version}</version></dependency><d…

dockerfile实现tomcat以及java的war包自动部署.240108

1. 下载jdk和tomcat wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.93/bin/apache-tomcat-8.5.93.tar.gz wget https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz 2. vim Dockerfile FROM centos:latest MAINTAINER Amadeus # now add…

Centos中keytool不起作用的解决方法.240109

​keytool是Java开发中用于管理密钥和证书的工具,可以用于生成密钥、创建证书请求、导入和导出证书等操作。你可以在Oracle官网上下载和安装JDK,然后在JDK的 bin目录下找到 keytool 工具。 因此,我们首先要给centos装jdk yum -y install java-1.8.0-openjdk* 然后在执行keyt…

【npm】npm warn ERESOLVE overriding peer dependency——版本冲突,降级

这里警告的远远是由于 @eslint 和 eslint-loader@2.2.1 之间版本冲突。eslint-loader支持的eslint版本在`>=1.6.0 <7.0.0`。可用输入 npm list eslint 查看当前依赖的具体问题。 所有,我们可以给wsint降级,选择1.6.0~7.0.0(不包含7.0.0)之间的版本。输入 npm view es…

群晖 MariaDB10 开启远程登录.240109

​情况:MariaDB设置了TCP/IP的端口,但是还是无法进行远程访问。解决方法: 一、使用ssh登录群晖,并进入MariaDB安装目录 cd /volume1/@appstore/MariaDB10/usr/local/mariadb10/bin 二、使用root登录 MariaDB,然后进行修改 mysql -u root -p MariaDB [(none)]> use mysq…

软件最难的不是开发程序,而是需求.240109

最近几个月,关于人工智能的惊人文章在互联网泛滥。这也引发了很多人的担心——软件开发人员可能很快就会失业,被人工智能取代。他们想象所有的企业高管和产品研究人员将绕过大多数或所有的软件开发人员,直接要求人工智能构建他们想要或需要的东西。但作为一个拥有15年一线开…

项目管理不再是难题:一揽子解决方案助你轻松前行

项目管理中的痛点涉及多个方面,但通过优化资源分配、建立有效的沟通机制、加强时间管理、完善风险控制、简化变更管理以及加强利益相关者期望管理等措施,可以有效地解决这些痛点,确保项目的顺利进行和成功完成。一、项目管理的核心要素 ● 范围管理:明确项目的范围和目标,…

如何修改网站的模板?

修改网站的模板是提升网站外观和用户体验的重要步骤。以下是详细的步骤和建议:备份原始模板:在进行任何修改之前,确保备份原始模板文件。 使用版本控制系统(如Git)来管理文件变更。选择合适的工具:根据网站的技术栈选择合适的工具。常见的工具包括文本编辑器(如Notepad+…

如何使用Dreamweaver修改网站模板?

Dreamweaver(DW)是一款功能强大的网页设计工具,可以帮助您轻松修改网站模板。以下是详细的步骤和建议:安装和启动Dreamweaver:确保已安装Dreamweaver软件。 启动Dreamweaver并打开您的网站项目。定位模板文件:在Dreamweaver的“文件”面板中,找到并打开需要修改的模板文…

如何登录网站后台并修改代码?

登录网站后台并修改代码是网站维护和开发过程中常见的任务。以下是详细的步骤和注意事项:获取后台登录信息:确保您拥有网站后台的登录凭证,包括用户名和密码。 如果忘记了登录信息,可以联系网站管理员或技术支持。登录后台:打开浏览器,输入网站后台的URL,通常是http://域…