当前位置: 首页 > news >正文

PulseSensor心率传感器详解(STM32)

目录

一、介绍

二、传感器原理

1.接线图

2.引脚描述

3.工作原理:光电容积法原理

4.工作原理:心率采样数据处理算法

三、程序设计

main.c文件

adcx.h文件

adc.c文件

四、实验效果 

五、资料获取

项目分享


一、介绍

        PulseSensor传感器是一种基于光学原理的心率传感器,可以通过测量心脏跳动时的血液流动情况来检测心率。它由一个LED和一个光敏元件组成,LED发出的光线透过皮肤照射到血液中,光敏元件接收反射回来的光线,然后将光信号转换为电信号,从而测量出心率。

以下是土壤湿度传感器的参数:

供电电压 

DC:3.3~5V

检测信号类型

光反射信号(PPG)

输出信号类型

模拟信号

LED峰值波长

515nm(绿光)

信号放大倍数

330

输出信号范围

0~VCC

电流大小

~4ma

 

哔哩哔哩视频

PulseSensor心率传感器详解(STM32)

(资料分享见文末) 

二、传感器原理

1.接线图

         传感器只有三个引脚,分别为信号输出 S 脚 、电源正极 VCC 以及电源负极 GND,供电电压为 3.3V - 5V,可通过杜邦线与开发板连接。上电后, 传感器会不断从 S 脚输出采集到的电压模拟值。

2.引脚描述

引脚名称

描述

S

脉搏信号输出

+

5V(3.3V)电源输入

-

GND

3.工作原理:光电容积法原理

        光电容积法的基本原理是利用人体组织在血管搏动时造成透光率不同来进行脉搏测量的。光源一般采用对动脉血有选择性的特定波长的发光二极管(515nm的绿光)。当光束透过人体外周血管,由于动脉搏动充血容积变化导致这束光的透过光率发生改变,此时由光电变换器接收人体组织反射的光线,转变为电信号并将其放大和输出。由于脉搏是随心脏的搏动而周期性变化的信号,动脉血管容积也周期性变化,因此光电变换器的电信号变化周期就是脉搏率。

4.工作原理:心率采样数据处理算法

        测量相邻两次脉搏的时间间隔,再用一分钟除以这个间隔得出心率。

IBI: 相邻两次脉搏的时间间隔(单位:ms),BPM:心率,一分钟内的心跳次数且:BPM = 60 / IBI。我们的最终目的就是要求出 IBI 的值,并通过 IBI 计算出实时心率。其核心操作在于识别一个脉搏信号

①选取阈值

首先动态计算出参考阈值,然后用用阈值对信号判定、识别一个波峰

② 计算特征点

选取信号上升到振幅的一半作为特征点,我们可以捕获这个特征点作为一个有效脉搏的标志,然后计算 IBI

三、程序设计

1.使用STM32F103C8T6读取PulseSensor心率传感器采集的数据

2.将读取得到的温湿度数据同时在OLED上显示

PulseSensor

PA0

OLED_SCL

PB11

OLED_SDA

PB10

串口

串口1

main.c文件

#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "adcx.h"
#include "timer.h"/*****************辰哥单片机设计******************STM32* 项目			:	PulseSensor心率传感器实验                     * 版本			: V1.0* 日期			: 2024.8.19* MCU			:	STM32F103C8T6* 接口			:	参看ADCX.h							* BILIBILI	:	辰哥单片机设计* CSDN			:	辰哥单片机设计* 作者			:	辰哥 **********************BEGIN***********************/extern _Bool Timer_Flag ;			//时间到 标准位
extern _Bool update_flag;			//更新标志变量//要写入到STM32 FLASH的字符串数组
u8 TEXT_Buffer[]={"0000000"};
#define SIZE sizeof(TEXT_Buffer)	 	//数组长度
//#define FLASH_SAVE_ADDR  0X08020000 	//设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)
#define FLASH_SAVE_ADDR  0X0800f400 	//设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)int main(void)
{ unsigned char p[16]=" ";u8 datatemp[SIZE];	_Bool Heart_OK = 0;				//读取到正确心率标志位unsigned char Heart = 0;		//心率值SystemInit();//配置系统时钟为72M	delay_init(72);LED_Init();LED_On();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);//设置中断优先级分组为组3:2位抢占优先级,2位响应优先级USART1_Config();//串口初始化OLED_Init();printf("Start \n");delay_ms(1000);//显示“血氧:”OLED_ShowChinese(0,0,0,16,1);OLED_ShowChinese(16,0,1,16,1);OLED_ShowChar(32,0,':',16,1);ADCx_Init();TIM3_Int_Init(1999,71);			//定时2ms中断TIM2_Int_Init(199,7199);		//10Khz的计数频率,计数到500为20ms //  while (1)
//  {
//		LED_Toggle();//		printf("光照强度: %d\r\n",light);
//		
//		OLED_ShowNum(80,0,light,3,16,1);//		delay_ms(500);
//  }while(1){	if(Timer_Flag==1)					//500ms到 读取数据{Timer_Flag = 0;					//清除标志TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE ); 						//使能指定的TIM3中断,允许更新中断TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE ); 						//使能指定的TIM3中断,允许更新中断		delay_ms(500);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); 						//使能指定的TIM3中断,允许更新中断TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); 						//使能指定的TIM3中断,允许更新中断TIM_Cmd(TIM2, ENABLE);  		//使能TIMx	if (QS == true)					//读取到了心率信号{			QS = false; 				//清除标志 等待下一次读取if(BPM>HEART_MIN_ERROR&&BPM<HEART_MAX_ERROR)		//读取到的值再正常心率区间 40-160内{Heart_OK = 1;			//标志位置一Heart = BPM;			//心率传递给Heart}else{Heart_OK = 0;			//标志位清零Heart = 0;				//设置为0}	}}delay_ms(20);	if(Heart_OK==1)								//读取到正确心率{OLED_ShowNum(40,0,Heart,3,16,1);}else{OLED_ShowString(32,0,":---r/min",16,1);}}	
}

