【雕爺學編程】Arduino動手做(100)---MAX30102手腕心率模塊4

37款傳感器與執行器的提法,在網絡上廣泛流傳,其實Arduino能夠兼容的傳感器模塊肯定是不止這37種的。鑑於本人手頭積累了一些傳感器和執行器模塊,依照實踐出真知(一定要動手做)的理念,以學習和交流爲目的,這裏準備逐一動手嘗試系列實驗,不管成功(程序走通)與否,都會記錄下來—小小的進步或是搞不掂的問題,希望能夠拋磚引玉。

【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
實驗一百:MAX30102血氧儀手腕心率脈搏檢測心跳傳感器模塊

實驗接線示意圖
硬件連接(MAX30102 到 Arduino):
-5V = 5V(允許 3.3V)
-接地 = 接地
-SDA = A4(或 SDA)
-SCL = A5(或 SCL)
-INT = 中斷腳未連接

 

MAX30102心率血氧傳感器模塊使用注意事項:
1、手指直接按壓可能會出現壓力變化,壓力變化會對傳感器數值產生影響。
2、佩戴部位爲手指,佩戴沒有方向區別。
3、本模塊並非專業醫療儀器,不能作爲輔助配件參與診斷和治療。

程序五:在 Arduino 的串口繪圖器上顯示用戶的心跳
Arduino參考開源代碼

/*
  【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
  程序五:在 Arduino 的串口繪圖器上顯示用戶的心跳
  下載庫: http://librarymanager/All#SparkFun_MAX30105
*/

#include <Wire.h>
#include "MAX30105.h"

MAX30105 particleSensor;

void setup() {
  Serial.begin(115200);
  Serial.println("正在初始化...");

  // 初始化傳感器
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //使用默認 I2C 端口,400kHz 速度
  {
    Serial.println("沒有找到MAX30105,請檢查接線/電源。 ");
    while (1);
  }

  //設置以感應串口繪圖器上漂亮的曲線
  byte ledBrightness = 0x1F; //亮度選項:0=關 到 255=50mA
  byte sampleAverage = 8; //樣本平均值選項:1、2、4、8、16、32
  byte ledMode = 3; //工作方式選項:1 = 僅紅色,2 = 紅色 + IR,3 = 紅色 + IR + 綠色
  int sampleRate = 100; //採樣率選項:50、100、200、400、800、1000、1600、3200
  int pulseWidth = 411; //脈寬選項:69、118、215、411
  int adcRange = 4096; //選項:2048、4096、8192、16384

  //使用這些設置來配置傳感器
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);

  //Arduino 繪圖儀令人討厭地自動縮放。爲了解決這個問題,預先填充
  //繪圖儀的傳感器平均讀數爲 500

  //在通電時取平均 IR 讀數
  const byte avgAmount = 64;
  long baseValue = 0;
  for (byte x = 0 ; x < avgAmount ; x++)
  {
    baseValue += particleSensor.getIR(); //讀取IR值
  }
  baseValue /= avgAmount;

  //預填充繪圖儀,使 Y 比例接近 IR 值
  for (int x = 0 ; x < 500 ; x++)
    Serial.println(baseValue);
}

void loop() {
  Serial.println(particleSensor.getIR()); //將原始數據發送到繪圖器
  delay(10);
}

  

打開Arduino IDE——工具——串口繪圖器,查看實驗波形
實驗串口繪圖器返回情況

 

程序六:最簡輸出傳感器讀取的原始值(IR 和紅色讀數)
Arduino參考開源代碼

/*
  【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
  程序六:最簡輸出傳感器讀取的原始值(IR 和紅色讀數)
  下載庫: http://librarymanager/All#SparkFun_MAX30105
*/

#include <Wire.h>

#include "MAX30105.h"//導入驅動庫

MAX30105 particleSensor;

void setup() {
  Serial.begin(9600);//初始化串口

  Serial.println("MAX30102準備就緒");

  // 初始化傳感器
  if (particleSensor.begin() == false) {
    Serial.println("沒有找到MAX30102,請檢查接線/電源。");
    while (1);
  }

  particleSensor.setup(); //配置傳感器,使用 6.4mA 進行 LED 驅動
}

void loop() {
  Serial.print(" R[");//串口打印傳感器讀取的原始值
  Serial.print(particleSensor.getRed());
  Serial.print("] IR[");
  Serial.print(particleSensor.getIR());
  Serial.println("]");

  delay(1000);
}

  實驗串口返回情況

程序七:最簡繪製心率波形
Arduino參考開源代碼

/*
  【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
  程序七:最簡繪製心率波形
  下載庫: http://librarymanager/All#SparkFun_MAX30105
*/

#include <Wire.h>
#include "MAX30105.h"//導入驅動庫
MAX30105 particleSensor;

void setup() {
  Serial.begin(9600);//初始化串口
  Serial.println("MAX30102準備就緒");

  // 初始化傳感器
  if (particleSensor.begin() == false) {
    Serial.println("沒有找到MAX30102,請檢查接線/電源。");
    while (1);
  }

  particleSensor.setup(); //配置傳感器,使用 6.4mA 進行 LED 驅動
}

