32331|19

217

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

MAX32630FTHR板的学习(三):MAX30102的初步使用及心率、血氧的测量原理 [复制链接]

 
本帖最后由 anning865 于 2017-8-6 17:30 编辑

        在上一篇帖子中,使用MAX32630FTHR板驱动了心率脉搏传感器Pulse sensor,得到了心率数值和脉搏的图像。这篇帖子介绍并研究一款美信公司生产的光学传感器MAX30102。
       美信公司的MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块。它集成了一个红光LED和一个红外光LED、光电检测器、光器件,以及带环境光抑制的低噪声电子电路。MAX30102采用一个1.8V电源和一个独立的5.0V用于内部LED的电源,应用于可穿戴设备进行心率和血氧采集检测,佩戴于手指、耳垂和手腕等处。标准的I2C兼容的通信接口可以将采集到的数值传输给Arduino、KL25Z等单片机进行心率和血氧计算。此外,该芯片还可通过软件关断模块,待机电流接近为零,实现电源始终维持供电状态。正因为其优异的性能,该芯片被大量应用在了三星Galaxy S7手机。与前代产品MAX30100相比(MAX30100目前已经停产淘汰),MAX30102集成了玻璃盖可以有效排除外界和内部光干扰,拥有最优可靠的性能。
       与Pulse sensor这种传感器相比,MAX30102的有点在于:
1.集成度高:MAX30102将两个发光LED、光电检测二极管、ADC、环境光抑制电路和光学机械外壳都集成在了一起,形成了一个完整模块。这样的优势就是体积小、能耗小、外界干扰小,易于集成系统。
2.数字输出:MAX30102本身自带18位高精度ADC,使用I2C接口与外接MCU通信。而且自身还有FIFO,可以减轻MCU负担,降低功耗。
3.功能丰富:MAX30102集成了LED驱动电路,可以根据不同情况调节LED电流,采样率也可以根据不同应用进行选择。此外还集成了片上温度传感器,可以随时监测片上温度(对血氧饱和度计算有用)。
       正是有以上一些优点,现在的模拟集成前端(AFE)都走向了集成化、小型化、数字化的方向,模拟电路的门槛越来越低了。
       首先看一下MAX30102的结构框图:

图1、MAX30102的结构框图


       MAX30102的发光部分包括两个LED,一个是红光LED(660nm),另一个是红外光LED(880nm),这个是测量血氧饱和度SPO2最常见的配置。接收部分是一个对可见光和红外光都敏感的光电二极管,其接收的光强度信号转换为电流信号,经过环境光消除电路后,最后被自带的18位ADC进行采样转化,至此模拟部分完成。AD转化后的数字经过数字滤波后储存在数据寄存器中,最后可通过I2C总线被外接MCU读取。在硬件上,LED的电源和其他部分的电源不是同一个,因为LED为了保证足够的出射光强,需要瞬间大电流(最大50ma),这就要求LED的正向电压足够大(要求3.1V以上)。而其余的AD转换和I2C总线部分,为了实现低功耗要求电压足够小(要求1.8V),所以传感器需要两路独立的电源。此外,由于LED电源会产生瞬间大电流,所以电源引脚附近要加一个大电容减轻对电源电压的影响。

图2、MAX30102引脚图


       传统的脉搏测量方法主要有三种:一是从心电信号中提取;二是从测量血压时压力传感器测到的波动来计算脉率;三是光电容积法。前两种方法提取信号都会限制病人的活动,如果长时间使用会增加病人生理和心理上的不舒适感。而光电容积法脉搏测量作为监护测量中最普遍的方法之一,其具有方法简单、佩戴方便、可靠性高等特点。
       光电容积法的基本原理是利用人体组织在血管搏动时造成透光率不同来进行脉搏和血氧饱和度测量的。其使用的传感器由光源和光电变换器两部分组成,通过绑带或夹子固定在病人的手指、手腕或耳垂上。光源一般采用对动脉血中氧合血红蛋白(HbO2)和去氧血红蛋白(Hb)有选择性的特定波长的发光二极管(一般选用660nm附近的红光和900nm附近的红外光)。当光束透过人体外周血管,由于动脉搏动充血容积变化导致这束光的透光率发生改变,此时由光电变换器接收经人体组织反射的光线,转变为电信号并将其放大和输出。由于脉搏是随心脏的搏动而周期性变化的信号,动脉血管容积也呈现周期性变化,因此光电变换器的电信号变化周期就是脉搏率。同时根据血氧饱和度的定义,其表示为:
图3、血氧饱和度定义式

