MAX30102:Arduino 心率監測器和血氧計模組

MAX30102

在這段時間裡,我們已經展示了大量的 電子元器件 與...兼容 Arduino 等板或相容板以及許多其他創客或 DIY 工作。現在我們將向您介紹該模組 MAX30102,其中包括一個測量脈搏和血氧的感測器。

透過這種方式,您還可以創建可穿戴設備,例如自製的活動手環或硬體 監測健康狀況 透過在該設備中整合心率監測器和血氧計,可以提供該人的生物識別數據或遙測數據...

什麼是心率監測器?它是如何運作的?

Un 脈搏感測器或心率監測器 它是一種用於即時測量人的心率的電子設備。它主要用於運動場,以監測訓練期間或日常的表現和努力。心率監測器在運動員中很受歡迎,但它們也是醫療中心了解心率(即心率或每分鐘心跳次數)的基本設備:

  • 心率每分鐘:顯示心率,即每分鐘的心跳次數。

在所有情況下, 感測器捕捉每次心跳的血量變化。這種變化被轉化為電訊號,經過處理後可以獲得心率。一些心率監測器還包括放大和雜訊消除電路,以提高讀數的準確性。

什麼是血氧計?它是如何運作的?

Un 血氧計是一種醫療或運動設備 用於測量血液中的氧飽和度。該設備提供值從 0 到 100% 的血氧飽和度數據。同一設備通常還包含心率選項,指示用於監測或記錄的所有資訊。

洛斯·達托斯克 測量血氧計 是:

  • %血氧飽和度:指血液中氧飽和度的百分比。

血氧計像夾子一樣放置,以適應我們手指的形態,或者也可以放置在身體的其他地方,就像心率監測器一樣,例如手腕,在許多活動手環中都可以看到,

關於其操作,血氧計會發出不同的訊號 光波長 穿過皮膚的。作用於這種光的是血紅蛋白,一種負責運輸氧氣的血液分子,根據其運輸的氧氣水平吸收不同數量的光。詳細流程如下:

  1. 發光- 血氧計發出兩種波長的光,一種是紅光,一種是紅外線,這些光穿過放在設備上的手指。
  2. 光吸收:血紅蛋白是紅血球中攜帶氧氣的分子,它吸收不同數量的這些光。含氧血紅素(氧合血紅素)和無氧血紅素(脫氧血紅素)具有不同的光吸收特性。
  3. 光檢測:光發射器另一側的偵測器收集穿過手指的光。
  4. 氧飽和度計算- 此裝置計算氧合血紅素與存在的血紅素總量(氧合血紅素和脫氧血紅素)的比率。此比例以血氧飽和度百分比 (%SpO2) 表示。這是透過能夠解釋這些電訊號並將其轉換為數值的處理器來完成的。

什麼是MAX30102模組?

傳感器 MAX30102,Maxim Integrated 生產,是一款結合了心率監測器和血氧計功能的整合式設備。該感測器可以輕鬆地與 Arduino 等微控制器一起使用。 MAX30102 屬於該公司的 MAX3010x 系列光學感測器。

其運作是基於血液對光吸收的變化,取決於其 血氧飽和度與脈搏 正如我在前兩節中提到的。該感測器配備兩個 LED,一個紅色,一個紅外線。它被放置在皮膚上,例如手指或手腕上,並檢測反射光以確定氧飽和度。

與MAX30102進行通信 透過I2C總線,可以輕鬆連接到 Arduino 等微控制器。 MAX30102需要雙電源:1.8V用於邏輯,3.3V用於LED。通常出現在已經包含必要電平匹配的 5V 模組上。

MAX30102是用於家庭或運動項目的感測器,也就是說,對於專業醫療用途來說,它可能不具備足夠的可靠性和靈敏度。

