赞
踩
MAX30102脉搏血氧计和心率传感器是一款基于I2C的低功耗即插即用生物识别传感器。想要将实时心率数据合并到项目中的学生、爱好者、工程师、制造商以及游戏和移动开发人员都可以使用它。
该模块采用 MAX30102——来自 Analog Devices 的现代集成脉搏血氧计和心率传感器 IC ( MAX30100的后继产品)。它结合了两个 LED、一个光电探测器、优化的光学器件和低噪声模拟信号处理,可检测脉搏血氧饱和度 (SpO2) 和心率 (HR) 信号。
MAX30102 在一侧窗户后面有两个 LED – 一个红色 LED 和一个红外 LED。另一侧是一个非常灵敏的光电探测器。这个想法是,您一次点亮一个 LED,检测探测器上反射回来的光量,然后根据签名,您可以测量血氧水平和心率。
MAX30102芯片需要两种不同的电源电压:IC的电源电压为1.8V,红色和红外LED的电源电压为3.3V。因此该模块配有 3.3V 和 1.8V 稳压器。
在 PCB 背面,您会发现一个焊接跳线,可用于在 3.3V 和 1.8V 逻辑电平之间进行选择。默认选择 3.3V 逻辑电平,与 Arduino 的逻辑电平兼容。但您也可以根据您的要求选择 1.8V 逻辑电平。这允许您将模块连接到具有 5V、3.3V、甚至 1.8V 电平 I/O 的任何微控制器。
MAX30102最重要的特性之一是其低功耗:测量期间MAX30102的功耗低于600μA。此外,还可以将 MAX30102 置于待机模式,此时功耗仅为 0.7μA。这种低功耗允许在手机、可穿戴设备或智能手表等电池供电设备中实施。
MAX30102具有片上温度传感器,可用于补偿环境变化并校准测量结果。
这是一款相当精确的温度传感器,可测量 -40°C 至 +85°C 范围内的“芯片温度”,精度为 ±1°C。
该模块使用简单的两线 I2C 接口与微控制器进行通信。它有一个固定的I2C地址:0xAE HEX(用于写操作)和0xAF HEX(用于读操作)。
MAX30102嵌入了一个用于存储数据样本的FIFO缓冲器。FIFO 具有 32 个样本存储库,这意味着它可以容纳多达 32 个 SpO2 和心率样本。FIFO 缓冲区可以减轻微控制器从传感器读取每个新数据样本的负担,从而节省系统功耗。
MAX30102可编程为产生中断,允许主机微控制器在传感器收集数据的同时执行其他任务。可以为 5 个不同的源启用中断:
INT 线是开漏极,因此它被板载电阻拉高。当中断发生时,INT 引脚变为低电平并保持低电平直到中断被清除。
以下是技术规格:
电源 | 3.3V至5.5V |
电流消耗 | ~600μA(测量期间) |
~0.7μA(待机模式期间) | |
红色 LED 波长 | 660nm |
红外 LED 波长 | 880nm |
温度范围 | -40°C 至 +85°C |
温度准确度 | ±1℃ |
您可以从数据表中找到有关 MAX30102 传感器的详细信息。
MAX30102 或任何光学脉搏血氧计和心率传感器由一对高强度 LED(红色和红外,波长不同)和一个光电探测器组成。这些 LED 的波长分别为 660nm 和 880nm。
MAX30102 的工作原理是将两束光照射到手指或耳垂(或者基本上是皮肤不太厚的任何地方,因此两束光可以轻松穿透组织),并使用光电探测器测量反射光量。这种通过光检测脉搏的方法称为光电体积描记法。
MAX30102的工作可以分为两部分:心率测量和脉搏血氧饱和度(测量血液中的含氧量)。
动脉血中的氧合血红蛋白(HbO2)具有吸收红外光的特性。血液越红(血红蛋白越高),吸收的红外光就越多。当血液随着每次心跳泵入手指时,反射光的量会发生变化,从而在光电探测器的输出端产生变化的波形。当您继续照射光线并获取光电探测器读数时,您很快就会开始获得心率 (HR) 脉搏读数。
脉搏血氧测定法的原理是,吸收的红光和红外光的量根据血液中的氧含量而变化。下图是含氧血红蛋白(HbO2)和脱氧血红蛋白(Hb)的吸收光谱。
从图中可以看出,脱氧血液吸收更多红光 (660nm),而含氧血液吸收更多红外光 (880nm)。通过测量光电探测器接收到的红外光和红光的比率,可以计算出血液中的氧含量 (SpO2)。
你可知道?
1935 年,德国医生 Karl Matthes 提出通过测量红光和红外光的吸光度来测量血红蛋白氧饱和度 (HbO2)。
起初,没有好的光电探测器,因此使用光谱的绿光波段代替红外波段。随着技术的进步,更可靠的方法被开发出来,绿光被红外光取代。
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是地面。
现在我们已经了解了该模块的所有信息,我们可以开始将其连接到我们的 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 传感器。然而,在我们的示例中,我们使用的是SparkFun Electronics的产品。该库展示了 MAX30102 的大部分功能,并提供简单易用的函数来计算脉率和 SpO2。您可以从 Arduino IDE 库管理器下载该库。
要安装库,请导航至 Sketch > Include Library > Manage Libraries... 等待库管理器下载库索引并更新已安装库的列表。
输入MAX3010x来过滤您的搜索。查找SparkFun MAX3010x 脉冲和接近传感器库。单击该条目,然后选择安装。
SparkFun_MAX3010x 库有许多示例草图。您可以使用这些示例草图作为开发自己的代码的基础。
要访问示例草图,请导航至文件 > 示例 > SparkFun MAX3010x 脉冲和接近传感器库。您将看到精选的示例草图。
第一个示例输出传感器读取的原始值(IR 和红色读数)。将其加载到 Arduino 上并打开串行终端以查看打印值。
- #include <Wire.h>
- #include "MAX30105.h"
-
- MAX30105 particleSensor;
-
- void setup() {
- Serial.begin(9600);
-
- // Initialize sensor
- if (particleSensor.begin() == false) {
- Serial.println("MAX30102 was not found. Please check wiring/power.");
- while (1);
- }
-
- particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
- }
-
- void loop() {
- Serial.print(" R[");
- Serial.print(particleSensor.getRed());
- Serial.print("] IR[");
- Serial.print(particleSensor.getIR());
- Serial.println("]");
- }

