pulsesensor传感器

PluseSensor传感器简介

PulseSensor 是一款用于心率测量、脉搏波形测量和 HRV 分析的光电反射式模拟传感器。将其佩戴于手指、耳垂等处,通过导线连接可将采集到的模拟信号传输给 Arduino、STM32 和 STC12C5A 等具有模拟采集功能的单片机并转换为数字信号,再通过单片机的简单计算后就可以得到心率数值,Pulse Sensor 是一款开源硬件,非常方便二次开发。

PluseSensor传感器参数

电路板直径:16mm
电路板厚度:1.2mm
LED 峰值波长:515nm(绿光)
供电电压:3.3~5v
检测信号类型:光反射信号(PPG)
输出信号类型:模拟信号
信号放大倍数:330 倍
输出信号范围:0~VCC
电流大小:~4ma(5v 下)
分辨率:1 bpm
采样率:500Hz(由程序设定)

PluseSensor传感器工作原理

传统的脉搏测量方法主要有三种:一是从心电信号中提取;二是从测量血压时压力传感器测到的波动来计算脉率;三是光电容积法。前两种方法提取信号都会限制病人的活动,如果长时间使用会增加病人生理和心理上的不舒适感。而光电容积法脉搏测量作为监护测量中最普遍的方法之一,其具有方法简单、佩戴方便、可靠性高等特点。
**光电容积法的基本原理是利用人体组织在血管搏动时造成透光率不同来进行脉搏测量的。**其使用的传感器由光源和光电变换器两部分组成,通过绑带或夹子固定在病人的手指或耳垂上。光源一般采用对动脉血中氧和血红蛋白有选择性的一定波长(500nm~700nm)的发光二极管。当光束透过人体外周血管,由于动脉搏动充血容积变化导致这束光的透光率发生改变,此时由光电变换器接收经人体组织反射的光线,转变为电信号并将其放大和输出。由于脉搏是随心脏的搏动而周期性变化的信号,动脉血管容积也周期性变化,因此光电变换器的电信号变化周期就是脉搏率。
根据相关文献和实验结果,560nm波长左右的波可以反映皮肤浅部微动脉信息,适合用来提取脉搏信号。本传感器采用了峰值波长为515nm的绿光LED,型号为AM2520,而光接收器采用了APDS-9008,这是一款环境光感受器,感受峰值波长为565nm,两者的峰值波长相近,灵敏度较高。此外,由于脉搏信号的频带一般在0.05~200Hz之间,信号幅度均很小,一般在毫伏级水平,容易受到各种信号干扰。在传感器后面使用了低通滤波器和由运放MCP6001构成的放大器,将信号放大了330倍,同时采用分压电阻设置直流偏置电压为电源电压的1/2,使放大后的信号可以很好地被单片机的AD采集到。

PluseSensor传感器连接方式

可以看到在传感器的背面,引出了三个脚,即传感器的接口, 红框中的 3 根线,标有S的为模拟信号输出线(最左边);标有+的为电源输入线(中间);标有-的为地线(最右边)。

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;
}


也在其他网站找到了一些程序,但还没理解。

烟雾传感器MQ-2

简介

MQ-2常用于家庭和工厂的气体泄漏监测装置,适宜于液化气、苯、烷、酒精、氢气、烟雾等的探测。故因此,MQ-2可以准确来说是一个多种气体探测器。
MQ-2的探测范围极其的广泛。它的优点:灵敏度高、响应快、稳定性好、寿命长、驱动电路简单。

工作原理

MQ-2型烟雾传感器属于二氧化锡半导体气敏材料,属于表面离子式N型半导体。处于200~300摄氏度时,二氧化锡吸附空气中的氧,形成氧的负离子吸附,使半导体中的电子密度减少,从而使其电阻值增加。当与烟雾接触时,如果晶粒间界处的势垒收到烟雾的调至而变化,就会引起表面导电率的变化。利用这一点就可以获得这种烟雾存在的信息,烟雾的浓度越大,导电率越大,输出电阻越低,则输出的模拟信号就越大。
使用的敏感材料是活性很高的金属氧化物半导体,传感器加热后,在不同气体浓度中电导率不同。使用简单的电路就可以将电导率的变化转换成与该气体浓度相对应的信号输出了。

模块介绍

MQ-2传感器对可燃气、烟雾等气体灵敏度高,基于MQ-2的烟雾传感器模块通过电路设计,提供了两种输出方式:
• 数字量输出:通过板载电位器设定浓度阈值,当检测到环境气体浓度超过阈值时,通过数字引脚DO输出低电平。
• 模拟量输出:浓度越高,AO引脚输出的电压值越高,通过ADC采集的模拟值越高。

电路图

烟雾传感器模块的VCC、GND分别连接到开发板的5V、GND。模块的AO引脚连接到开发板的模拟引脚A0,模块的DO引脚连接到开发板的数字引脚2。

程序

#include <Arduino.h>#define Sensor_AO A0
#define Sensor_DO 2unsigned int sensorValue = 0;void setup()
{pinMode(Sensor_DO, INPUT);Serial.begin(9600);
}void loop()
{sensorValue = analogRead(Sensor_AO);Serial.print("Sensor AD Value = ");Serial.println(sensorValue);if (digitalRead(Sensor_DO) == LOW){Serial.println("Alarm!");}delay(1000);
}

特性

