【雕爷学编程】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);
  }
}

  实验串口返回情况

 

posted @ 2023-07-23 07:04  行者花雕  阅读(1306)  评论(1编辑  收藏  举报