将传感器朝上,将手滑过传感器。当您的手反射不同量的光时,您应该会看到值的变化。
如果您只查看值,则串行数据可能很难可视化。如果您使用的是 Arduino IDE v1.6.6+,可以选择使用Arduino 串行绘图仪查看图表上的数据。
首先,将上面代码中的loop()替换为以下代码片段:
- void loop() {
- Serial.print(particleSensor.getRed());
- Serial.print(", ");
- Serial.println(particleSensor.getIR());
- }
在 Arduino IDE 中,选择“工具”>“串行绘图仪”。当您在传感器上滑动手时,您应该会看到类似于下图的波浪。
我们的下一个实验展示了如何使用 MAX30102 传感器作为通用接近传感器或反射传感器,并且可以作为更实际的实验和项目的基础。
此示例的工作原理是在设置期间获取少量读数并将它们平均在一起。然后它使用该平均值作为基线。如果传感器检测到平均值有显着变化,“有东西在那里!” 被打印。继续尝试绘制草图。
- #include <Wire.h>
- #include "MAX30105.h"
-
- MAX30105 particleSensor;
-
- long samplesTaken = 0; //Counter for calculating the Hz or read rate
- long unblockedValue; //Average IR at power up
- long startTime; //Used to calculate measurement rate
-
- void setup() {
- Serial.begin(9600);
-
- // Initialize sensor
- if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false) { //Use default I2C port, 400kHz speed
- Serial.println("MAX30102 was not found. Please check wiring/power. ");
- while (1);
- }
-
- //Setup to sense up to 18 inches, max LED brightness
- byte ledBrightness = 0xFF; //Options: 0=Off to 255=50mA
- byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
- byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
- int sampleRate = 400; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
- int pulseWidth = 411; //Options: 69, 118, 215, 411
- int adcRange = 2048; //Options: 2048, 4096, 8192, 16384
-
- //Configure sensor with these settings
- particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
-
- particleSensor.setPulseAmplitudeRed(0); //Turn off Red LED
- particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
-
- //Take an average of IR readings at power up
- unblockedValue = 0;
- for (byte x = 0 ; x < 32 ; x++) {
- unblockedValue += particleSensor.getIR(); //Read the IR value
- }
- unblockedValue /= 32;
-
- startTime = millis();
- }
-
- void loop() {
- samplesTaken++;
-
- Serial.print("IR[");
- Serial.print(particleSensor.getIR());
- Serial.print("] Hz[");
- Serial.print((float)samplesTaken / ((millis() - startTime) / 1000.0), 2);
- Serial.print("]");
-
- long currentDelta = particleSensor.getIR() - unblockedValue;
-
- Serial.print(" delta[");
- Serial.print(currentDelta);
- Serial.print("]");
-
- if (currentDelta > (long)100) {
- Serial.print(" Something is there!");
- }
-
- Serial.println();
- }

