Pulse Sensor 心率传感器CC2530源码
** ZigBee、NBIOT等无线通信技术交流学习,可以加入QQ技术交流群:575036716
可以到CSDN的下载版块下载该源码包: 点击打开链接
最近有朋友需要通过Pulse Sensor也就是心率传感器结合ZigBee进行开发,ZigBee是Ti的方案,主控是CC2530,因此写了这款传感器的驱动程序!
Pulse Sensor是一款用来检测心率的传感器,使用方法还是比较方便的,用户只需要用手指按住传感器就可以,传感器的实物图如下:
正面 背面
Pulse Sensor检测原理是通过发射光源,然后根据光源返回的效果输出ADC数据。由于手指上布满毛细血管,而毛细血管会随着心率而跳动,这就导致传感器发射和接收光的效果不同,从而达到ADC输出效果不同,比如下图就是ADC的输出图:
因此检测心率的方式很简单:测出两个ADC峰值间的时长,假设这个时长为T,单位是毫秒,那么1分钟的心率假设为S,则:
S = 60000/T 次/秒
程序设计需要考虑的地方:
1. 传感器检测时,必须手指按在传感器上,否则检测的数据是不对的,所以首先要判断传感器是否有手指接触。
2. 如何正确的获取两次峰值数据?
程序逻辑:
- if(halPulseSensorTouch())
- {
- if( (refPeak = halPulseSensorPeakFitting()) == 0 )
- goto RET;
- // First Beat
- if(halPulseSensorGetNextBeat(refPeak) == 0)
- goto RET;
- // Clear and Start Timer
- HAL_PULSE_SENSOR_TIMER_CLEAR();
- HAL_PULSE_SENSOR_TIMER_START();
- // Skip the peak value
- HAL_PULSE_SENSOR_DELAY_MS(200);
- // Second Beat
- secondBeat = halPulseSensorGetNextBeat(refPeak);
- // Stop Timer and get the delay time
- HAL_PULSE_SENSOR_TIMER_STOP();
- if(secondBeat == 0)
- goto RET;
- if( (beatTime = (uint16)HAL_PULSE_SENSOR_TIMER_GET_TIME()) == 0 )
- goto RET;
- if( (dat.heartRate = (uint16)60000 / beatTime) != 0 )
- dat.ok = TRUE;
- }
首先我们通过函数halPulseSensorTouch()检测是否手指是触摸在传感器上的,如果是我们才进行数据读取!
然后函数halPulseSensorPeakFitting()是用来获取ADC峰值的数据,这个函数会拟合出一个峰值的数值作为参考数值,
具体的做法是不断地获取峰值数据,然后筛选出相近的一组数值求取平均值,这个平均值将作为峰值参考数值!
然后确定一个峰值点,作为时间的起始点,这时候开启定时器,定时时间直到获取到下一个峰值点,这段时间就是一次心跳
的时长:
- // First Beat
- if(halPulseSensorGetNextBeat(refPeak) == 0)
- goto RET;
开启定时器并尝试获取第二个峰值:
- // Clear and Start Timer
- HAL_PULSE_SENSOR_TIMER_CLEAR();
- HAL_PULSE_SENSOR_TIMER_START();
- // Skip the peak value
- HAL_PULSE_SENSOR_DELAY_MS(200); // <-- 获取一个峰值后,如果直接读取数据,可能瞬间读到的数据还是峰值数据,所以通过延时跳过峰值阶段
- // Second Beat
- secondBeat = halPulseSensorGetNextBeat(refPeak); // <---------------- 获取第二个峰值
- // Stop Timer and get the delay time
- HAL_PULSE_SENSOR_TIMER_STOP();
剩下的数据就是读取这段时间定时器时长,然后计算出心率就OK了:
- if( (beatTime = (uint16)HAL_PULSE_SENSOR_TIMER_GET_TIME()) == 0 )
- goto RET;
- if( (dat.heartRate = (uint16)60000 / beatTime) != 0 ) // <------- 计算出心率
- dat.ok = TRUE;
判断手指是否按下的方法: 先获取一个ADC的数据作为参考点,然后连续再获取20个数据(数量可调整)作为采样点,如果说这些采样点有一半以上和参考点是相近的,可以认为是没有手指按下!
- static BOOL halPulseSensorTouch(void)
- {
- uint8 i;
- uint16 timeout = 0;
- uint8 cnt = 0;
- uint8 adc8Next;
- uint8 adc8;
- /* First touch or Realease */
- while( (adc8 = HAL_PULSE_SENSOR_ADC8()) < HAL_PULSE_SENSOR_TOUCH_ADC8 ||
- adc8 > HAL_PULSE_SENSOR_REALEASE_ADC8)
- {
- HAL_PULSE_SENSOR_DELAY_MS(10);
- if(++timeout >= 100)
- goto ERROR;
- }
- /* Touching */
- adc8 = HAL_PULSE_SENSOR_ADC8();
- for(i = 0; i < HAL_PULSE_SENSOR_SPACING_CMP_TIMES; i++)
- {
- HAL_PULSE_SENSOR_DELAY_MS(20);
- adc8Next = HAL_PULSE_SENSOR_ADC8();
- if( ( adc8Next >= adc8 && adc8Next < (adc8 + HAL_PULSE_SENSOR_SPACING) ) ||
- ( adc8Next < adc8 && (adc8Next + HAL_PULSE_SENSOR_SPACING) > adc8 ) )
- {
- continue;
- }
- cnt++;
- }
- if(cnt >= HAL_PULSE_SENSOR_SPACING_CMP_TIMES/2)
- return TRUE;
- ERROR:
- return FALSE;
- }
获取峰值的方法: 由于人的心率是有范围的,正常人是60~100次/分钟,也有可能50、120这样,如果我们取一个极限值30次/Min,也就是说两个峰值的时长是2秒,再极端点算3秒,时长可自行调整,也就是说3秒内一定最少有一个峰值数据出现,我们只需要在这段时间内不断的获取ADC数据然后取最大值即可!当然这个过程还需要考虑其他情况,比如手指突然松开等等。
- static uint8 halPulseSensorGetPeak(void)
- {
- uint16 i;
- uint8 adc8;
- uint8 adc8Peak = 0;
- /* Get and compare the ADC value in 3 Second */
- for(i = 0; i < 300; i++)
- {
- HAL_PULSE_SENSOR_DELAY_MS(10);
- adc8 = HAL_PULSE_SENSOR_ADC8();
- if(adc8 >= adc8Peak)
- {
- adc8Peak = adc8;
- }
- }
- if(adc8Peak <= HAL_PULSE_SENSOR_TOUCH_ADC8 ||
- adc8Peak >= HAL_PULSE_SENSOR_REALEASE_ADC8)
- {
- adc8Peak = 0;
- }
- return adc8Peak;
- }
拟合峰值数据的方法:可以在每次获取心率时,由于每次都需要获取峰值来作为参考峰值数据,所以我们可以保存起来,比如保存10个数据,然后把这10个数据中相近的数值保留起来,其他删除等到下次更新,直到10个数据都是相近数据,然后我们可以算出平均值,这个平均值就会一直作为我们的参考峰值数据了!
- static uint8 halPulseSensorPeakFitting(void)
- {
- uint8 peak;
- uint8 index;
- for(index = 0; index < HAL_PULSE_SENSOR_PEAK_LEN; index++)
- {
- if(halPulseSensorPeak_g[index] == 0)
- break;
- }
- if(index < HAL_PULSE_SENSOR_PEAK_LEN)
- {
- peak = halPulseSensorGetPeak();
- halPulseSensorPeak_g[index] = peak;
- }
- else
- {
- for(uint8 i = 0; i < HAL_PULSE_SENSOR_PEAK_LEN; i++)
- {
- uint8 cnt = 0;
- if( halPulseSensorPeak_g[i] == 0 )
- continue;
- for(uint8 j = 0; j < HAL_PULSE_SENSOR_PEAK_LEN; j++)
- {
- if( halPulseSensorPeak_g[j] == 0 )
- continue;
- if( halPulseSensorPeak_g[i] < (halPulseSensorPeak_g[j] - HAL_PULSE_SENSOR_FITTING_ERR) ||
- halPulseSensorPeak_g[i] > (halPulseSensorPeak_g[j] + HAL_PULSE_SENSOR_FITTING_ERR) )
- {
- cnt++;
- }
- }
- if(cnt >= (HAL_PULSE_SENSOR_PEAK_LEN/2))
- halPulseSensorPeak_g[i] = 0;
- }
- uint16 tmp = 0;
- uint8 tmpCnt = 0;
- for(uint8 i = 0; i < HAL_PULSE_SENSOR_PEAK_LEN; i++)
- {
- if( halPulseSensorPeak_g[i] == 0 )
- continue;
- tmp += halPulseSensorPeak_g[i];
- tmpCnt++;
- }
- peak = (uint8)(tmp/tmpCnt);
- }
- return peak;
- }
根据参考峰值数据获取心跳峰值点方法:我们会设置一段时间,比如3秒,然后在这段时间内不断的获取数据,如果获取的数据和参考峰值数据相近,我们会标记为峰值点记为A,然后继续获取,如果数据比A大,那么更新A,直到数据比A小,也就是呈现出下降趋势,说明已经到峰值点了,那么我们就会停止获取数据的动作并立即返回!
- static uint8 halPulseSensorGetNextBeat(uint8 refPeak)
- {
- uint16 i;
- uint8 adc8, peak = 0;
- for(i = 0; i < 300; i++)
- {
- HAL_PULSE_SENSOR_DELAY_MS(10);
- adc8 = HAL_PULSE_SENSOR_ADC8();
- if( peak == 0 &&
- ( adc8 < (refPeak - HAL_PULSE_SENSOR_HEARTBEAT_ERR) ||
- adc8 > (refPeak + HAL_PULSE_SENSOR_HEARTBEAT_ERR) ) )
- {
- continue;
- }
- if(adc8 >= peak)
- {
- peak = adc8;
- continue;
- }
- return peak;
- }
- return 0;
- }
Pulse Sensor 心率传感器CC2530源码相关推荐
- 采用arduino UNO和pulse sensor心率传感器进行心率测量
转自:anning86525的博客 网址:https://blog.csdn.net/anning86525/article/details/80096816 1.准备工作 首先阅读一遍我们编写的pu ...
- pulse sensor心率传感器
pulse sensor心率传感器 脉搏传感器本质上是一个光电容积描记器,用于无创心率监测的医疗设备.有时,光电容积描记器可以测量血氧水平,有时却不能.来自光电容积描记器的心脏脉搏信号是电压的模拟波动 ...
- STM32cube之Pulse Sensor脉搏传感器测试
首先介绍一下Pulse Sensor PulseSensor 脉搏传感器介绍 基本参数 供电电压: 3.3~5V 检测信号类型: 光反射信号(PPG) 输出信号类型: 模拟信号 输出信号大小: 0~V ...
- 水位传感器c语言程序,简单水位报警器(水浸传感器)单片机源码
简单水位报警器(水浸传感器)单片机源码: [code]#include#define uchar unsigned char #define uint unsigned int sbit f=P3^7 ...
- 2014年3月份源码索引贴
[eoe源码索引]2014年3月份源码索引贴 分类: android2014-07-07 22:49 278人阅读 评论(0) 收藏 举报 本帖索引了3月份eoe源码区大部分的源码,几个不能运行的源码 ...
- 【eoe源码索引】2014年3月份源码索引贴
本帖索引了3月份eoe源码区大部分的源码,几个不能运行的源码没有去索引,整理东西真心很耗时,帖子整理了一晚上,大半夜发帖有点迷糊,如果有遗漏请私信我.另外这个索引贴本来也是几天前给tms承诺的,一直拖 ...
- android源码集合989个实例 (从网上摘抄,在此记录下)
需要批量打包下载请联系QQ:50841662 ├-地图相关 Android bikeroute自行车导航源码.rar: http://www.t00y.com/file/64335654 Andro ...
- 第一期 android源码集合987个实例(从网上摘抄,在此记录下)
├-地图相关 Android bikeroute自行车导航源码.rar: http://www.t00y.com/file/64335654 Android Gps Test源码.rar: htt ...
- android源码集合(从网上摘抄,在此记录下)
*************************************************************************************************** ...
最新文章
- mongodb的几种启动方法
- MyBatis(四)MyBatis插件原理
- linux+nginx+mysql+php系统修改文件上传大小限制
- Java加入背景音乐
- linux树莓派 ssh密码,树莓派之SSH连接经验
- 数据机构与算法:书籍介绍
- c#程序实现调用迅雷
- java插件已崩溃怎么处理_java.lang.IllegalArgumentException:插件已初始化
- ssm+安卓APP校园学生疫情防范监控系统毕业设计源码281444
- springboot+微信小程序点餐系统的设计与实现毕业设计源码221541
- android app邀请码,还在用邀请码邀请注册吗?落后咯!!!我家APP自带邀请码的
- 步进电机之步进电机驱动器使用说明
- camera内存优化
- Mindmanager2018 官方中文版下载
- CentOS 7账号密码忘了怎么办?
- 员工内斗,管理者要不要插手?
- 华为AC旁路二层组网隧道转发示例
- 数据库实验六:完整性语言实验
- 【汇总】行为识别、时序行为检测、弱监督行为检测、时空行为定位论文代码(持续更新!!!)
- 实用工具—SimpleMind 和Sublime Text
热门文章
- Cisco Nexus 之“ip redirect”
- [教你做小游戏] 只用几行原生JS,写一个函数,播放音效、播放BGM、切换BGM
- 区块链安全100问 |​ 第四篇:保护数字钱包安全,防止资产被盗
- 第四届拍拍贷魔镜杯冠军方案分享
- 深度学习——多GPU训练代码实现
- magic--创建魔方矩阵
- 没什么卵用的 ICN 论文
- 渥尔曼电路设计_渥尔曼自举电路
- 【一步步学OpenGL 6】 -《平移变换》
- idea中补全变量快捷键_我最常用的Intellij IDEA快捷键