图4、不同波长下氧合血红蛋白(HbO2)和去氧血红蛋白(Hb)的吸收
     MAX30102本身集成了完整的发光LED及驱动部分,光感应和AD转换部分,环境光干扰消除及数字滤波部分,只将数字接口留给用户,极大地减轻了用户的设计负担。用户只需要使用单片机通过硬件I2C或者模拟I2C接口来读取MAX30102本身的FIFO,就可以得到转换后的光强度数值,通过编写相应算法就可以得到心率值和血氧饱和度。

    本来为了方便验证MAX30102和MAX32630FTHR板配合使用,本人从淘宝上买了一个现成的MAX30102模块。但是让人意想不到的是,这个模块本身设计存在很大问题,它的I2C总线上拉电压被强制固定在1.8V上了,这导致了该模块与IO口为3.3v,5v电平的单片机无法正常通信!真的是脑残的设计啊!为了找这个原因,浪费了很多时间,后来在GITHUB上看到有外国人抱怨,我才明白!最后只能飞线解决。


图5、X宝上某有问题的模块设计


图6、问题模块及飞线解决方法

       这次简单验证一下MAX32630FTHR板可以通过I2C总线对MAX30102进行通信,所以在MBED上写了读取MAX30102片上温度的程序,并通过串口打印输出温度结果。具体程序如下:
  1. #include "mbed.h"
  2. #include "max32630fthr.h"

  3. #define false 0
  4. #define true 1
  5. MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
  6. Serial pc(USBTX, USBRX);//USB TO SERIAL
  7. DigitalIn INT(P3_2);  //pin P3.2 connects to the interrupt output pin of the MAX30102
  8. I2C i2cm1(P3_4, P3_5);


  9. #define I2C_WRITE_ADDR 0xAE
  10. #define I2C_READ_ADDR 0xAF

  11. //register addresses
  12. #define REG_INTR_STATUS_1 0x00
  13. #define REG_INTR_STATUS_2 0x01
  14. #define REG_INTR_ENABLE_1 0x02
  15. #define REG_INTR_ENABLE_2 0x03
  16. #define REG_FIFO_WR_PTR 0x04
  17. #define REG_OVF_COUNTER 0x05
  18. #define REG_FIFO_RD_PTR 0x06
  19. #define REG_FIFO_DATA 0x07
  20. #define REG_FIFO_CONFIG 0x08
  21. #define REG_MODE_CONFIG 0x09
  22. #define REG_SPO2_CONFIG 0x0A
  23. #define REG_LED1_PA 0x0C
  24. #define REG_LED2_PA 0x0D
  25. #define REG_PILOT_PA 0x10
  26. #define REG_MULTI_LED_CTRL1 0x11
  27. #define REG_MULTI_LED_CTRL2 0x12
  28. #define REG_TEMP_INTR 0x1F
  29. #define REG_TEMP_FRAC 0x20
  30. #define REG_TEMP_CONFIG 0x21
  31. #define REG_PROX_INT_THRESH 0x30
  32. #define REG_REV_ID 0xFE
  33. #define REG_PART_ID 0xFF

  34. bool maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data)
  35. /**
  36. * \brief        Write a value to a MAX30102 register
  37. * \par          Details
  38. *               This function writes a value to a MAX30102 register
  39. *
  40. * \param[in]    uch_addr    - register address
  41. * \param[in]    uch_data    - register data
  42. *
  43. * \retval       true on success
  44. */
  45. {
  46.   char ach_i2c_data[2];
  47.   ach_i2c_data[0]=uch_addr;
  48.   ach_i2c_data[1]=uch_data;
  49.   
  50.   if(i2cm1.write(I2C_WRITE_ADDR, ach_i2c_data, 2, false)==0)
  51.     return true;
  52.   else
  53.     return false;
  54. }

  55. bool maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data)
  56. /**
  57. * \brief        Read a MAX30102 register
  58. * \par          Details
  59. *               This function reads a MAX30102 register
  60. *
  61. * \param[in]    uch_addr    - register address
  62. * \param[out]   puch_data    - pointer that stores the register data
  63. *
  64. * \retval       true on success
  65. */
  66. {
  67.   char ch_i2c_data;
  68.   ch_i2c_data=uch_addr;
  69.   if(i2cm1.write(I2C_WRITE_ADDR, &ch_i2c_data, 1, true)!=0)
  70.     return false;
  71.   if(i2cm1.read(I2C_READ_ADDR, &ch_i2c_data, 1, false)==0)
  72.   {
  73.     *puch_data=(uint8_t) ch_i2c_data;
  74.     return true;
  75.   }
  76.   else
  77.     return false;
  78. }

  79. bool maxim_max30102_reset()
  80. /**
  81. * \brief        Reset the MAX30102
  82. * \par          Details
  83. *               This function resets the MAX30102
  84. *
  85. * \param        None
  86. *
  87. * \retval       true on success
  88. */
  89. {
  90.     if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40))
  91.         return false;
  92.     else
  93.         return true;   
  94. }

  95. bool maxim_max30102_init()
  96. /**
  97. * \brief        Initialize the MAX30102
  98. * \par          Details
  99. *               This function initializes the MAX30102
  100. *
  101. * \param        None
  102. *
  103. * \retval       true on success
  104. */
  105. {
  106.   if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting
  107.     return false;
  108.   if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x02))
  109.     return false;
  110.   if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00))  //FIFO_WR_PTR[4:0]
  111.     return false;
  112.   if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00))  //OVF_COUNTER[4:0]
  113.     return false;
  114.   if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00))  //FIFO_RD_PTR[4:0]
  115.     return false;
  116.   if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f))  //sample avg = 1, fifo rollover=false, fifo almost full = 17
  117.     return false;
  118.   if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03))   //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
  119.     return false;
  120.   if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27))  // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
  121.     return false;
  122.   
  123.   if(!maxim_max30102_write_reg(REG_LED1_PA,0x24))   //Choose value for ~ 7mA for LED1
  124.     return false;
  125.   if(!maxim_max30102_write_reg(REG_LED2_PA,0x24))   // Choose value for ~ 7mA for LED2
  126.     return false;
  127.   if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f))   // Choose value for ~ 25mA for Pilot LED
  128.     return false;
  129. if(!maxim_max30102_write_reg(REG_TEMP_CONFIG,0x01))   // En temp
  130.     return false;
  131.    
  132.   return true;  
  133. }

  134. int main()
  135. {
  136.     uint8_t temp_inter,temp_fra;
  137.     float temp_value;
  138.    
  139.     maxim_max30102_reset(); //resets the MAX30102
  140.     // initialize serial communication at 9600 bits per second:
  141.     pc.baud(9600);
  142.     pc.format(8,SerialBase::None,1);
  143.     pc.printf("ready to go!");
  144.     wait(1);
  145.    
  146.     //read and clear status register
  147.     maxim_max30102_read_reg(0,&temp_inter);
  148.     maxim_max30102_init();
  149.    
  150.     while(1)
  151.     {
  152.     while(INT.read()==1);
  153.     maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter);
  154.     maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra);
  155.     temp_value=temp_inter+temp_fra*0.0625;
  156.     pc.printf("temperature is %6.4f \n\r", temp_value);
  157.     }
  158. }
