当前位置:   article > 正文

将 MAX30102 脉搏血氧计和心率传感器与 Arduino 连接_max30102心率血氧传感器

max30102心率血氧传感器

Arduino-MAX30102-脉搏血氧计-心率传感器接口教程

MAX30102脉搏血氧计和心率传感器是一款基于I2C的低功耗即插即用生物识别传感器。想要将实时心率数据合并到项目中的学生、爱好者、工程师、制造商以及游戏和移动开发人员都可以使用它。

MAX30102模块硬件概述

该模块采用 MAX30102——来自 Analog Devices 的现代集成脉搏血氧计和心率传感器 IC ( MAX30100的后继产品)。它结合了两个 LED、一个光电探测器、优化的光学器件和低噪声模拟信号处理,可检测脉搏血氧饱和度 (SpO2) 和心率 (HR) 信号。

max30102 模块硬件概述 IC 和 LED

MAX30102 在一侧窗户后面有两个 LED – 一个红色 LED 和一个红外 LED。另一侧是一个非常灵敏的光电探测器。这个想法是,您一次点亮一个 LED,检测探测器上反射回来的光量,然后根据签名,您可以测量血氧水平和心率。

电力需求

MAX30102芯片需要两种不同的电源电压:IC的电源电压为1.8V,红色和红外LED的电源电压为3.3V。因此该模块配有 3.3V 和 1.8V 稳压器。

max30102 稳压器模块硬件概述

在 PCB 背面,您会发现一个焊接跳线,可用于在 3.3V 和 1.8V 逻辑电平之间进行选择。默认选择 3.3V 逻辑电平,与 Arduino 的逻辑电平兼容。但您也可以根据您的要求选择 1.8V 逻辑电平。这允许您将模块连接到具有 5V、3.3V、甚至 1.8V 电平 I/O 的任何微控制器。

max30102模块硬件概述焊接跳线

MAX30102最重要的特性之一是其低功耗:测量期间MAX30102的功耗低于600μA。此外,还可以将 MAX30102 置于待机模式,此时功耗仅为 0.7μA。这种低功耗允许在手机、可穿戴设备或智能手表等电池供电设备中实施。

片上温度传感器

MAX30102具有片上温度传感器,可用于补偿环境变化并校准测量结果。

这是一款相当精确的温度传感器,可测量 -40°C 至 +85°C 范围内的“芯片温度”,精度为 ±1°C。

I2C接口

该模块使用简单的两线 I2C 接口与微控制器进行通信。它有一个固定的I2C地址:0xAE HEX(用于写操作)和0xAF HEX(用于读操作)。

先进先出缓冲器

MAX30102嵌入了一个用于存储数据样本的FIFO缓冲器。FIFO 具有 32 个样本存储库,这意味着它可以容纳多达 32 个 SpO2 和心率样本。FIFO 缓冲区可以减轻微控制器从传感器读取每个新数据样本的负担,从而节省系统功耗。

中断

MAX30102可编程为产生中断,允许主机微控制器在传感器收集数据的同时执行其他任务。可以为 5 个不同的源启用中断:

  • 电源就绪:在通电时或断电情况后触发。
  • 新数据就绪:收集每个 SpO2 和 HR 数据样本后触发。
  • 环境光消除:当SpO2/HR光电二极管的环境光消除功能达到最大极限时触发,影响ADC的输出。
  • 温度就绪:内部芯片温度转换完成时触发。
  • FIFO 几乎已满:当 FIFO 已满且未来数据即将丢失时触发。

max30102模块硬件概述中断引脚

INT 线是开漏极,因此它被板载电阻拉高。当中断发生时,INT 引脚变为低电平并保持低电平直到中断被清除。

技术规格

以下是技术规格:

电源3.3V至5.5V
电流消耗~600μA(测量期间)
~0.7μA(待机模式期间)
红色 LED 波长660nm
红外 LED 波长880nm
温度范围-40°C 至 +85°C
温度准确度±1℃

您可以从数据表中找到有关 MAX30102 传感器的详细信息。

MAX30102 脉搏血氧计和心率传感器如何工作?

MAX30102 或任何光学脉搏血氧计和心率传感器由一对高强度 LED(红色和红外,波长不同)和一个光电探测器组成。这些 LED 的波长分别为 660nm 和 880nm。

max30102 脉冲检测光电体积描记图