adcx.h文件

#ifndef _ADCX_H_
#define _ADCX_H_
#include "stm32f10x.h"                  // Device header/*****************辰哥单片机设计******************STM32* 项目			:	PulseSensor心率传感器实验                     * 版本			: V1.0* 日期			: 2024.8.19* MCU			:	STM32F103C8T6* 接口			:	参看ADCX.h							* BILIBILI	:	辰哥单片机设计* CSDN			:	辰哥单片机设计* 作者			:	辰哥 **********************BEGIN***********************/// ADC 编号选择
// 可以是 ADC1/2/3
#define    ADCx                          ADC1
#define    ADC_CLK                       RCC_APB2Periph_ADC1#define		PulseSensor_GPIO_CLK							RCC_APB2Periph_GPIOA
#define 	PulseSensor_GPIO_PORT							GPIOA
#define 	PulseSensor_GPIO_PIN							GPIO_Pin_0void ADCx_Init(void);
u16  Get_Adc(u8 ch); 
u16  Get_Adc_Average(u8 ch,u8 times); #endif

adc.c文件

#include "adcx.h"
#include "delay.h"/*****************辰哥单片机设计******************STM32* 项目			:	PulseSensor心率传感器实验                     * 版本			: V1.0* 日期			: 2024.8.19* MCU			:	STM32F103C8T6* 接口			:	参看ADCX.h							* BILIBILI	:	辰哥单片机设计* CSDN			:	辰哥单片机设计* 作者			:	辰哥 **********************BEGIN***********************///初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3																	   
void  ADCx_Init(void)
{ 	ADC_InitTypeDef   ADC_InitStructure;GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(PulseSensor_GPIO_CLK|ADC_CLK,ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);//PA0GPIO_InitStructure.GPIO_Pin=PulseSensor_GPIO_PIN;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;GPIO_Init(PulseSensor_GPIO_PORT,& GPIO_InitStructure);ADC_DeInit(ADCx);ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADCx和ADC2工作在独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE;	      //模数转换工作在单通道模式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
//ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	  //转换由软件而不是外部触发启动ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;//选择TIM3作为外部触发源ADC_InitStructure.ADC_DataAlign= ADC_DataAlign_Right;                	//ADC数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1;	                              //顺序进行规则转换的ADC通道的数目ADC_Init(ADCx, &ADC_InitStructure);	ADC_ExternalTrigConvCmd(ADCx,ENABLE);//采用外部触发ADC_RegularChannelConfig(ADCx, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);//adc转换时间21usADC_Cmd(ADCx, ENABLE);ADC_ResetCalibration(ADCx);									//复位校准while(ADC_GetResetCalibrationStatus(ADCx));	//等待校准结束,校准结束状态为RESETADC_StartCalibration(ADCx);									//AD校准while(ADC_GetCalibrationStatus(ADCx));			//等待校准结束	}				  
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{//设置指定ADC的规则组通道,一个序列,采样时间ADC_RegularChannelConfig(ADCx, ch, 1, ADC_SampleTime_239Cycles5 );	//ADCx,ADC通道,采样时间为239.5周期	  			    ADC_SoftwareStartConvCmd(ADCx, ENABLE);		//使能指定的ADCx的软件转换启动功能	while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC ));//等待转换结束return ADC_GetConversionValue(ADCx);	//返回最近一次ADCx规则组的转换结果
}u16 Get_Adc_Average(u8 ch,u8 times)
{u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}return temp_val/times;
} 	 

四、实验效果 

五、资料获取

项目分享

http://www.lryc.cn/news/434407.html

相关文章:

  • NISP 一级 | 3.1 网络基础知识
  • 模拟网络丢包常用方法以及工具
  • ABC 370 E - Avoid K Partition
  • C++: set与map容器的介绍与使用
  • 单片机-STM32 看门狗(八)
  • iOS 18.1将上线新功能,可惜这波国内的小伙伴无缘了
  • MySQL中DML操作(二)
  • LLMs技术 | 整合Ollama实现本地LLMs调用
  • 【C-实践】文件服务器(3.0)
  • LeetCode 2181.合并零之间的节点
  • 千益畅行,共享旅游卡,引领旅游新潮流
  • K均值聚类
  • 【Ubuntu】安装常用软件包
  • 探索全光网技术 | 全光网产品解决方案整理-(宇洪科技)
  • 资料分析(2)
  • 百元以下蓝牙耳机性价比之王品牌?四大高能性价比机型推荐
  • 考场考生行为检测数据集 7000张 带标注 voc yolo
  • 深度学习算法,该如何深入,举例说明
  • 舵机的原理及应用
  • Nacos与Eureka--微服务注册中心
  • Android 调试桥——ADB
  • 闲鱼放弃成为淘宝复刻版了吗?上线学生专属交易交流版块“学生鱼”频道
  • 【学习笔记11】如何找到twitter中自己的cookie?
  • 新办建筑智能化专项乙级设计资质,郑州企业需要达到哪些要求?
  • 项目管理:项目执行过程中的控制点——基线
  • NVIDIA驱动学习
  • 小小GCD、LCM拿下拿下
  • 如何集成Android平台GB28181设备接入模块?
  • mysql——关于表的增删改查(CRUD)
  • docker 重启容器且修改服务映射端口