复制代码

上面的代码在MBED平台记得添加MAX32630FTHR和MBED库文件。


图7、实验图片(MAX30102的LED已经点亮了)


图8、串口输出温度数据

        最后KEIL的PACK包已经由论坛发出了,MBED的程序终于可以导出到KEIL调试了,但是我在下载选项中没有找到MAX32630的FLASH选项,请教了几个坛友,希望有成功者指点一二。并附上导出的KEIL整个工程文件 FTHR_MAX30102_temp_uvision5_max32630fthr.zip (4.62 MB, 下载次数: 2712)







最新回复

这种的只是做来玩玩,如果想要得到精确数值的话,I2C建议通过电平转换芯片来实现,测量位置推荐指肚和耳垂,手腕和小臂基本没用。   详情 回复 发表于 2023-4-12 10:54
点赞(2) 关注(2)
个人签名心率传感器:https://shop108071095.taobao.com
 

回复
举报

217

帖子

0

TA的资源

一粒金砂(高级)

沙发
 
自己总结一下这篇帖子。
总结:
1.MAX30102传感器集成度较高,实现了整个心率和血氧测量的模拟前端功能,功耗,体积上有优势
2.淘宝上目前某些的MAX30102模块有硬件错误,要谨慎购买使用
3.MAX32630FHTR板可以通过I2C成功读取MAX30102内部温度数值
个人签名心率传感器:https://shop108071095.taobao.com
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
厉害,学习了
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(中级)

4
 
感谢楼主的分享,想问一下我按图片所示飞线之后接上电源之后板子温度很高,请问楼主出现这种情况了吗?

点评

没有出现你说的情况。飞线后I2C总线上拉电压应该和VIN输入电压相同,不过实际测量后发现电压和VIN电压差一点,大概零点几伏,应该是和上面那个6脚芯片有关,但是不清楚那个芯片具体是什么型号。 如果使用我第四篇帖  详情 回复 发表于 2017-8-23 00:44
 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

5
 
mse 发表于 2017-8-22 20:42
感谢楼主的分享,想问一下我按图片所示飞线之后接上电源之后板子温度很高,请问楼主出现这种情况了吗?