MAX30102 的工作原理是将两束光照射到手指或耳垂(或者基本上是皮肤不太厚的任何地方,因此两束光可以轻松穿透组织),并使用光电探测器测量反射光量。这种通过光检测脉搏的方法称为光电体积描记法

MAX30102的工作可以分为两部分:心率测量和脉搏血氧饱和度(测量血液中的含氧量)。

心率测量

动脉血中的氧合血红蛋白(HbO2)具有吸收红外光的特性。血液越红(血红蛋白越高),吸收的红外光就越多。当血液随着每次心跳泵入手指时,反射光的量会发生变化,从而在光电探测器的输出端产生变化的波形。当您继续照射光线并获取光电探测器读数时,您很快就会开始获得心率 (HR) 脉搏读数。

脉搏检测心率传感器工作光电体积描记图

脉搏血氧仪

脉搏血氧测定法的原理是,吸收的红光和红外光的量根据血液中的氧含量而变化。下图是含氧血红蛋白(HbO2)和脱氧血红蛋白(Hb)的吸收光谱。

hb 和 hbo2 的吸收光谱

从图中可以看出,脱氧血液吸收更多红光 (660nm),而含氧血液吸收更多红外光 (880nm)。通过测量光电探测器接收到的红外光和红光的比率,可以计算出血液中的氧含量 (SpO2)。

你可知道?

1935 年,德国医生 Karl Matthes 提出通过测量红光和红外光的吸光度来测量血红蛋白氧饱和度 (HbO2)。

起初,没有好的光电探测器,因此使用光谱的绿光波段代替红外波段。随着技术的进步,更可靠的方法被开发出来,绿光被红外光取代。

MAX30102模块引脚排列

MAX30102模块提供以下连接。

max30102模块引脚排列

VIN是电源引脚。您可以将其连接到 Arduino 的 3.3V 或 5V 输出。

SCL是I2C时钟引脚,连接到Arduino的I2C时钟线。

SDA是I2C数据引脚,连接到Arduino的I2C数据线。

INTMAX30102可编程为每个脉冲生成一个中断。该线是漏极开路,因此它被板载电阻拉高。当中断发生时,INT 引脚变为低电平并保持低电平直到中断被清除。

IDRMAX30102 集成了 LED 驱动器,用于驱动 LED 脉冲以进行 SpO2 和 HR 测量。如果您想自己驱动 IR LED,请使用此选项,否则请将其悬空。

RD引脚与 IRD 引脚类似,但用于驱动红色 LED。如果您不想自己驱动红色 LED,请将其悬空。

GND是地面。

将 MAX30102 模块连接到 Arduino

现在我们已经了解了该模块的所有信息,我们可以开始将其连接到我们的 Arduino 了!

首先将VCC引脚连接到电源,3V-5V即可。使用与微控制器逻辑相同的电压。对于大多数 Arduino,电压为 5V。对于 3.3V 逻辑器件,请使用 3.3V。现在将 GND 连接到公共地。

将 SCL 引脚连接到 Arduino 上的 I2C 时钟引脚,将 SDA 引脚连接到 I2C 数据引脚。请注意,每个 Arduino 板都有不同的 I2C 引脚,应进行相应的连接。在采用 R3 布局的 Arduino 板上,SDA(数据线)和 SCL(时钟线)位于靠近 AREF 引脚的排针上。它们也称为 A5 (SCL) 和 A4 (SDA)。

下图显示了接线。

max30102脉搏血氧仪心率模块的arduino接线

库安装

有多个库可用于 MAX30102 传感器。然而,在我们的示例中,我们使用的是SparkFun Electronics的产品。该库展示了 MAX30102 的大部分功能,并提供简单易用的函数来计算脉率和 SpO2。您可以从 Arduino IDE 库管理器下载该库。

要安装库,请导航至 Sketch > Include Library > Manage Libraries... 等待库管理器下载库索引并更新已安装库的列表。

管理图书馆

输入MAX3010x来过滤您的搜索。查找SparkFun MAX3010x 脉冲和接近传感器库。单击该条目,然后选择安装。

max30102库安装

MAX30102 示例草图

SparkFun_MAX3010x 库有许多示例草图。您可以使用这些示例草图作为开发自己的代码的基础。

要访问示例草图,请导航至文件 > 示例 > SparkFun MAX3010x 脉冲和接近传感器库。您将看到精选的示例草图。