再次将手滑过传感器并查找消息“有东西在那里!” 打印在串行终端上。尝试测试传感器可以检测到某些东西的范围。
请注意,MAX30102 能够读取最多 18 位或最多 262,144 个值。可以检测到极小的运动!
我们的下一个示例以摄氏度和华氏度输出板载温度传感器的读数。尽管温度读数应用于校准 HR 和 SpO2 测量值,但如果您需要灵敏且快速响应的温度传感器,它可能会很有用。
- #include <Wire.h>
-
- #include "MAX30105.h"
- MAX30105 particleSensor;
-
- void setup() {
- Serial.begin(9600);
- Serial.println("Initializing...");
-
- // Initialize sensor
- if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false) { //Use default I2C port, 400kHz speed
- Serial.println("MAX30102 was not found. Please check wiring/power. ");
- while (1);
- }
-
- //The LEDs are very low power and won't affect the temp reading much but
- //you may want to turn off the LEDs to avoid any local heating
- particleSensor.setup(0); //Configure sensor. Turn off LEDs
-
- particleSensor.enableDIETEMPRDY(); //Enable the temp ready interrupt. This is required.
- }
-
- void loop() {
- float temperature = particleSensor.readTemperature();
-
- Serial.print("temperatureC=");
- Serial.print(temperature, 4);
-
- float temperatureF = particleSensor.readTemperatureF();
-
- Serial.print(" temperatureF=");
- Serial.print(temperatureF, 4);
-
- Serial.println();
- }

现在尝试用手指加热传感器或对传感器轻轻吹气。您应该看到类似于下面的输出。
这就是乐趣的开始!在此示例中,我们将测量所监测人员的心率(每分钟心跳数或 BPM)。
警告:
该草图以光学方式检测心率。这种方法很棘手并且容易给出错误的读数。所以请不要将其用于实际的医疗诊断。
- #include <Wire.h>
- #include "MAX30105.h"
- #include "heartRate.h"
-
- MAX30105 particleSensor;
-
- const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
- byte rates[RATE_SIZE]; //Array of heart rates
- byte rateSpot = 0;
- long lastBeat = 0; //Time at which the last beat occurred
-
- float beatsPerMinute;
- int beatAvg;
-
- void setup() {
- Serial.begin(115200);
- Serial.println("Initializing...");
-
- // Initialize sensor
- if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
- Serial.println("MAX30102 was not found. Please check wiring/power. ");
- while (1);
- }
- Serial.println("Place your index finger on the sensor with steady pressure.");
-
- particleSensor.setup(); //Configure sensor with default settings
- particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
- particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
- }
-
- void loop() {
- long irValue = particleSensor.getIR();
-
- if (checkForBeat(irValue) == true) {
- //We sensed a beat!
- long delta = millis() - lastBeat;
- lastBeat = millis();
-
- beatsPerMinute = 60 / (delta / 1000.0);
-
- if (beatsPerMinute < 255 && beatsPerMinute > 20) {
- rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
- rateSpot %= RATE_SIZE; //Wrap variable
-
- //Take average of readings
- beatAvg = 0;
- for (byte x = 0 ; x < RATE_SIZE ; x++)
- beatAvg += rates[x];
- beatAvg /= RATE_SIZE;
- }
- }
-
- Serial.print("IR=");
- Serial.print(irValue);
- Serial.print(", BPM=");
- Serial.print(beatsPerMinute);
- Serial.print(", Avg BPM=");
- Serial.print(beatAvg);
-
- if (irValue < 50000)
- Serial.print(" No finger?");
-
- Serial.println();
- }

