** 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. 如何正确的获取两次峰值数据?

程序逻辑:

  1. if(halPulseSensorTouch())
  2. {
  3. if( (refPeak = halPulseSensorPeakFitting()) == 0 )
  4. goto RET;
  5. // First Beat
  6. if(halPulseSensorGetNextBeat(refPeak) == 0)
  7. goto RET;
  8. // Clear and Start Timer
  9. HAL_PULSE_SENSOR_TIMER_CLEAR();
  10. HAL_PULSE_SENSOR_TIMER_START();
  11. // Skip the peak value
  12. HAL_PULSE_SENSOR_DELAY_MS(200);
  13. // Second Beat
  14. secondBeat = halPulseSensorGetNextBeat(refPeak);
  15. // Stop Timer and get the delay time
  16. HAL_PULSE_SENSOR_TIMER_STOP();
  17. if(secondBeat == 0)
  18. goto RET;
  19. if( (beatTime = (uint16)HAL_PULSE_SENSOR_TIMER_GET_TIME()) == 0 )
  20. goto RET;
  21. if( (dat.heartRate = (uint16)60000 / beatTime) != 0 )
  22. dat.ok = TRUE;
  23. }

首先我们通过函数halPulseSensorTouch()检测是否手指是触摸在传感器上的,如果是我们才进行数据读取!

然后函数halPulseSensorPeakFitting()是用来获取ADC峰值的数据,这个函数会拟合出一个峰值的数值作为参考数值,

具体的做法是不断地获取峰值数据,然后筛选出相近的一组数值求取平均值,这个平均值将作为峰值参考数值!

然后确定一个峰值点,作为时间的起始点,这时候开启定时器,定时时间直到获取到下一个峰值点,这段时间就是一次心跳

的时长:

  1. // First Beat
  2. if(halPulseSensorGetNextBeat(refPeak) == 0)
  3. goto RET;

开启定时器并尝试获取第二个峰值:

  1. // Clear and Start Timer
  2. HAL_PULSE_SENSOR_TIMER_CLEAR();
  3. HAL_PULSE_SENSOR_TIMER_START();
  4. // Skip the peak value
  5. HAL_PULSE_SENSOR_DELAY_MS(200);  // <-- 获取一个峰值后,如果直接读取数据,可能瞬间读到的数据还是峰值数据,所以通过延时跳过峰值阶段
  6. // Second Beat
  7. secondBeat = halPulseSensorGetNextBeat(refPeak);  // <---------------- 获取第二个峰值
  8. // Stop Timer and get the delay time
  9. HAL_PULSE_SENSOR_TIMER_STOP();

剩下的数据就是读取这段时间定时器时长,然后计算出心率就OK了:

  1. if( (beatTime = (uint16)HAL_PULSE_SENSOR_TIMER_GET_TIME()) == 0 )
  2. goto RET;
  3. if( (dat.heartRate = (uint16)60000 / beatTime) != 0 )  // <------- 计算出心率
  4. dat.ok = TRUE;

判断手指是否按下的方法: 先获取一个ADC的数据作为参考点,然后连续再获取20个数据(数量可调整)作为采样点,如果说这些采样点有一半以上和参考点是相近的,可以认为是没有手指按下!

  1. static BOOL halPulseSensorTouch(void)
  2. {
  3. uint8 i;
  4. uint16 timeout = 0;
  5. uint8 cnt = 0;
  6. uint8 adc8Next;
  7. uint8 adc8;
  8. /* First touch or Realease */
  9. while( (adc8 = HAL_PULSE_SENSOR_ADC8()) < HAL_PULSE_SENSOR_TOUCH_ADC8 ||
  10. adc8 > HAL_PULSE_SENSOR_REALEASE_ADC8)
  11. {
  12. HAL_PULSE_SENSOR_DELAY_MS(10);
  13. if(++timeout >= 100)
  14. goto ERROR;
  15. }
  16. /* Touching */
  17. adc8 = HAL_PULSE_SENSOR_ADC8();
  18. for(i = 0; i < HAL_PULSE_SENSOR_SPACING_CMP_TIMES; i++)
  19. {
  20. HAL_PULSE_SENSOR_DELAY_MS(20);
  21. adc8Next = HAL_PULSE_SENSOR_ADC8();
  22. if( ( adc8Next >= adc8 && adc8Next < (adc8 + HAL_PULSE_SENSOR_SPACING) ) ||
  23. ( adc8Next < adc8 && (adc8Next + HAL_PULSE_SENSOR_SPACING) > adc8 )  )
  24. {
  25. continue;
  26. }
  27. cnt++;
  28. }
  29. if(cnt >= HAL_PULSE_SENSOR_SPACING_CMP_TIMES/2)
  30. return TRUE;
  31. ERROR:
  32. return FALSE;
  33. }

