在本期文章中,我们来介绍一种利用脉搏传感器输出的模拟信号计算心率的方法。该方法经测试,得出的心率值还是比较准确的,且测量效率较高。下面先来介绍一下文中所用的脉搏传感器。
该传感器测量脉搏的强度,输出一个模拟信号。其测量脉搏使用了“光电容积法”。下面是模块手册上摘抄的原理说明:“光电容积法是利用人体组织在血管搏动时造成透光率不同来测量脉搏的。光源采用对动脉血中氧和血红蛋白有选择性的一定波长(500NM-700NM)的发光二极管。当光束透过外周血管,由于动脉搏动充血容积变化导致透光率发生变化,此时用光电变换器接收经人体组织反射的、变化的光信号,转变为电压信号输出。”这种传感器测量时只需用手指接触或夹在耳垂上即可测量,但缺点就是当皮肤潮湿或接触传感器不充分则测量会失效。
下面,我们先用Arduino采集传感器的原始数据,用串口将原始数据输出到ArduinoIDE的“串口绘图”看看“心电图”。(代码比较简单,只需要启动串口,然后“打印”AD采样的值即可。)下图为传感器与手指接触良好时得到的曲线,采样周期为10毫秒:
接下来看看当手指未接触传感器时得到的曲线:
从上面两图可以看到,当传感器采集到脉搏时,会输出与心跳一至的“搏动”信号,其最大值在800左右,最小值在400左右,我们可以通过串口监视器看到具体的数值。这两个值因人而异,不同的人会得到不同的峰谷值。当手指移开,传感器“悬空”,则得到第二图中的曲线,数据会在500-600之间有一个很小的波动。至此,我们对传感器的输出信号有了一个基本的认识,但本文的关键不是看看这个“心电图”,虽然系统采集并打印了数据,但系统并不知道所采集的“心电图”中,心率-心跳次数是多少,所以,接下来的关键就是设计一个处理方法,从“心电图”中获取心跳次数。
在我最初接触这个传感器时,我觉得要算出心率很简单啊:一分钟内统计来了多少个波峰不就知道心率了。然而事实上,这个方法并不奏效,它存在两个问题:1、如何统计“波峰”;2、测量一次心率,至少需要连续采样信号一分钟以上,效率太低。经过查阅资料及仔细的思考,我确立了这样一个计算思路:测量两次“波峰”之间的间隔时间,就可以推算一分钟内的心率。但是仍然存在一个问题:如何判断“波峰”?从波形中我们很容易想到:设定一个“阈值”,当数值大于该阈值时则记为一个波峰。但是,波峰阈值设定为多少合适呢?不同的人,或者同一个人不同时间或不同状态,得到的波峰值都不一致,这个方法还是不行,从上面的图中我们可以看到,每个波峰的峰值其实都不一致,其中一个波峰相对于其他的波峰“矮”了不少,如果简单地设定阈值,对于计算心率可能会出现很大的误差。那么,怎样才能准确地判断一个波峰呢?
通过观察波形,可以得到:一个波峰必然经历一个“单调递增”和一个“单调递减”的过程,因此我们可以在采样一次数据后,马上对“曲线”进行“求导”,也就是计算曲线的斜率,用本次的采样值减去上一次的采样值得出一个“导数”。曲线在单调递增的区间,导数是正的;在单调递减区间,导数是付的;在波峰的封顶,必然有一个导数为零的地方。实际上,导数为0的点是我们进行定时计算的最佳点,但这个点是很难采样到的,因此,只能把导数第一次“由正变负”的时刻作为计时开始及计算的特征点。另外,在“心电图”中我们还能看到,在“大波峰”的旁边,还伴随着一个“小波峰”,这个小波峰的导数也有同样的变化过程,而这个小波峰对于心率计算是没有作用的,但如果我们不作处理,就会对心率计算产生巨大影响。为了“去掉”小波峰,可以在采样中记录曲线的最大值和最小值,当系统检测到导数为负数时,参考当前采样值是否小于最大值且大于最小值加上一定的值,这样既可将小波峰的影响隔离掉。
下图中的定理说明了函数单调性与导数的关系:
基于上述方法,在第一次试验中,直接引入了AD采样的值进行计算,得出的结果是失败的,分析原因就是“导数”一直在正负切换。再次分析“心电图”发现,这是由于“心电图”的“毛刺”引起的,因此,在进行导数计算之前,还应该对AD采样的值进行滤波处理。借助之前对陀螺仪加速度计数据处理的经验,这里可以采用一阶滞后滤波的方法来处理,其实就是本次的输出值为上一次的输出值与本次测量值的加权和。下面看看滤波后的心电图,采样周期为10毫秒:
从上图中看到,经过滤波后的“心电图”变得光滑了很多,“毛刺”消失了,且“小波峰”也被“拉平”了很多,这给心率计算带来了极大的好处。下面给出基本“心电图”打印的代码及心率计算输出的代码:
下面是心率测量计算的输出显示:
在上面的代码中,以13号引脚上LED同步指示心跳-即LED随心跳闪烁。在测量过程中,如果系统检测到“导数”始终在正负5的范围内(该范围可以通过串口输出导数值确定)或AD采样滤波值低于最大峰值减去200,则开始计数,如果连续两秒符合这个条件,则系统会判定手指已移开或无心跳,此时会将曲线最大值与最小值进行“复位”处理。
下面是演示视频:
欢迎关注智造DIY创客空间,后续将陆续分享飞思卡尔、STM32的学习过程以及更多Arduino的趣味制作。我们一直致力于创客课程及项目开发实战的研究。暑期青少年创客活动课程继续!
地址:玉溪市红塔区红塔大道50号商务大楼305室智造DIY创客空间
电话:13577781795