max30102 库示例

示例 1 – 读取红色和 IR

第一个示例输出传感器读取的原始值(IR 和红色读数)。将其加载到 Arduino 上并打开串行终端以查看打印值。

  1. #include <Wire.h>
  2. #include "MAX30105.h"
  3. MAX30105 particleSensor;
  4. void setup() {
  5. Serial.begin(9600);
  6. // Initialize sensor
  7. if (particleSensor.begin() == false) {
  8. Serial.println("MAX30102 was not found. Please check wiring/power.");
  9. while (1);
  10. }
  11. particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
  12. }
  13. void loop() {
  14. Serial.print(" R[");
  15. Serial.print(particleSensor.getRed());
  16. Serial.print("] IR[");
  17. Serial.print(particleSensor.getIR());
  18. Serial.println("]");
  19. }

将传感器朝上,将手滑过传感器。当您的手反射不同量的光时,您应该会看到值的变化。

max30102 原始红色和 ir 值输出

如果您只查看值,则串行数据可能很难可视化。如果您使用的是 Arduino IDE v1.6.6+,可以选择使用Arduino 串行绘图仪查看图表上的数据。

首先,将上面代码中的loop()替换为以下代码片段:

  1. void loop() {
  2. Serial.print(particleSensor.getRed());
  3. Serial.print(", ");
  4. Serial.println(particleSensor.getIR());
  5. }

在 Arduino IDE 中,选择“工具”>“串行绘图仪”。当您在传感器上滑动手时,您应该会看到类似于下图的波浪。

串行绘图仪上的 max30102 输出

示例 2 – 存在感应

我们的下一个实验展示了如何使用 MAX30102 传感器作为通用接近传感器或反射传感器,并且可以作为更实际的实验和项目的基础。

此示例的工作原理是在设置期间获取少量读数并将它们平均在一起。然后它使用该平均值作为基线。如果传感器检测到平均值有显着变化,“有东西在那里!” 被打印。继续尝试绘制草图。

  1. #include <Wire.h>
  2. #include "MAX30105.h"
  3. MAX30105 particleSensor;
  4. long samplesTaken = 0; //Counter for calculating the Hz or read rate
  5. long unblockedValue; //Average IR at power up
  6. long startTime; //Used to calculate measurement rate
  7. void setup() {
  8. Serial.begin(9600);
  9. // Initialize sensor
  10. if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false) { //Use default I2C port, 400kHz speed
  11. Serial.println("MAX30102 was not found. Please check wiring/power. ");
  12. while (1);
  13. }
  14. //Setup to sense up to 18 inches, max LED brightness
  15. byte ledBrightness = 0xFF; //Options: 0=Off to 255=50mA
  16. byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
  17. byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  18. int sampleRate = 400; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  19. int pulseWidth = 411; //Options: 69, 118, 215, 411
  20. int adcRange = 2048; //Options: 2048, 4096, 8192, 16384
  21. //Configure sensor with these settings
  22. particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
  23. particleSensor.setPulseAmplitudeRed(0); //Turn off Red LED
  24. particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
  25. //Take an average of IR readings at power up
  26. unblockedValue = 0;
  27. for (byte x = 0 ; x < 32 ; x++) {
  28. unblockedValue += particleSensor.getIR(); //Read the IR value
  29. }
  30. unblockedValue /= 32;
  31. startTime = millis();
  32. }
  33. void loop() {
  34. samplesTaken++;
  35. Serial.print("IR[");
  36. Serial.print(particleSensor.getIR());
  37. Serial.print("] Hz[");
  38. Serial.print((float)samplesTaken / ((millis() - startTime) / 1000.0), 2);
  39. Serial.print("]");
  40. long currentDelta = particleSensor.getIR() - unblockedValue;
  41. Serial.print(" delta[");
  42. Serial.print(currentDelta);
  43. Serial.print("]");
  44. if (currentDelta > (long)100) {
  45. Serial.print(" Something is there!");
  46. }
  47. Serial.println();
  48. }

再次将手滑过传感器并查找消息“有东西在那里!” 打印在串行终端上。尝试测试传感器可以检测到某些东西的范围。

max30102 存在感应输出

请注意,MAX30102 能够读取最多 18 位或最多 262,144 个值。可以检测到极小的运动!

示例 3 – 读取温度

