1 Star 7 Fork 6

小贝比/蓝牙转WIFI计步上位机

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
README.md 10.35 KB
一键复制 编辑 原始数据 按行查看 历史
小贝比 提交于 3年前 . 说明更新

蓝牙转WIFI计步上位机

1. 设计简介

本上位机采用.NET平台下的WPF实现一个MPU6050数据从蓝牙从机——>蓝牙主机——>WIFI的UDP接收数据传输并可视化的功能。

1.1 运行环境

.Net平台下的WPF。VS2019(需安装C#支持的环境)。拿到源码打开 BluetoothPC.sln 运行正常即可。

设计了一个很好看的UI图标:)

2. 设计流程

2.1 设计框架

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

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

  1. UDP数据监听接收线程。
  2. 三轴数据UI更新线程。
  3. 计步和进度条数据更新线程。

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

2.2 服务器连接设计

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

2.3 三轴加速度显示

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

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

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

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

2.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,小于2s
                    if (((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步距离弹出提示框,计步结束也弹提示框通知。

2.5 倾力UI按钮设计

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

3. 总结

本上位机是课程设计的一个附属品,有需要的小伙伴拿去改改,望点个star <- .->!

Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/tytokongjian/StepCountingUpperPC.git
git@gitee.com:tytokongjian/StepCountingUpperPC.git
tytokongjian
StepCountingUpperPC
蓝牙转WIFI计步上位机
master

搜索帮助