上传草图后,将手指尽可能稳定地放在传感器上,并等待几秒钟以使读数稳定。你会看到这样的结果。
如果您看不到心跳,请执行以下操作。
在最后一个示例中,我们将测量所监测人员的血氧水平 (SpO2)。继续尝试绘制草图。
- #include <Wire.h>
- #include "MAX30105.h"
- #include "spo2_algorithm.h"
-
- MAX30105 particleSensor;
-
- #define MAX_BRIGHTNESS 255
-
- #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
- //Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
- //To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
- uint16_t irBuffer[100]; //infrared LED sensor data
- uint16_t redBuffer[100]; //red LED sensor data
- #else
- uint32_t irBuffer[100]; //infrared LED sensor data
- uint32_t redBuffer[100]; //red LED sensor data
- #endif
-
- int32_t bufferLength; //data length
- int32_t spo2; //SPO2 value
- int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
- int32_t heartRate; //heart rate value
- int8_t validHeartRate; //indicator to show if the heart rate calculation is valid
-
- byte pulseLED = 11; //Must be on PWM pin
- byte readLED = 13; //Blinks with each data read
-
- void setup()
- {
- Serial.begin(115200); // initialize serial communication at 115200 bits per second:
-
- pinMode(pulseLED, OUTPUT);
- pinMode(readLED, OUTPUT);
-
- // Initialize sensor
- if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
- {
- Serial.println(F("MAX30105 was not found. Please check wiring/power."));
- while (1);
- }
-
- Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
- while (Serial.available() == 0) ; //wait until user presses a key
- Serial.read();
-
- byte ledBrightness = 60; //Options: 0=Off to 255=50mA
- byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
- byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
- byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
- int pulseWidth = 411; //Options: 69, 118, 215, 411
- int adcRange = 4096; //Options: 2048, 4096, 8192, 16384
-
- particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
- }
-
- void loop()
- {
- bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps
-
- //read the first 100 samples, and determine the signal range
- for (byte i = 0 ; i < bufferLength ; i++)
- {
- while (particleSensor.available() == false) //do we have new data?
- particleSensor.check(); //Check the sensor for new data
-
- redBuffer[i] = particleSensor.getRed();
- irBuffer[i] = particleSensor.getIR();
- particleSensor.nextSample(); //We're finished with this sample so move to next sample
-
- Serial.print(F("red="));
- Serial.print(redBuffer[i], DEC);
- Serial.print(F(", ir="));
- Serial.println(irBuffer[i], DEC);
- }
-
- //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
- maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
-
- //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second
- while (1)
- {
- //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
- for (byte i = 25; i < 100; i++)
- {
- redBuffer[i - 25] = redBuffer[i];
- irBuffer[i - 25] = irBuffer[i];
- }
-
- //take 25 sets of samples before calculating the heart rate.
- for (byte i = 75; i < 100; i++)
- {
- while (particleSensor.available() == false) //do we have new data?
- particleSensor.check(); //Check the sensor for new data
-
- digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read
-
- redBuffer[i] = particleSensor.getRed();
- irBuffer[i] = particleSensor.getIR();
- particleSensor.nextSample(); //We're finished with this sample so move to next sample
-
- //send samples and calculation result to terminal program through UART
- Serial.print(F("red="));
- Serial.print(redBuffer[i], DEC);
- Serial.print(F(", ir="));
- Serial.print(irBuffer[i], DEC);
-
- Serial.print(F(", HR="));
- Serial.print(heartRate, DEC);
-
- Serial.print(F(", HRvalid="));
- Serial.print(validHeartRate, DEC);
-
- Serial.print(F(", SPO2="));
- Serial.print(spo2, DEC);
-
- Serial.print(F(", SPO2Valid="));
- Serial.println(validSPO2, DEC);
- }
-
- //After gathering 25 new samples recalculate HR and SP02
- maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
- }
- }

上传草图后,将手指尽可能稳定地放在传感器上,并等待几秒钟以使读数稳定;。你会看到这样的结果。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。