La 光學脈搏血氧儀 它是一種確定血液中氧飽和度百分比的非侵入性方法。正如我之前提到的,它是基於血紅蛋白(Hb)和氧合血紅蛋白(HbO2)對於不同波長的光吸收係數的差異。含氧量高的血液吸收較多的紅外光,而含氧量低的血液吸收較多的紅光。在身體皮膚足夠薄並且下面有血管的區域,這種差異可以用來確定氧飽和度。

帶有脈搏和血氧感測器的MAX30102模組的特點

MAX30102 包括:

  • 2 個 LED,一個紅色 (660nm) 和一個紅外線 (880nm)
  • 2x 光電二極體用於測量反射光
  • 18 位元 ADC 轉換器,取樣率為每秒 50 至 3200 個取樣。
  • 此外,它還具有用於訊號放大和過濾、消除環境光、抑制 50-60Hz 頻率(人造光)和溫度補償所需的電子裝置。

模組消耗 最高可達50mA 在測量過程中,雖然可以透過程式調整強度,但在測量過程中採用 0.7μA 的低功耗模式。

價格和購買地點

用於測量脈搏和血氧的 MAX30102 感測器 他們很便宜。您只需幾歐元即可在 eBay、Aliexpress 或 Amazon 等網站上購買這些模組。您會看到有多種類型,我們推薦以下幾種:

與 Arduino 的連接和範例

Arduino IDE、數據類型、編程

若要使用 Arduino 測試 MAX30102,請先將模組連接到 Arduino 板。這 連接非常簡單,您只需連接以下內容:

  1. 模組的Vcc必須連接到Arduino板的5V輸出。
  2. 模組的GND必須連接到Arduino板的GND插座。
  3. 模組的 SCL 必須連接到 Arduino 板的類比輸入之一,例如 A5。
  4. 模組的 SDA 必須連接到 Arduino 板的另一個類比輸入,例如 A4。

一旦在 MAX30102 板和 Arduino 板之間建立了適當的連接,下一步就是編寫原始程式碼或草圖以使其工作並開始接收來自相關人員的生物識別資料。這就像在中編寫以下程式碼一樣簡單 Arduino IDE 並對板進行編程:

您還需要在 Arduino IDE 中安裝一個程式庫才能使用它。該庫由 SparkFun 開發,可在 https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library.
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"

MAX30102 pulsioximetro;


#define MAX_BRIGHTNESS 255


#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Arduino Uno no tiene suficiente SRAM para almacenar 100 muestreos, por lo que hay que truncar las muestras en 16-bit MSB.
uint16_t pulsoBuffer[100]; //infrared LED sensor data
uint16_t oxiBuffer[100];  //red LED sensor data

#else
uint32_t pulsoBuffer[100]; //Sensores
uint32_t oxiBuffer[100];  

#endif

int32_t BufferLongitud; //Longitud de datos
int32_t spo2; //Valor de SPO2
int8_t SPO2valido; //Indicador de validez del valor SPO2
int32_t rangopulsacion; //PR BPM o pulsaciones
int8_t validrangopulsacion; //Indicador de validez del valor PR BPM

byte pulsoLED = 11; //Pin PWM
byte lecturaLED = 13; //Titila con cada lectura

void setup()
{
  Serial.begin(115200); // Inicia la comunicación con el microcontrolador a 115200 bits/segundo

  pinMode(pulsoLED, OUTPUT);
  pinMode(lecturaLED, OUTPUT);

  // Inicializar sensores
  if (!pulsioximetro.begin(Wire, I2C_SPEED_FAST)) //Usar el bus I2C a 400kHz 
  {
    Serial.println(F("MAX30102 no encontrado. Por favor, comprueba la conexión y alimentación del módulo."));
    while (1);
  }

  Serial.println(F("Pon el sensor en contacto con tu dedo y presiona cualquier tecla para iniciar la conversión."));
  while (Serial.available() == 0) ; //Esperar hasta que se pulsa una tecla
  Serial.read();

  byte brilloLED = 60; //Opciones: 0=Apagado hasta 255=50mA
  byte mediaMuestreo = 4; //Opciones: 1, 2, 4, 8, 16, 32
  byte ModoLED = 2; //Opciones: 1 = Rojo solo, 2 = Rojo + IR, 3 = Rojo + IR + Verde
  byte rangoMuestreo = 100; //Opciones: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int anchoPulso = 411; //Opciones: 69, 118, 215, 411
  int rangoADC = 4096; //Opciones: 2048, 4096, 8192, 16384

  pulsioximetro.setup(brilloLED, mediaMuestreo, ModoLED, rangoMuestreo, anchoPulso, rangoADC); //Configuración del módulo
}

