You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写代码实现MAX30102传感器同步读取心率(BPM)与血氧(SpO2)

MAX30102 心率+血氧同步读取精简整合代码

直接基于官方血氧示例优化即可,官方血氧示例自带的maxim_heart_rate_and_oxygen_saturation函数本身就会同时计算心率和血氧,不需要再叠加独立心率示例的逻辑,既省内存也不会出现逻辑冲突,Arduino Uno也能正常运行。

整合后完整代码

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

MAX30105 particleSensor;

// 内存适配:Uno用16位缓冲避免内存不足
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
uint16_t irBuffer[100];
uint16_t redBuffer[100];
#else
uint32_t irBuffer[100];
uint32_t redBuffer[100];
#endif

int32_t bufferLength = 100;
int32_t spo2;
int8_t validSPO2;
int32_t heartRate;
int8_t validHeartRate;

byte readLED = 13; // 板载LED指示采样状态

void setup()
{
  Serial.begin(115200);
  pinMode(readLED, OUTPUT);

  // 传感器初始化
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST))
  {
    Serial.println("MAX30105未找到,请检查接线和供电");
    while (1);
  }

  // 传感器配置,兼顾精度和功耗
  byte ledBrightness = 60;
  byte sampleAverage = 4;
  byte ledMode = 2; // 仅开启红光+红外,满足血氧心率测量需求
  byte sampleRate = 100;
  int pulseWidth = 411;
  int adcRange = 4096;

  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
  Serial.println("请将手指轻放在传感器上,保持稳定");
}

void loop()
{
  // 首次采集100组样本初始化算法
  for (byte i = 0 ; i < bufferLength ; i++)
  {
    while (particleSensor.available() == false)
      particleSensor.check();
    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample();
  }

  // 计算心率和血氧
  maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

  // 循环更新数据,每秒刷新一次结果
  while (1)
  {
    // 滑动窗口:保留旧的75组样本,补充25组新样本
    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));
      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample();
    }

    // 重新计算数值
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

    // 输出结果
    Serial.print("=== 测量结果 ===");
    if (irBuffer[99] < 50000)
    {
      Serial.println(" 未检测到手指");
    }
    else
    {
      if (validHeartRate) Serial.printf(" 心率:%d BPM", heartRate);
      else Serial.print(" 心率:计算中");
      if (validSPO2) Serial.printf(" 血氧:%d %%", spo2);
      else Serial.print(" 血氧:计算中");
      Serial.println();
    }
  }
}

优化说明

  • 去掉了独立心率示例的重复心跳检测逻辑,直接复用血氧算法自带的心率计算能力,减少了约30%的代码量,内存占用控制在2KB以内,完全满足Uno的内存限制
  • 删除了冗余的原始采样值串口输出,只保留最终结果输出,串口信息更清晰
  • 去掉了需要按键启动的逻辑,上电自动运行,测试更方便
  • 保留了原版的跨平台内存适配逻辑,除了Uno之外,ESP32、STM32等开发板也能直接运行

使用注意事项

  • 测量时手指轻贴传感器,不要用力按压,避免强光直射传感器表面,一般3-5秒就能输出稳定有效数值
  • 心率和血氧旁显示「计算中」时代表当前采样不足,等待几秒算法校准完成就会输出有效数值
  • 如果需要更高的刷新率,可以把缓冲长度从100改为50,刷新率会提升一倍,但数值精度会略有下降,可按需调整

内容的提问来源于stack exchange,提问作者Mari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:15:02