用M5StickC-Plus实现跳绳计数器
用M5Stack的StickC-Plus实现跳绳计数器。在Arduino平台上开发,
标签
数字逻辑
M5Stack
2022暑假在家练
跳绳计数器
StickC-Plus
何小强
更新2022-09-07
北京大学
744

内容介绍

任务要求

电子森林的“2022年暑假在家一起练”活动提供了M5Stack StickC Plus开发板,完成以下任务之一:

  • 可以用语音控制的灯板
  • 可以定时的电子沙漏
  • 使用姿态传感器完成体感游戏手柄
  • 设计一个跳绳计数器

家里有个小孩正在读小学。他们要求经常进行跳绳锻炼,而且跳绳也是考试内容之一,因此我选择了跳绳计数器,觉得挺有实际价值的,以后有空了再尝试其他的任务。

StickC Plus内置3轴加速计与3轴陀螺仪,再加上配套的手表带,对我们这个可穿戴设备的任务来说,这些硬件的准备已经完全足够了,剩下的工作只需要软件开发和算法设计。

以下是StickC Plus的介绍,其特点就是麻雀虽小五脏俱全,非常适合做一些DIY的小玩意。

FqxSyKXQFB21X-hUdLegOX9PuOiL

环境配置

由于涉及到算法设计,我选择了arduino平台,忍痛放弃了图形化编程的方便性。Arduino的配置非常简单,主要就是安装M5Stack平台以及StickC Plus需要的库。而在算法实现过程中用来检测波峰信号的第三方库,我是直接把代码下载下来跟ino文件放在同一个目录下面。

FuS0BAItLQXiFgl-bZznpv7J8pDU

程序实现

跳绳的时候,人的手臂处于周期运动的状态。只需要记录该运动状态的循环次数,即可知道跳绳的次数。StickC Plus可以通过接口函数,直接获得加速度、角速度。

    float accX, accY, accZ;
    M5.IMU.getAccelData(&accX, &accY, &accZ);
    
    //float pitch, roll, yaw;
    //M5.IMU.getAhrsData(&pitch, &roll, &yaw);

    //float gyroX, gyroY, gyroZ;
    //M5.IMU.getGyroData(&gyroX, &gyroY, &gyroZ);

参考了一些跳绳计数器的做法,“该传感器采集了人体跳动过程中加速度变化的数据,该传感器采用三轴加速度传感器,但仅采集Z轴的数据”,我们在这个项目中也只采用了加速度数据来判断跳绳动作的的次数。

而一般情况下,每个周期都有一个极值,因此我们也可以通过检测该运动状态的极值来判断跳绳次数。我们借鉴了github上的一个开源项目PeakDetector,eyal-lezmy/peak-detector: Detect peaks on an input signal (github.com),通过分析信号变化来检测信号峰值。首先识别出上升和下降沿,然后如果一个上升沿紧跟着一个下降沿,那么中间那个点就是极值点。原文如下

The peak detector observes the variations of the signal (the differences between the 5 successive values), to determine if we watch an increasing or decreasing front. The signal must increase 3 times in a row to be an increasing front. And decrease 3 times in a row to be decreasing. The peak is validated only if its intensity is at least the half of the average of the previously observed peak intensities.

When the detector find an increasing front followed by a decreasing front, a peak is detected.

另一方面,通过接口函数我们获得了XYZ三个方向的加速度。StickC Plus绑在手腕上,记录跳绳动作的数据,其中两个垂直手臂方向的信号比较相似,而与平行手臂方向的信号有些差别。从结果来看,垂直手臂方向的信号比较清晰,跳绳次数测量结果更准确一些。因此我们倾向于选择垂直手臂方向的信号,比如对两个垂直方向的信号的波峰数目取平均。

在代码中的实现方法是对三个信号分别进行波峰检测,然后对得到的三个波峰数值取中值,可以尽量避免因为细微抖动或者噪声带来的测量误差。

  int get_median(int a, int b, int c) {
      return a>=b?(b>=c?b:(a>=c?c:a)):(a>=c?a:(b>=c?c:b));
  }

总体算法如下

Fp2RPCi7hqk6N5srydIT0rWcXzE_

另外就是加速度数据的采样频率。考虑到小学跳绳成绩满分是1分钟200次左右,或者频率超过3次每秒,而为了更好地识别出波峰,我们需要有足够多的数据来判断上升沿和下降沿,因此我们设置每隔10毫秒采样一次。

在程序中还用数据列表记录加速度数据历史记录,可用于进一步的分析,比如剔除不合理的数据段等。但目前还没想好怎么使用。

最后把结果显示在LCD中。在StickC的库对IMU数据获取和LCD屏幕显示都有很好的支持了,这儿不需要详细介绍了。

演示成品如图,屏幕中央显示最终跳绳次数以及所用的时间,下面用小一号的数字显示三个轴分别测到的波峰个数。

FsWbARg9wbKy1CjqhUhK_nNvQZ9v

未来建议

在开发过程中,我们发现,如果把设备跳绳计数器结合到跳绳握把里面,其测量准确度会提高很多,经常是完全正确的。而把计数器作为手环绑在手腕上,其测量结果很容易出现偏差,其原因是跳绳过程中手臂运动幅度很小,测量出来的信号周期形状不明显,而跳绳过程中人体上下跳跃的动作同样会引入信号波动,对手臂往复运动状态的检测造成干扰;而跳绳握把的运动幅度相对较大,其信号具有很强的周期特性,测量结果也更加稳定可靠。

因此如果需要做成可行的产品,我会更倾向于把计数器集成到跳绳里面,而不是作为一个可穿戴设备戴在手腕上。

而在数据处理方面也可以做更多的事情。上面我们只选取某个方向的加速度值,而事实上我们可以对三个轴的加速度数据进行融合处理,比如主成分分析PCA,以尽可能地保留更多的信息。

更进一步的是,我们还可以利用历史数据记录来识别运动状态,只有在跳绳运动状态时才开始计数,避免了因为准备运动、设置硬件等动作而引入的计数误差。

最后感谢电子森林,给我们提供了电子器件和交流社区,帮助有兴趣的同学们学习电子设计,即使是菜鸟也可以零基础入门,DIY出自己感兴趣的东西。

附件下载

RopeSkipper.zip

团队介绍

我自己,一个热爱技术的工程师,长期写代码,现在有空想玩玩硬件。

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号