void loop() {
  Serial.print(particleSensor.getRed());
  Serial.print(", ");
  Serial.println(particleSensor.getIR());
  delay(6);
}

  

打開Arduino IDE——工具——串口繪圖器,查看實驗波形
實驗串口繪圖器返回情況

在 Arduino IDE 中,選擇工具 > 串行繪圖儀。當您將手滑過傳感器時,您應該會看到類似於下圖的波浪。

程序八:以光學方式檢測心率的演示
說明:這種方法很棘手,容易給出錯誤的讀數。所以請不要將它用於實際的醫療診斷。
Arduino參考開源代碼

/*
  【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
  程序八:以光學方式檢測心率的演示
  說明:這種方法很棘手,容易給出錯誤的讀數。所以請不要將它用於實際的醫療診斷。
  下載庫: http://librarymanager/All#SparkFun_MAX30105
*/

#include <Wire.h>
#include "MAX30105.h"//導入驅動庫
#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4; //增加這個以獲得更多平均,4比較好。
byte rates[RATE_SIZE]; //心率數組
byte rateSpot = 0;
long lastBeat = 0; //最後一個節拍發生的時間

float beatsPerMinute;
int beatAvg;

void setup() {
  Serial.begin(115200);
  Serial.println("Initializing...");

  // 初始化傳感器
  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(); //使用默認設置配置傳感器
  particleSensor.setPulseAmplitudeRed(0x0A); //將紅色LED變爲低電平表示傳感器正在運行
  particleSensor.setPulseAmplitudeGreen(0); //關閉綠色LED
}

void loop() {
  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true) {
    //我們感覺到了節拍!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute; //將此讀數存儲在數組中
      rateSpot %= RATE_SIZE; //包裝變量

      //取讀數的平均值
      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)
說明:將手指儘可能穩定地放在傳感器上,然後等待幾秒鐘以使讀數有意義。
Arduino參考開源代碼

/*
  【Arduino】168種傳感器模塊系列實驗(資料代碼+仿真編程+圖形編程)
  程序九:測量血氧飽和度 (SpO2)
  說明:將手指儘可能穩定地放在傳感器上,然後等待幾秒鐘以使讀數有意義。
  下載庫: http://librarymanager/All#SparkFun_MAX30105
*/

#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 沒有足夠的 SRAM 來存儲 100 個 32 位格式的 IR LED 數據和紅色 LED 數據樣本
//爲了解決這個問題,採樣數據的16位MSB將被截斷。樣本變成 16 位數據。
uint16_t irBuffer[100];   //紅外LED傳感器數據
uint16_t redBuffer[100];  //紅色LED傳感器數據
#else
uint32_t irBuffer[100];   //紅外LED傳感器數據
uint32_t redBuffer[100];  //紅色LED傳感器數據
#endif

int32_t bufferLength; //數據長度
int32_t spo2; //SPO2值
int8_t validSPO2; //用於顯示 SPO2 計算是否有效的指標
int32_t heartRate; //心率值
int8_t validHeartRate; //顯示心率計算是否有效的指標

byte pulseLED = 11; //必須在PWM引腳上
byte readLED = 13; //每次讀取數據時閃爍

void setup() {
  Serial.begin(115200); // 以每秒 115200 位初始化串行通信

  pinMode(pulseLED, OUTPUT);
  pinMode(readLED, OUTPUT);

  // 初始化傳感器
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) // 使用默認 I2C 端口,400kHz 速度
  {
    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) ; //等到用戶按下一個鍵
  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);
}

void loop() {
  bufferLength = 100; // 100 的緩衝區長度存儲以 25sps 運行的 4 秒樣本

  //讀取前100個樣本,並確定信號範圍
  for (byte i = 0 ; i < bufferLength ; i++)
  {
    while (particleSensor.available() == false) //我們有新數據嗎?
      particleSensor.check(); //檢查傳感器是否有新數據

    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample(); //我們已經完成了這個樣本所以移動到下一個樣本

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

  //計算前 100 個樣本後的心率和 SpO2(前 4 秒樣本)
  maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

  //繼續從MAX30102採樣。每 1 秒計算一次心率和 SpO2
  while (1)
  {
    //轉儲內存中的前25組樣本並將後75組樣本移到頂部
    for (byte i = 25; i < 100; i++)
    {
      redBuffer[i - 25] = redBuffer[i];
      irBuffer[i - 25] = irBuffer[i];
    }

    //在計算心率之前取25組樣本
    for (byte i = 75; i < 100; i++)
    {
      while (particleSensor.available() == false) //我們有新數據嗎?
        particleSensor.check(); //檢查傳感器是否有新數據

      digitalWrite(readLED, !digitalRead(readLED)); //每次讀取數據時板載 LED 閃爍

      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample(); // 我們已經完成了這個樣本所以移動到下一個樣本

      //通過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);
    }

    //收集25個新樣本後重新計算HR和SP02
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  }
}

  實驗串口返回情況

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章