1、MQ-2型传感器对天然气、液化石油气等烟雾有很高的灵敏度,尤其对烷类烟雾更为敏感,具有良好的抗干扰性,可准确排除有刺激性非可燃性烟雾的干扰信息。
2、MQ-2型传感器具有良好的重复性和长期的稳定性。初始稳定,响应时间短,长时间工作性能好。需要注意的是:在使用之前必须加热一段时间,否则其输出的电阻和电压不准确。
3、其检测可燃气体与烟雾的范围是100~10000ppm
(ppm为体积浓度。 1ppm=1立方厘米/1立方米)
4.电路设计电压范围宽,24V以下均可,加热电压5±0.2V

pulsesensor传感器和烟雾传感器MQ-2的学习笔记相关推荐

  1. 传感器技术—电容式传感器的测量转换电路(学习笔记七 补充)

    5.2 电容式传感器的测量转换电路 5.2.1 电桥电路 5.2.2 调频电路 5.2.3 运算放大器电路 5.2.4 二级管双T型电桥电路 5.3电容式传感器的运用 5.3.1 电容测厚仪 5.3. ...

  2. 心率传感器和烟雾传感器的学习了解

    第三次培训 心率传感器和烟雾传感器的学习了解 一.pulsesensor传感器 1.学习了解 Pulse Sensor是一款用来检测心率的传感器,使用方法还是比较方便的,用户只需要用手指按住传感器就可 ...

  3. VIO学习笔记(二)—— IMU 传感器

    学习资料是深蓝学院的<从零开始手写VIO>课程,对课程做一些记录,方便自己以后查询,如有错误还请斧正.由于习惯性心算公式,所以为了加深理解,文章公式采用手写的形式. VIO学习笔记(一)- ...

  4. CoppeliaSim学习笔记之差速小车的控制与传感器的驱动

    文章目录 1. 控制篇 2. 传感器篇 2.1 里程计仿真 2.2 TF 发布 2.3 激光雷达仿真 2.4 IMU 仿真   上一章节 CoppeliaSim学习笔记之仿真环境与小车模型的搭建 我们 ...

  5. 传感器自学笔记第十一章——三色RGB学习笔记+高感度声音检测模块+KY-010光遮断传感器+TCRT5000循迹传感器+倾斜模块

    作者:GWD 时间:2019.06.28 三色RGB学习笔记(开关量类传感器) 一.学习要点:无 二.手册分析(开关量传感器) 1.产品用途:RGB LED 模块由一个贴片全彩 LED 制成,通过 R ...

  6. ⑦ ESP8266 开发学习笔记_By_GYC 【ESP8266 驱动 DHT11 温湿度传感器】

    目录 一.准备材料 二.硬件连接 三.软件编程 1.修改工程名 2.添加组件 3.编程 4.反馈结果 5.核心代码 四.总结 ⑦ ESP8266 开发学习笔记_By_GYC [ESP8266 驱动 D ...

  7. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  8. MTI姿态传感器学习笔记

    MTi 学习笔记 1. 介绍 MTi 是集成了3D 磁力仪(3D 指南针)的完整的微型惯性测量 单元,带有一个能够实时计算滚动,俯仰和偏航的嵌入式处理器,能 够输出校准的3D 线性加速,旋转速度(陀螺 ...

  9. linux 应用层gpio中断_linux下GPIO中断驱动US100传感器--Apple的学习笔记

    一,前言 资源就的利用起来.linux下串口raw驱动(US100超声波)--Apple的学习笔记已经用US100玩了串口,US100还可以用GPIO和中断来玩.原理就是triq发送大于10us的高电 ...

最新文章

  1. 图书管理系统python源代码-Python实现图书管理系统
  2. 【财经】创业的10条定律 10大烦恼
  3. .NET Core2.1获取自定义配置文件信息
  4. 用Js的eval解析JSON中的注意点
  5. 『玩具装箱TOY 斜率优化DP』
  6. MySQL数据迁移到SQL Server
  7. 杨浦区阜盛农民工子弟小学见闻
  8. 某个知名技术论坛用户名和密码泄露(第一部分)
  9. 线性代数(9):线性正交
  10. 魔兽世界服务器卡 邮件寄不出去,魔兽世界怀旧服邮件收不到怎么办 WOW怀旧服邮件取不出来解决方法...
  11. Tableau 2020.2版本如何做环形图
  12. 太原理工大学计算机科学与技术老师 王颖,王华 - 太原理工大学 - 信息与计算机学院...
  13. 【English】十大词性之感叹词(感叹句)
  14. Gym - 100203A Ariel 暴力+位运算
  15. 个人使用CocosCreator开发小游戏路上的一些“坑坑洼洼”
  16. 汇编代码--立即数的概念与判断方法
  17. 微信小程序云开发沉浸式(透明)状态栏的实现(怎么写)
  18. 力扣:63. 不同路径 II
  19. 01-4 哪些指令不能重排:Happen-Before规则
  20. 移动版3060参数 移动版3060功耗 移动版3060相当于桌面版什么水平

热门文章

  1. 中科大-凸优化 笔记(lec44)-一些上界下界及梯度下降
  2. Parajumpers Gobi Royal Blue Ladies Winter down Coats
  3. i9-13900k服务器水冷定制提供强力驱动全网首发
  4. 考研数学练习题-2022年12月25日
  5. GameFramework教程✨三、流程
  6. 百度核心竞争力分析-天蝎座的李彦宏
  7. 川大计算机学院夏令营感谢,计算机专业暑期夏令营之行总结
  8. 配置iOS证书 (1)
  9. 第三局晋级赛数据分析 他来了他来了
  10. 3. 大数据存储与管理