我们的下一个示例以摄氏度和华氏度输出板载温度传感器的读数。尽管温度读数应用于校准 HR 和 SpO2 测量值,但如果您需要灵敏且快速响应的温度传感器,它可能会很有用。

  1. #include <Wire.h>
  2. #include "MAX30105.h"
  3. MAX30105 particleSensor;
  4. void setup() {
  5. Serial.begin(9600);
  6. Serial.println("Initializing...");
  7. // Initialize sensor
  8. if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false) { //Use default I2C port, 400kHz speed
  9. Serial.println("MAX30102 was not found. Please check wiring/power. ");
  10. while (1);
  11. }
  12. //The LEDs are very low power and won't affect the temp reading much but
  13. //you may want to turn off the LEDs to avoid any local heating
  14. particleSensor.setup(0); //Configure sensor. Turn off LEDs
  15. particleSensor.enableDIETEMPRDY(); //Enable the temp ready interrupt. This is required.
  16. }
  17. void loop() {
  18. float temperature = particleSensor.readTemperature();
  19. Serial.print("temperatureC=");
  20. Serial.print(temperature, 4);
  21. float temperatureF = particleSensor.readTemperatureF();
  22. Serial.print(" temperatureF=");
  23. Serial.print(temperatureF, 4);
  24. Serial.println();
  25. }

现在尝试用手指加热传感器或对传感器轻轻吹气。您应该看到类似于下面的输出。

max30102内部温度传感器输出

示例 4 – 测量心率 (BPM)

这就是乐趣的开始!在此示例中,我们将测量所监测人员的心率(每分钟心跳数或 BPM)。

警告:

该草图以光学方式检测心率。这种方法很棘手并且容易给出错误的读数。所以请不要将其用于实际的医疗诊断。

  1. #include <Wire.h>
  2. #include "MAX30105.h"
  3. #include "heartRate.h"
  4. MAX30105 particleSensor;
  5. const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
  6. byte rates[RATE_SIZE]; //Array of heart rates
  7. byte rateSpot = 0;
  8. long lastBeat = 0; //Time at which the last beat occurred
  9. float beatsPerMinute;
  10. int beatAvg;
  11. void setup() {
  12. Serial.begin(115200);
  13. Serial.println("Initializing...");
  14. // Initialize sensor
  15. if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
  16. Serial.println("MAX30102 was not found. Please check wiring/power. ");
  17. while (1);
  18. }
  19. Serial.println("Place your index finger on the sensor with steady pressure.");
  20. particleSensor.setup(); //Configure sensor with default settings
  21. particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
  22. particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
  23. }
  24. void loop() {
  25. long irValue = particleSensor.getIR();
  26. if (checkForBeat(irValue) == true) {
  27. //We sensed a beat!
  28. long delta = millis() - lastBeat;
  29. lastBeat = millis();
  30. beatsPerMinute = 60 / (delta / 1000.0);
  31. if (beatsPerMinute < 255 && beatsPerMinute > 20) {
  32. rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
  33. rateSpot %= RATE_SIZE; //Wrap variable
  34. //Take average of readings
  35. beatAvg = 0;
  36. for (byte x = 0 ; x < RATE_SIZE ; x++)
  37. beatAvg += rates[x];
  38. beatAvg /= RATE_SIZE;
  39. }
  40. }
  41. Serial.print("IR=");
  42. Serial.print(irValue);
  43. Serial.print(", BPM=");
  44. Serial.print(beatsPerMinute);
  45. Serial.print(", Avg BPM=");
  46. Serial.print(beatAvg);
  47. if (irValue < 50000)
  48. Serial.print(" No finger?");
  49. Serial.println();
  50. }

上传草图后,将手指尽可能稳定地放在传感器上,并等待几秒钟以使读数稳定。你会看到这样的结果。

max30102心率输出

看不到心跳有困难吗?

如果您看不到心跳,请执行以下操作。

  • 如果握传感器太用力,手指上的血就会被挤干,而且没有任何迹象!如果握得太轻,就会因运动和环境光而产生噪音。脉搏传感器上的汗点压力(不要太硬,不要太软)将给出良好的干净信号。
  • 不同的压力会导致手指中的血液流动不同,从而导致传感器读数不稳定。尝试使用橡皮筋或其他紧固装置将传感器固定在手指上,施加恒定的压力。
  • 在身体有毛细组织的不同部位(例如耳垂或下唇)尝试使用传感器。

