一、血氧测量原理

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其接近功能只能使用红光去做接近检测,所以就算手指拔出进入「接近模式」也会有红色的光发散出来,影响体验所以不推荐。但还是简要的说明其操作步骤:

  1. 先将 MODE 设置为「SpO2/HR 模式」;
  2. 将 PROX_INT_EN 置为 1;(必须的!相当于使能硬件的Proximity Mode功能。置0则不会进入接近模式,直接数据采集);
  3. 设置手指离开后,传感器进入「接近模式」后的红色LED电流大小:PILOT_PA ;
  4. 设置手指插入后,传感器恢复「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 血氧调试笔记相关推荐

  1. 基于STM32F030、MAX30102血氧心率监测仪的设计(二)

    上篇主要讲解了MAX30102寄存器相关知识,这篇主要看下程序配置. MAX30102寄存器配置 在一般的配置中我们让设备开机直接开始进入SpO2/HR 模式(PROX_INT_EN 置 0),设置两 ...

  2. 基于STM32F030、MAX30102血氧心率监测仪的设计(三)

    本篇主要记录一下开发过程中遇到的问题与解决. max30102模块是某宝上购买的,价格不贵5元左右,如下图所示. 使用引脚为SDA.SCL.INT.VIN.GND 拿到模块后,看着资料开始移植程序,我 ...

  3. MAX30102血氧模块检测心率和血氧

    1. 完成 CubeMX初始化配置 1.1 利用CubeMX完成HAL库工程模板和初始化: 通过选择芯片型号创建CubeMX工程 在弹出的对话框中输入开发板上的芯片型号,STM32F103RB 在右侧 ...

  4. 基于STM32F030、MAX30102血氧心率监测仪的设计(一)

    搞这个设计用时大约一周,中途遇到好多问题,查找资料乱七八糟,始终没有解决问题,只能自己慢慢的啃资料,本文章主要记录设计过程及记录遇到的问题,做个记录同时帮助有需要的朋友. 目前该设计已成功读取计算出血 ...

  5. 基于STM32F030、MAX30102血氧心率监测仪的设计(四)

    这篇主要分享代码,不做过多介绍! #include "myiic.h"#define CPU_FREQUENCY_MHZ 48 // STM32时钟主频void iic_delay ...

  6. spo2数据集_Arduino 血氧心率模块传感器数据采集

    开发环境: Arduino-1.8.5-windows.exe.HXDZ-30102-ACC 硬件设备: MAX30102 MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块. 它集成 ...

  7. 基于Arduino 开发 MAX30102 LM35 SSD1306 观察血氧、心率和温度血氧仪

    ↵本项目第一版本实现在arduino框架下通过MAX30102 对血氧和心率 进行实时监控,通过LM35 对温度进行监控 .所有数值在 ssd 1306 上进行显示.在血氧低过一定数值的时,设备会通过 ...

  8. MAX30102脉搏血氧仪和心率传感器(四)血氧+心率完整版(STM32)

    文章目录 前言 一.先上测试结果 1.测试步骤 2.测试结果 3.后续处理方法 二.血氧饱和度 1.原理 2.计算方法 三.源码获取(STM32例程) 前言 相较于上一章,增加和改进的地方有:①增加了 ...

  9. STM32+Air202+Air530+HXDZ-30102-ACC心率血氧GPS采集上传到阿里云

    主要功能 HXDZ-30102-ACC采集心率血氧数据 STM32通过串口将数据转发到air202模块 air202将数据上传到阿里云平台进行展示与处理 整合合宙air530GPS模块,将定位数据上传 ...

  10. 基于单片机MAX30100血氧、心率检测系统设计-整套资料

    基于美信MAX30100/MAX30102传感器设计的血氧和心率检测,以单片机STM32F103CBT6为主控核心,其中涉及电源模块.心率血氧模块.蓝牙模块.电源模块是提供所有系统的供电,心率血氧是整 ...

最新文章

  1. DataUml Design 教程3-模型与数据库同步
  2. 从TXT文本文档向Sql Server中批量导入数据
  3. linux db2备份,db2实现备份
  4. HTML里面Textarea换行总结
  5. 程序员为什么越老越贬值的厉害?
  6. 获取skipcase
  7. 根据前序和中序构造整个二叉树
  8. Git版本控制:Git高级教程
  9. 13. GameProjec1_GameEngine
  10. java技术可行性分析_Java可行性分析
  11. android 反编译 dex2jar,Android反编译教程:apktool,dex2jar的使用
  12. 第1篇 初识IPP(Integrated Performance Primitives)
  13. flink连接kafka报错
  14. C语言 冒泡法排序,选择法排序和插入排序
  15. cboard企业版源码_CBoard自助BI数据分析产品 v0.4.2
  16. 鲁班H5页面生成工具
  17. Spring Boot系列之Thymeleaf模板布局
  18. 使用简单的编程为您的网站构建具有自定义知识的类似 ChatGPT 的聊天机器人
  19. 微软推出三维立体地图搜索(3-D City Live Search)
  20. Echarts实现世界地图

热门文章

  1. FFmpeg —— 屏幕录像机
  2. 计算机硬件故障有哪些现象,计算机常见硬件故障症状现象分析及解决办法
  3. Opencv实战四 图像匹配
  4. 科大讯飞 asr 实时语音转写 rtasr 基于Netty编写的websocket client SDK
  5. 使用php,根据输入的文字自动生成图片,并把文字在图片上展示出来
  6. Java 点餐小程序源码带管理后台(免费分享)
  7. hsql转换oracle,Hive系列之HSQL转换成MapReduce过程
  8. 你们要的终极指南! 交易API接口
  9. 一人有限责任公司章程范本
  10. android截屏方法是黑屏,Android截屏SurfaceView黑屏问题的解决办法