void loop()
{
  BufferLongitud = 100; //10 almacenamientos en el buffer con 4 segundos corriendo a 25sps

  //Leer las primeras 100 muestras
  for (byte i = 0 ; i < BufferLongitud ; i++)
  {
    while (pulsioximetro.available() == false) //Comprobar nuevos datos
      pulsioximetro.check(); 
    oxiBuffer[i] = pulsioximetro.getRed();
    pulsoBuffer[i] = pulsioximetro.getIR();
    pulsioximetro.siguienteMuestreo(); //Muestreo terminado, ir al siguiente muestreo

    Serial.print(F("red="));
    Serial.print(oxiBuffer[i], DEC);
    Serial.print(F(", ir="));
    Serial.println(pulsoBuffer[i], DEC);
  }

  //Calcular el valor del pulso PM y SpO2 tras los primeros 100 samples
  maxim_heart_rate_and_oxygen_saturation(pulsoBuffer, BufferLongitud, oxiBuffer, &spo2, &SPO2valido, &rangopulsacion, &validrangopulsacion);

  //Calcular muestreos continuos
  while (1)
  {
    //Volcar los 25 primeros valores en memoria y desplazar los últimos 75 arriba
    for (byte i = 25; i < 100; i++)
    {
      oxiBuffer[i - 25] = oxiBuffer[i];
      pulsoBuffer[i - 25] = pulsoBuffer[i];
    }

    for (byte i = 75; i < 100; i++)
    {
      while (pulsioximetro.available() == false) //Comprobar si existen nuevos datos
        pulsioximetro.check(); 

      digitalWrite(lecturaLED, !digitalRead(lecturaLED)); //Parpadea el LED on-board con cada dato

      oxiBuffer[i] = pulsioximetro.getRed();
      pulsoBuffer[i] = pulsioximetro.getIR();
      pulsioximetro.siguienteMuestreo(); //Al finalizar, moverse al siguiente muestreo

      Serial.print(F("Oxígeno="));
      Serial.print(oxiBuffer[i], DEC);
      Serial.print(F(", Pulso="));
      Serial.print(pulsoBuffer[i], DEC);

      Serial.print(F(", HR="));
      Serial.print(rangopulsacion, DEC);

      Serial.print(F(", HRvalid="));
      Serial.print(validrangopulsacion, DEC);

      Serial.print(F(", SPO2="));
      Serial.print(spo2, DEC);

      Serial.print(F(", SPO2 válido="));
      Serial.println(SPO2valido, DEC);
    }

    //Recalcular tras los primeros muestreos
    maxim_heart_rate_and_oxygen_saturation(pulsoBuffer, BufferLongitud, oxiBuffer, &spo2, &SPO2valido, &rangopulsacion, &validrangopulsacion);
  }
}

當然,你可以根據自己的需求修改程式碼,這只是一個例子...


成為第一個發表評論

發表您的評論

您的電子郵件地址將不會被發表。 必填字段標有 *

*

*

  1. 負責數據:MiguelÁngelGatón
  2. 數據用途:控制垃圾郵件,註釋管理。
  3. 合法性:您的同意
  4. 數據通訊:除非有法律義務,否則不會將數據傳達給第三方。
  5. 數據存儲:Occentus Networks(EU)託管的數據庫
  6. 權利:您可以隨時限制,恢復和刪除您的信息。