【雕爷学编程】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); } }
实验串口返回情况