示例 5 – 测量血氧饱和度 (SpO2)

在最后一个示例中,我们将测量所监测人员的血氧水平 (SpO2)。继续尝试绘制草图。

  1. #include <Wire.h>
  2. #include "MAX30105.h"
  3. #include "spo2_algorithm.h"
  4. MAX30105 particleSensor;
  5. #define MAX_BRIGHTNESS 255
  6. #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
  7. //Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
  8. //To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
  9. uint16_t irBuffer[100]; //infrared LED sensor data
  10. uint16_t redBuffer[100]; //red LED sensor data
  11. #else
  12. uint32_t irBuffer[100]; //infrared LED sensor data
  13. uint32_t redBuffer[100]; //red LED sensor data
  14. #endif
  15. int32_t bufferLength; //data length
  16. int32_t spo2; //SPO2 value
  17. int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
  18. int32_t heartRate; //heart rate value
  19. int8_t validHeartRate; //indicator to show if the heart rate calculation is valid
  20. byte pulseLED = 11; //Must be on PWM pin
  21. byte readLED = 13; //Blinks with each data read
  22. void setup()
  23. {
  24. Serial.begin(115200); // initialize serial communication at 115200 bits per second:
  25. pinMode(pulseLED, OUTPUT);
  26. pinMode(readLED, OUTPUT);
  27. // Initialize sensor
  28. if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  29. {
  30. Serial.println(F("MAX30105 was not found. Please check wiring/power."));
  31. while (1);
  32. }
  33. Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
  34. while (Serial.available() == 0) ; //wait until user presses a key
  35. Serial.read();
  36. byte ledBrightness = 60; //Options: 0=Off to 255=50mA
  37. byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
  38. byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  39. byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  40. int pulseWidth = 411; //Options: 69, 118, 215, 411
  41. int adcRange = 4096; //Options: 2048, 4096, 8192, 16384
  42. particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
  43. }
  44. void loop()
  45. {
  46. bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps
  47. //read the first 100 samples, and determine the signal range
  48. for (byte i = 0 ; i < bufferLength ; i++)
  49. {
  50. while (particleSensor.available() == false) //do we have new data?
  51. particleSensor.check(); //Check the sensor for new data
  52. redBuffer[i] = particleSensor.getRed();
  53. irBuffer[i] = particleSensor.getIR();
  54. particleSensor.nextSample(); //We're finished with this sample so move to next sample
  55. Serial.print(F("red="));
  56. Serial.print(redBuffer[i], DEC);
  57. Serial.print(F(", ir="));
  58. Serial.println(irBuffer[i], DEC);
  59. }
  60. //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
  61. maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  62. //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second
  63. while (1)
  64. {
  65. //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
  66. for (byte i = 25; i < 100; i++)
  67. {
  68. redBuffer[i - 25] = redBuffer[i];
  69. irBuffer[i - 25] = irBuffer[i];
  70. }
  71. //take 25 sets of samples before calculating the heart rate.
  72. for (byte i = 75; i < 100; i++)
  73. {
  74. while (particleSensor.available() == false) //do we have new data?
  75. particleSensor.check(); //Check the sensor for new data
  76. digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read
  77. redBuffer[i] = particleSensor.getRed();
  78. irBuffer[i] = particleSensor.getIR();
  79. particleSensor.nextSample(); //We're finished with this sample so move to next sample
  80. //send samples and calculation result to terminal program through UART
  81. Serial.print(F("red="));
  82. Serial.print(redBuffer[i], DEC);
  83. Serial.print(F(", ir="));
  84. Serial.print(irBuffer[i], DEC);
  85. Serial.print(F(", HR="));
  86. Serial.print(heartRate, DEC);
  87. Serial.print(F(", HRvalid="));
  88. Serial.print(validHeartRate, DEC);
  89. Serial.print(F(", SPO2="));
  90. Serial.print(spo2, DEC);
  91. Serial.print(F(", SPO2Valid="));
  92. Serial.println(validSPO2, DEC);
  93. }
  94. //After gathering 25 new samples recalculate HR and SP02
  95. maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  96. }
  97. }

上传草图后,将手指尽可能稳定地放在传感器上,并等待几秒钟以使读数稳定;。你会看到这样的结果。

max30102心率和血氧饱和度输出

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/401495
推荐阅读
相关标签
  

闽ICP备14008679号