没有出现你说的情况。飞线后I2C总线上拉电压应该和VIN输入电压相同,不过实际测量后发现电压和VIN电压差一点,大概零点几伏,应该是和上面那个6脚芯片有关,但是不清楚那个芯片具体是什么型号。
如果使用我第四篇帖子里重新改版的传感器,就没有上述问题。
个人签名心率传感器:https://shop108071095.taobao.com
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 
你好,除了飞线之外是不是还要讲472与1.8V的相连的线断掉?

点评

肯定啊  详情 回复 发表于 2018-5-8 19:01
 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

7
 
小陆肉肉 发表于 2018-5-7 17:39
你好,除了飞线之外是不是还要讲472与1.8V的相连的线断掉?

肯定啊
个人签名心率传感器:https://shop108071095.taobao.com
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

8
 

那要怎么断开啊?对板子要做如何操作?
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

9
 
SolitaryLGQ 发表于 2018-7-4 16:50
那要怎么断开啊?对板子要做如何操作?

已解决:就是将65k5左边那个和472连接的线划掉就可以了;代码在下面网址下载https://www.maximintegrated.com/ ... d/6300.html/tb_tab2
下一步打算修改代码使测量更准确
 
 
 

回复

1

帖子

1

TA的资源

一粒金砂(初级)

10
 
这个芯片是拿来测血氧和心率的,温度只是用来校准的,你竟然拿来测温度
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

11
 
SolitaryLGQ 发表于 2018-7-4 18:22
已解决:就是将65k5左边那个和472连接的线划掉就可以了;代码在下面网址下载https://www.maximintegrated ...

请问下断线是断的哪里,我的MAX30102使用例程无法正常通讯,是这种原因吗
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

12
 
能指导一下接近模式使用问题么

点评

看MAX30102最新版说明书,接近模式已经取消掉了,相应寄存器都不提了。我觉得这个功能就用程序简单写一下就能实现,可能没必要用寄存器了。  详情 回复 发表于 2019-5-9 15:05
 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

13
 
727741248 发表于 2019-5-6 12:08
能指导一下接近模式使用问题么

看MAX30102最新版说明书,接近模式已经取消掉了,相应寄存器都不提了。我觉得这个功能就用程序简单写一下就能实现,可能没必要用寄存器了。
个人签名心率传感器:https://shop108071095.taobao.com
 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

14
 

读出的值每个部位的都不一样(如手和小臂的值),并且移植的算法始终不能出正确的值,这个是怎么回事呢?

 

 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

15
 
不!努力 发表于 2019-8-15 14:59 读出的值每个部位的都不一样(如手和小臂的值),并且移植的算法始终不能出正确的值,这个是怎么回事呢? ...

大神您解决这个问题了吗?我的也是始终没正确的值,值的跳变也很大,是算法的问题吗?

 
 
 

回复

7

帖子

0

TA的资源

一粒金砂(中级)

16
 

感觉这个模块网上的算法等都没得到准确的值,原始数据虽然有,但是一经过算法后始终是错误的值,要是说是环境的干扰我用黑色胶布缠绕还是不行

 
 
 

回复

217

帖子

0

TA的资源

一粒金砂(高级)

17
 
不!努力 发表于 2019-8-19 13:25 感觉这个模块网上的算法等都没得到准确的值,原始数据虽然有,但是一经过算法后始终是错误的值,要是说是环 ...

可能你的传感器是坏的或者劣质品。目前市面上十元左右的30102基本都是原厂挑剩下的残次品。你只能多买几个挑性能比较好的,或者直接买原厂的芯片(价格三十多)。

个人签名心率传感器:https://shop108071095.taobao.com
 
 
 

回复

125

帖子

0

TA的资源

一粒金砂(高级)

18
 

美信的料市场确实有仿制品出现,这也正是说明美信原装产品的珍贵,大家一定要搽亮眼睛,一定找懂技术的供应商来合作

 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

19
 
不!努力 发表于 2019-8-15 14:59 读出的值每个部位的都不一样(如手和小臂的值),并且移植的算法始终不能出正确的值,这个是怎么回事呢? ...

指肚和耳垂的比较准确,手腕和小臂几乎测不到值的。

 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

20
 
不!努力 发表于 2019-8-19 13:25 感觉这个模块网上的算法等都没得到准确的值,原始数据虽然有,但是一经过算法后始终是错误的值,要是说是环 ...

这种的只是做来玩玩,如果想要得到精确数值的话,I2C建议通过电平转换芯片来实现,测量位置推荐指肚和耳垂,手腕和小臂基本没用。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表