获取峰值的方法: 由于人的心率是有范围的,正常人是60~100次/分钟,也有可能50、120这样,如果我们取一个极限值30次/Min,也就是说两个峰值的时长是2秒,再极端点算3秒,时长可自行调整,也就是说3秒内一定最少有一个峰值数据出现,我们只需要在这段时间内不断的获取ADC数据然后取最大值即可!当然这个过程还需要考虑其他情况,比如手指突然松开等等。

  1. static uint8 halPulseSensorGetPeak(void)
  2. {
  3. uint16 i;
  4. uint8  adc8;
  5. uint8  adc8Peak = 0;
  6. /* Get and compare the ADC value in 3 Second */
  7. for(i = 0; i < 300; i++)
  8. {
  9. HAL_PULSE_SENSOR_DELAY_MS(10);
  10. adc8 = HAL_PULSE_SENSOR_ADC8();
  11. if(adc8 >= adc8Peak)
  12. {
  13. adc8Peak = adc8;
  14. }
  15. }
  16. if(adc8Peak <= HAL_PULSE_SENSOR_TOUCH_ADC8 ||
  17. adc8Peak >= HAL_PULSE_SENSOR_REALEASE_ADC8)
  18. {
  19. adc8Peak = 0;
  20. }
  21. return adc8Peak;
  22. }

拟合峰值数据的方法:可以在每次获取心率时,由于每次都需要获取峰值来作为参考峰值数据,所以我们可以保存起来,比如保存10个数据,然后把这10个数据中相近的数值保留起来,其他删除等到下次更新,直到10个数据都是相近数据,然后我们可以算出平均值,这个平均值就会一直作为我们的参考峰值数据了!

  1. static uint8 halPulseSensorPeakFitting(void)
  2. {
  3. uint8 peak;
  4. uint8 index;
  5. for(index = 0; index < HAL_PULSE_SENSOR_PEAK_LEN; index++)
  6. {
  7. if(halPulseSensorPeak_g[index] == 0)
  8. break;
  9. }
  10. if(index < HAL_PULSE_SENSOR_PEAK_LEN)
  11. {
  12. peak = halPulseSensorGetPeak();
  13. halPulseSensorPeak_g[index] = peak;
  14. }
  15. else
  16. {
  17. for(uint8 i = 0; i < HAL_PULSE_SENSOR_PEAK_LEN; i++)
  18. {
  19. uint8 cnt = 0;
  20. if( halPulseSensorPeak_g[i] == 0 )
  21. continue;
  22. for(uint8 j = 0; j < HAL_PULSE_SENSOR_PEAK_LEN; j++)
  23. {
  24. if( halPulseSensorPeak_g[j] == 0 )
  25. continue;
  26. if( halPulseSensorPeak_g[i] < (halPulseSensorPeak_g[j] - HAL_PULSE_SENSOR_FITTING_ERR)  ||
  27. halPulseSensorPeak_g[i] > (halPulseSensorPeak_g[j] + HAL_PULSE_SENSOR_FITTING_ERR) )
  28. {
  29. cnt++;
  30. }
  31. }
  32. if(cnt >= (HAL_PULSE_SENSOR_PEAK_LEN/2))
  33. halPulseSensorPeak_g[i] = 0;
  34. }
  35. uint16 tmp = 0;
  36. uint8  tmpCnt = 0;
  37. for(uint8 i = 0; i < HAL_PULSE_SENSOR_PEAK_LEN; i++)
  38. {
  39. if( halPulseSensorPeak_g[i] == 0 )
  40. continue;
  41. tmp += halPulseSensorPeak_g[i];
  42. tmpCnt++;
  43. }
  44. peak = (uint8)(tmp/tmpCnt);
  45. }
  46. return peak;
  47. }

根据参考峰值数据获取心跳峰值点方法:我们会设置一段时间,比如3秒,然后在这段时间内不断的获取数据,如果获取的数据和参考峰值数据相近,我们会标记为峰值点记为A,然后继续获取,如果数据比A大,那么更新A,直到数据比A小,也就是呈现出下降趋势,说明已经到峰值点了,那么我们就会停止获取数据的动作并立即返回!

  1. static uint8 halPulseSensorGetNextBeat(uint8 refPeak)
  2. {
  3. uint16 i;
  4. uint8 adc8, peak = 0;
  5. for(i = 0; i < 300; i++)
  6. {
  7. HAL_PULSE_SENSOR_DELAY_MS(10);
  8. adc8 = HAL_PULSE_SENSOR_ADC8();
  9. if( peak == 0 &&
  10. ( adc8 < (refPeak - HAL_PULSE_SENSOR_HEARTBEAT_ERR)  ||
  11. adc8 > (refPeak + HAL_PULSE_SENSOR_HEARTBEAT_ERR) ) )
  12. {
  13. continue;
  14. }
  15. if(adc8 >= peak)
  16. {
  17. peak = adc8;
  18. continue;
  19. }
  20. return peak;
  21. }
  22. return 0;
  23. }

