MAX30102 血氧调试笔记
一、血氧测量原理
1.1 PPG波形介绍
血氧饱和度(英语:Oxygen saturation),或称血氧浓度,是指血中氧饱和血红蛋白相对于总血红蛋白(不饱和+饱和)的比例。人体需要并调节血液中氧气的非常精确和特定的平衡。 人体的正常动脉血氧饱和度为95-100%。 如果该水平低于90%,则被认为是低氧血症。
血氧的测量主要分为透射式和反射式。目前的主流是透射式。但是两者原理差不多,都是使用发光二极管(红光RED,红外IR,绿光GREEN和蓝光BLUE等)照射被测部位,然后使用一个光电二极管接收透射/反射的光线,将光信号转换为电信号。然后通过高精度的ADC测量反射回的电流大小,评估血液中的含氧量。
图1 典型PPG 波形
上图是一个典型的PPG波形,即光电二极管接收到原始的光信号波形。波形(由图中间的白色横虚线)可分为两部分:DC signal 和 AC signal,即直流信号和交流信号。
其中直流信号由下到上可分为以下三部分的反射:组织(issue),静脉血(Venous blood)和不跳动的动脉血(Non pulsatile arterial blood)。当然对于不同年龄、性别和肤色等人不同,对应的DC signal 值也会不同。所以后面的血氧计算都是使用相对值。
而 AC signal 交流信号就比较单一:由跳动的动脉血反射得到。其中波峰对应心脏的收缩(Systole),波谷对应心脏舒张(Diastole)。
1.2 心率计算(HR)
通过计算AC signal 两个波峰的时间(图中两条竖着的黑色虚线),我们就能计算出心率。这里不再赘述。
1.3 灌注指数(PI)
临床上,交流分量与直流分量的幅值之比反映了人体的血流灌注能力,称为血流灌注指数(Perfusion Index,PI),其表达式为:
1.4 血氧计算(SpO2)
血压计算公式也比较简单,这里MAX30102是一路红光,一路红外。只分别算出红光的交流除以红光的直流即: ACred/DCred,和红外的交流除以红外的直流分量即:ACired/DCired。然后两者再相除得到R。
得到 R 然后查表即可得到血氧值,也可以通过下面美信拟合的公式计算:
SpO2 = -45.060*R*R + 30.354 *R + 94.845
二、MAX30102传感器原理
由上面的原理我们简化为:将RED/IR 光射向皮肤,透过皮肤组织反射回的光被光敏传感器接受并转换成电信号,再经过AD转换成数字信号。简化过程:光--> 电 --> 数字信号。所以我们需要控制光源LED的电流强度和采样率,光敏传感器的ADC精度(xbit)等。
图2 MAX30102 系统框图
三、MAX30102寄存器配置
3.1 初始化配置
在一般的配置中我们让设备开机直接开始进入SpO2/HR 模式就好(PROX_INT_EN 置 0),设置两个LED的电流都为0x40,然后开启 RDY 中断使能。这样每次数据采集ok就可以中断一次去处理数据。
// 主要寄存器配置参数
MAX30102_Write_Byte(MODE_CONFIG, 0X40); //RESET FIRSTam_util_delay_ms(20);
MAX30102_Write_Byte(INTERRUPT_ENABLE1, 0xC0); // A_FULL_EN, PPG_RDY_EN set to 1.
MAX30102_Write_Byte(INTERRUPT_ENABLE2, 0x02); //TEMP RDY EN 0x02
MAX30102_Write_Byte(FIFO_WR_PTR, 0x00); //recommend to clear first
MAX30102_Write_Byte(OVERFLOW_COUNTER, 0x00); //recommend to clear first
MAX30102_Write_Byte(FIFO_RE_PTR, 0x00); //recommend to clear first MAX30102_Write_Byte(FIFO_CONFIG, 0x0f); //sample avg = 1, fifo rollover=false, fifo almost full = 17
MAX30102_Write_Byte(MODE_CONFIG, 0x03); //SpO2 mode. RED and IR
MAX30102_Write_Byte(SPO2_CONFIG, 0x2B); // SPO2_ADC range = 4096nA, 200Hz, LED pulseWidth (411uS) ,18bit
MAX30102_Write_Byte(DIE_TEMP_CONFIG, 0x01); //TEMP_EN set 1.MAX30102_Write_Byte(LED1_PULSE_AMP, 0X40); //Choose value for ~ 13mA for LED1(red)
MAX30102_Write_Byte(LED2_PULSE_AMP, 0X40); //Choose value for ~ 13mA for LED2(ir)MAX30102_Read_Byte(INTERRUPT_STATUS1); //clear int flag first.不然可能无法进中断
MAX30102_Read_Byte(INTERRUPT_STATUS2);
3.2 FIFO读取数据
MAX30102 FIFO 的深度为32,每个buf是6个字节(两通道数据,每通道3字节)。我么可以开启 PPG_RDY_EN,这样就能每来一个新的数据,就会中断一次通知我们去取数据。读FIFO_DATA 就会自动清掉中断标志位。
图3 FIFO 寄存器
FIFO相关的寄存器有4个。虽然是显示均可读写(R/W),但是实际上只有 FIFO Read Pointer可以写(应用在读数据出错,往回重读一次的情况)。其他 FIFO 寄存器均为只读。
- FIFO Write Pointer:好理解,就是写指针寄存器。保存下一个新数据在 FIFO 中的写地址。每次来一个数据,这个写指针会自动移动一位。
- Over Flow Counter: 如果32个FIFO深度满了,就会在这里增加1,表示溢出。
- FIFO Read Pointer:FIFO读指针,始终指向下一个待读取的FIFO地址。如果数据读取后,读地址也会自动增加。
- FIFO Data Register: 可以简单的理解为 *FIFO_RD_PTR,始终指向下一个数据。
I2C寄存器映射中的FIFO_DATA寄存器指向要从FIFO读取的下一个样本。 FIFO_RD_PTR指向此样本。所以虽然通过连续读 FIFO_DATA 不会使该寄存器自增,但是 FIFO_DATA 寄存器实际是映射到FIFO_RD_PTR,而FIFO_RD_PTR 寄存器始终指向下一个待读取的数据,所以对FIFO_DATA 连续读,是能够实现的。读 FIFO 函数如下:
/*****************************************************************************************
* Function Name: MAX30102_Read_FIFO_Data
* Description : 通过硬件I2C,读取FIFO中的数据RED, IR.
* Arguments : *data:两路电流值大小
* Return Value : none
******************************************************************************************/
void MAX30102_Read_FIFO_Data(uint32_t *data)
{uint8_t tmp[6];MAX30102_Read_Len(FIFO_DATA, tmp, 6);data[0] = ((tmp[0]<<16 | tmp[1]<<8 | tmp[2]) & 0x03ffff);data[1] = ((tmp[3]<<16 | tmp[4]<<8 | tmp[5]) & 0x03ffff);//am_util_stdio_printf("%d, %d\n", data[0], data[1]);
}
3.3 采样率和精度设置
简单的说想要更高的ADC精度(位数),就得提高脉宽(增加ADC的采样时间)。但是脉宽又会受限制于采样率,如果采样率太高,这个每个周期的时间短可能太短,就不足以满足高采样率的脉宽要求。所以具体的设置参考下表:
图4 脉宽示意图
图5 两种模式各自允许设置采样率表
由上表可知,如果我们在SpO2模式想要ADC的精度为 18bits,脉宽只能为400us,且采样率最高只能到400Hz。两个LED的点亮时序如下图所示:
图6 两路LED的开启时序
四、接近检测功能(Proximity Mode)
通过以上的配置我们已经可以实现两路(红光和红外)PPG的采集。但是为了优化设备的体验,我们期望当手指离开传感器后,能够自动关闭LED,待手指插入后能自动开启继续采集。这样可以做到省电且减少红外的释放,所以我们需要能够自动的调节血氧传感器的开启和停止。而这个的实现就依赖于「接近检测功能」。
「接近检测功能」可以由硬件(传感器本身的Proximity Mode功能)或者软件(应用程序控制LED电流)两种方法实现。基本原理都一样:就是当 红外/红灯 的接收光线低于某一阀值后(表示手指离开),我们就将红灯熄灭,同时降低红外电流且降低采样率,这样达到不漏光且省电的效果。这个时候红外工作在低采样率阶段,如果这时有手指接入,如果达到启动阀值,则重新开始正常的采样,恢复采样率和红光/红外电流。
4.1 硬件实现(不推荐)
实际测试发现,MAX30102其接近功能只能使用红光去做接近检测,所以就算手指拔出进入「接近模式」也会有红色的光发散出来,影响体验所以不推荐。但还是简要的说明其操作步骤:
- 先将 MODE 设置为「SpO2/HR 模式」;
- 将 PROX_INT_EN 置为 1;(必须的!相当于使能硬件的Proximity Mode功能。置0则不会进入接近模式,直接数据采集);
- 设置手指离开后,传感器进入「接近模式」后的红色LED电流大小:PILOT_PA ;
- 设置手指插入后,传感器恢复「SpO2/HR 模式」的阀值:PROX_INT_THRESH;
图7 两个工作模式的转换
主要寄存器配置如下:
MAX30102_Write_Byte(MODE_CONFIG, 0X40); //RESET FIRSTam_util_delay_ms(20);
MAX30102_Write_Byte(INTERRUPT_ENABLE1, 0xD0); // A_FULL_EN, PPG_RDY_EN, PROX_INT_EN set to 1.
MAX30102_Write_Byte(INTERRUPT_ENABLE2, 0x02); //TEMP RDY EN 0x02
MAX30102_Write_Byte(FIFO_WR_PTR, 0x00); //recommend to clear first
MAX30102_Write_Byte(OVERFLOW_COUNTER, 0x00); //recommend to clear first
MAX30102_Write_Byte(FIFO_RE_PTR, 0x00); //recommend to clear first MAX30102_Write_Byte(FIFO_CONFIG, 0x0f); //sample avg = 1, fifo rollover=false, fifo almost full = 17
MAX30102_Write_Byte(MODE_CONFIG, 0x03); //SpO2 mode. RED and IR
MAX30102_Write_Byte(SPO2_CONFIG, 0x2B); //SPO2_ADC range = 4096nA, 200Hz, LED pulseWidth (411uS) ,18bit
MAX30102_Write_Byte(DIE_TEMP_CONFIG, 0x01); //TEMP_EN set 1.MAX30102_Write_Byte(LED1_PULSE_AMP, 0X40); //Choose value for ~ 13mA for LED1(red)
MAX30102_Write_Byte(LED2_PULSE_AMP, 0X40); //Choose value for ~ 13mA for LED2(ir)
MAX30102_Write_Byte(PILOT_PA, 0x01); //Choose value for ~ 0.2mA for Pilot LED (IR)
MAX30102_Write_Byte(PROX_INT_THRESH, 0x01); //唤醒血氧LED的阀值MAX30102_Read_Byte(INTERRUPT_STATUS1); //clear int flag first.不然可能无法进中断
MAX30102_Read_Byte(INTERRUPT_STATUS2);
上述配置后,由于 PROX_INT_EN 已经置1,所以设备开机即进入「接近模式」。可以看到红色灯微微亮起(此时红外没有工作),此时红灯电流大小就是我们 PILOT_PA 寄存器设置的值。如果此时有手指插入,使红色接收管大于 PROX_INT_THRESH 设置的值,那么就会进入 「SpO2/HR 模式」,开始正常采集。
开始正常采集后,就算手指离开探头也不会自动进入「接近模式」,想要进入需要我们手动的再次写 MODE 寄存器:MAX30102_Write_Byte(MODE_CONFIG, 0x03); 至于何时写 MODE 寄存器,需要应用程序通过用户设置的阀值去判断。
4.2 软件实现(推荐)
如果使用软件实现接近检测,我们就可以使用红外灯去做接近检测,这样肉眼就看不到红外光,更合理。
主要思路是:我们初始化时只点亮红外灯,关闭红灯(驱动电流设为0)。然后在 Data DRDY 的中断里,根据自己设定的红外阀值去需要此时是否有手指插入。如果超过阀值就设置两个 LED 的为正常采样率、电流大小;如果再次低于阀值则关闭红灯,降低红外的采样率和电流降低功耗。
步骤:1. Initial Setting – SW proximity mode
开机后,先关闭红灯,红外灯5ms电流,调低采样率,等待手指插入。
// 主要寄存器配置
//寄存器地址 设置参数
0x0C 0x00 //RED LED: 0mA
0x0D 0x19 //IR LED: 5mA
0x0A 0x43 //SPO2 CONFIGURATION //SPO2_ADC_RGE : 8uA (this is a good starting point, try other settings in order to fine tune your design), //SPO2_SR : 50HZ, LED_PW : 400us
0x08 0x00 //FIFO CONFIG
0x11 0x12 //Multi-LED 1
0x12 0x00 //Multi-LED 2
0x04 0x00 //FIFO RESET
0x05 0x00 //FIFO RESET
0x06 0x00 //FIFO RESET
0x09 0x07 //Mode Configuration : Multi-LED Mode
0x02 0x40 //PPG RDY Interrupt Enable
current mode = proximity
2.在 DRDY IRQ Handler的中断里面去判断手指拔出与否,如果有手指则进入正常的采集模式,开启红灯,恢复高采样率。
// 主要寄存器配置(中断伪代码)
// Read 6 bytes from FIFO(first 3bytes : IR, next 3bytes : RED)
if ( IR Count > 2000 and current mode == proximity ) { // 进入正常采集模式0x0C 0x? //RED LED: desired LED current for RED0x0D 0x? //IR LED: desired LED current for IR0x0A 0x4E //SPO2 CONFIGURATION SPO2_ADC_RGE : 8uA, SPO2_SR : 400HZ, LED_PW : 400us0x08 0x40 //FIFO CONFIG : SMP_AVG : 4 Samples : 100 Hz ODRcurrent mode = HRM_SPO2
}
else if ( IR Count < 5000 and current mode == HRM_SPO2 ) { // 进入接近模式(待手指插入)0x0C 0x00 //RED LED: 0mA0x0D 0x19 //IR LED: 5mA0x0A 0x43 //SPO2 CONFIGURATION SPO2_ADC_RGE : 8uA, SPO2_SR : 50HZ, LED_PW : 400us0x04 0x00 //FIFO RESET0x05 0x00 //FIFO RESET0x06 0x00 //FIFO RESET0x08 0x00 //FIFO CONFIGcurrent mode = proximity
}
需要注意,程序中 2000 和 5000 这两个阀值需要根据实际的情况去设置。
4.3 最终效果
两路PPG实时波形效果(蓝色曲线为红光,白色线为红外):可以看出放入手指后,由于有反射,接收到的电流显著增大。
图8 对比手指插入后ppg的变化
图9 两路PPG细节(白色-红外,绿色-红光)
参考资料
[1] Proximity mode
[2] Pulse oximetry: Understanding its basic principles facilitates appreciation of its limitations
[3] GUIDELINES FOR SPO2 MEASUREMENT
MAX30102 血氧调试笔记相关推荐
- 基于STM32F030、MAX30102血氧心率监测仪的设计(二)
上篇主要讲解了MAX30102寄存器相关知识,这篇主要看下程序配置. MAX30102寄存器配置 在一般的配置中我们让设备开机直接开始进入SpO2/HR 模式(PROX_INT_EN 置 0),设置两 ...
- 基于STM32F030、MAX30102血氧心率监测仪的设计(三)
本篇主要记录一下开发过程中遇到的问题与解决. max30102模块是某宝上购买的,价格不贵5元左右,如下图所示. 使用引脚为SDA.SCL.INT.VIN.GND 拿到模块后,看着资料开始移植程序,我 ...
- MAX30102血氧模块检测心率和血氧
1. 完成 CubeMX初始化配置 1.1 利用CubeMX完成HAL库工程模板和初始化: 通过选择芯片型号创建CubeMX工程 在弹出的对话框中输入开发板上的芯片型号,STM32F103RB 在右侧 ...
- 基于STM32F030、MAX30102血氧心率监测仪的设计(一)
搞这个设计用时大约一周,中途遇到好多问题,查找资料乱七八糟,始终没有解决问题,只能自己慢慢的啃资料,本文章主要记录设计过程及记录遇到的问题,做个记录同时帮助有需要的朋友. 目前该设计已成功读取计算出血 ...
- 基于STM32F030、MAX30102血氧心率监测仪的设计(四)
这篇主要分享代码,不做过多介绍! #include "myiic.h"#define CPU_FREQUENCY_MHZ 48 // STM32时钟主频void iic_delay ...
- spo2数据集_Arduino 血氧心率模块传感器数据采集
开发环境: Arduino-1.8.5-windows.exe.HXDZ-30102-ACC 硬件设备: MAX30102 MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块. 它集成 ...
- 基于Arduino 开发 MAX30102 LM35 SSD1306 观察血氧、心率和温度血氧仪
↵本项目第一版本实现在arduino框架下通过MAX30102 对血氧和心率 进行实时监控,通过LM35 对温度进行监控 .所有数值在 ssd 1306 上进行显示.在血氧低过一定数值的时,设备会通过 ...
- MAX30102脉搏血氧仪和心率传感器(四)血氧+心率完整版(STM32)
文章目录 前言 一.先上测试结果 1.测试步骤 2.测试结果 3.后续处理方法 二.血氧饱和度 1.原理 2.计算方法 三.源码获取(STM32例程) 前言 相较于上一章,增加和改进的地方有:①增加了 ...
- STM32+Air202+Air530+HXDZ-30102-ACC心率血氧GPS采集上传到阿里云
主要功能 HXDZ-30102-ACC采集心率血氧数据 STM32通过串口将数据转发到air202模块 air202将数据上传到阿里云平台进行展示与处理 整合合宙air530GPS模块,将定位数据上传 ...
- 基于单片机MAX30100血氧、心率检测系统设计-整套资料
基于美信MAX30100/MAX30102传感器设计的血氧和心率检测,以单片机STM32F103CBT6为主控核心,其中涉及电源模块.心率血氧模块.蓝牙模块.电源模块是提供所有系统的供电,心率血氧是整 ...
最新文章
- DataUml Design 教程3-模型与数据库同步
- 从TXT文本文档向Sql Server中批量导入数据
- linux db2备份,db2实现备份
- HTML里面Textarea换行总结
- 程序员为什么越老越贬值的厉害?
- 获取skipcase
- 根据前序和中序构造整个二叉树
- Git版本控制:Git高级教程
- 13. GameProjec1_GameEngine
- java技术可行性分析_Java可行性分析
- android 反编译 dex2jar,Android反编译教程:apktool,dex2jar的使用
- 第1篇 初识IPP(Integrated Performance Primitives)
- flink连接kafka报错
- C语言 冒泡法排序,选择法排序和插入排序
- cboard企业版源码_CBoard自助BI数据分析产品 v0.4.2
- 鲁班H5页面生成工具
- Spring Boot系列之Thymeleaf模板布局
- 使用简单的编程为您的网站构建具有自定义知识的类似 ChatGPT 的聊天机器人
- 微软推出三维立体地图搜索(3-D City Live Search)
- Echarts实现世界地图
热门文章
- FFmpeg —— 屏幕录像机
- 计算机硬件故障有哪些现象,计算机常见硬件故障症状现象分析及解决办法
- Opencv实战四 图像匹配
- 科大讯飞 asr 实时语音转写 rtasr 基于Netty编写的websocket client SDK
- 使用php,根据输入的文字自动生成图片,并把文字在图片上展示出来
- Java 点餐小程序源码带管理后台(免费分享)
- hsql转换oracle,Hive系列之HSQL转换成MapReduce过程
- 你们要的终极指南! 交易API接口
- 一人有限责任公司章程范本
- android截屏方法是黑屏,Android截屏SurfaceView黑屏问题的解决办法