-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHeartRateSensor.cpp
More file actions
107 lines (81 loc) · 2.64 KB
/
Copy pathHeartRateSensor.cpp
File metadata and controls
107 lines (81 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "HeartRateSensor.h"
#include <Arduino.h>
#define BASELINE_SIZE 16
#define BPM_BUF_SIZE 4
#define SMOOTH_ALPHA 0.4f
#define BEAT_MIN_MS 333
#define BEAT_MAX_MS 1500
void HeartRateSensor::begin() {
if (!sensor.begin(Wire, I2C_SPEED_FAST)) {
Serial.println("MAX30102 not found!");
while (1);
}
sensor.setup(
60, // LED brightness
4, // sample average
2, // LED mode (red + IR)
400, // sample rate
411, // pulse width
4096 // ADC range
);
Serial.println("MAX30102 OK");
}
void HeartRateSensor::update() {
long irValue = sensor.getIR();
unsigned long now = millis();
// 手指偵測
if (irValue < 50000) {
finger = false;
wasAbove = false;
baselineSum = 0;
baselineIdx = 0;
baselineFull = false;
bpmIdx = 0;
bpmFilled = 0;
smooth = 0;
finalBpm = 0;
return;
}
finger = true;
// ── 動態基線(移動平均)──
baselineSum -= baseline[baselineIdx];
baseline[baselineIdx] = irValue;
baselineSum += irValue;
baselineIdx = (baselineIdx + 1) % BASELINE_SIZE;
if (!baselineFull && baselineIdx == 0) baselineFull = true;
int n = baselineFull ? BASELINE_SIZE : baselineIdx;
long irMean = baselineSum / n;
// 基線未穩定 → 不偵測
if (!baselineFull && baselineIdx < BASELINE_SIZE / 2) return;
// ── 過零點偵測(低 → 高)──
bool isAbove = (irValue > irMean);
if (isAbove && !wasAbove) {
if (lastCross > 0) {
unsigned long interval = now - lastCross;
if (interval >= BEAT_MIN_MS && interval <= BEAT_MAX_MS) {
int bpm = (int)(60000.0f / interval + 0.5f);
bpmBuf[bpmIdx++] = bpm;
bpmIdx %= BPM_BUF_SIZE;
if (bpmFilled < BPM_BUF_SIZE) bpmFilled++;
int sum = 0;
for (int i = 0; i < bpmFilled; i++) sum += bpmBuf[i];
int avg = sum / bpmFilled;
if (smooth == 0) smooth = bpm;
else smooth = SMOOTH_ALPHA * avg + (1.0f - SMOOTH_ALPHA) * smooth;
finalBpm = (int)(smooth + 0.5f);
beatFrame = !beatFrame;
Serial.print("Interval="); Serial.print(interval);
Serial.print("ms BPM="); Serial.print(bpm);
Serial.print(" Out="); Serial.println(finalBpm);
}
}
lastCross = now;
}
wasAbove = isAbove;
}
int HeartRateSensor::getBpm() {
return finalBpm;
}
bool HeartRateSensor::fingerDetected() {
return finger;
}