Pulse Sensor 心率传感器CC2530源码相关推荐

  1. 采用arduino UNO和pulse sensor心率传感器进行心率测量

    转自:anning86525的博客 网址:https://blog.csdn.net/anning86525/article/details/80096816 1.准备工作 首先阅读一遍我们编写的pu ...

  2. pulse sensor心率传感器

    pulse sensor心率传感器 脉搏传感器本质上是一个光电容积描记器,用于无创心率监测的医疗设备.有时,光电容积描记器可以测量血氧水平,有时却不能.来自光电容积描记器的心脏脉搏信号是电压的模拟波动 ...

  3. STM32cube之Pulse Sensor脉搏传感器测试

    首先介绍一下Pulse Sensor PulseSensor 脉搏传感器介绍 基本参数 供电电压: 3.3~5V 检测信号类型: 光反射信号(PPG) 输出信号类型: 模拟信号 输出信号大小: 0~V ...

  4. 水位传感器c语言程序,简单水位报警器(水浸传感器)单片机源码

    简单水位报警器(水浸传感器)单片机源码: [code]#include#define uchar unsigned char #define uint unsigned int sbit f=P3^7 ...

  5. 2014年3月份源码索引贴

    [eoe源码索引]2014年3月份源码索引贴 分类: android2014-07-07 22:49 278人阅读 评论(0) 收藏 举报 本帖索引了3月份eoe源码区大部分的源码,几个不能运行的源码 ...

  6. 【eoe源码索引】2014年3月份源码索引贴

    本帖索引了3月份eoe源码区大部分的源码,几个不能运行的源码没有去索引,整理东西真心很耗时,帖子整理了一晚上,大半夜发帖有点迷糊,如果有遗漏请私信我.另外这个索引贴本来也是几天前给tms承诺的,一直拖 ...

  7. android源码集合989个实例 (从网上摘抄,在此记录下)

    需要批量打包下载请联系QQ:50841662 ├-地图相关 Android bikeroute自行车导航源码.rar:  http://www.t00y.com/file/64335654 Andro ...

  8. 第一期 android源码集合987个实例(从网上摘抄,在此记录下)

    ├-地图相关 Android bikeroute自行车导航源码.rar:  http://www.t00y.com/file/64335654 Android Gps Test源码.rar:  htt ...

  9. android源码集合(从网上摘抄,在此记录下)

    *************************************************************************************************** ...

最新文章

  1. mongodb的几种启动方法
  2. MyBatis(四)MyBatis插件原理
  3. linux+nginx+mysql+php系统修改文件上传大小限制
  4. Java加入背景音乐
  5. linux树莓派 ssh密码,树莓派之SSH连接经验
  6. 数据机构与算法:书籍介绍
  7. c#程序实现调用迅雷
  8. java插件已崩溃怎么处理_java.lang.IllegalArgumentException:插件已初始化
  9. ssm+安卓APP校园学生疫情防范监控系统毕业设计源码281444
  10. springboot+微信小程序点餐系统的设计与实现毕业设计源码221541
  11. android app邀请码,还在用邀请码邀请注册吗?落后咯!!!我家APP自带邀请码的
  12. 步进电机之步进电机驱动器使用说明
  13. camera内存优化
  14. Mindmanager2018 官方中文版下载
  15. CentOS 7账号密码忘了怎么办?
  16. 员工内斗,管理者要不要插手?
  17. 华为AC旁路二层组网隧道转发示例
  18. 数据库实验六:完整性语言实验
  19. 【汇总】行为识别、时序行为检测、弱监督行为检测、时空行为定位论文代码(持续更新!!!)
  20. 实用工具—SimpleMind 和Sublime Text

热门文章

  1. Cisco Nexus 之“ip redirect”
  2. [教你做小游戏] 只用几行原生JS,写一个函数,播放音效、播放BGM、切换BGM
  3. 区块链安全100问 |​ 第四篇:保护数字钱包安全,防止资产被盗
  4. 第四届拍拍贷魔镜杯冠军方案分享
  5. 深度学习——多GPU训练代码实现
  6. magic--创建魔方矩阵
  7. 没什么卵用的 ICN 论文
  8. 渥尔曼电路设计_渥尔曼自举电路
  9. 【一步步学OpenGL 6】 -《平移变换》
  10. idea中补全变量快捷键_我最常用的Intellij IDEA快捷键