Skip to content

Commit 330d5e6

Browse files
committed
Heartrate measurements in background InfiniTimeOrg#1718
commit d271670 Author: Patric Gruber <me@patric-gruber.at> Date: Thu May 11 23:49:39 2023 +0200 remove version change in CMakeLists.txt commit faec69e Author: Patric Gruber <me@patric-gruber.at> Date: Thu May 11 23:47:31 2023 +0200 rebase on main commit c5d2e42 Author: Patric Gruber <me@patric-gruber.at> Date: Mon Apr 3 21:29:17 2023 +0200 remove background start timestamp reset on sleep commit 7180646 Author: Patric Gruber <me@patric-gruber.at> Date: Fri Mar 31 12:38:37 2023 +0200 remove version change in CMakeLists.txt commit 9186cd2 Author: Patric Gruber <me@patric-gruber.at> Date: Fri Mar 31 10:25:36 2023 +0200 increase task delay when waiting in the background to 10s commit a3a30a2 Author: Patric Gruber <me@patric-gruber.at> Date: Fri Mar 31 10:00:56 2023 +0200 add heart rate measurments in the background
1 parent e9b2c48 commit 330d5e6

File tree

2 files changed

+86
-49
lines changed

2 files changed

+86
-49
lines changed

src/heartratetask/HeartRateTask.cpp

+78-47
Original file line numberDiff line numberDiff line change
@@ -25,77 +25,57 @@ void HeartRateTask::Process(void* instance) {
2525

2626
void HeartRateTask::Work() {
2727
int lastBpm = 0;
28+
2829
while (true) {
30+
auto delay = CurrentTaskDelay();
2931
Messages msg;
30-
uint32_t delay;
31-
if (state == States::Running) {
32-
if (measurementStarted) {
33-
delay = ppg.deltaTms;
34-
} else {
35-
delay = 100;
36-
}
37-
} else {
38-
delay = portMAX_DELAY;
39-
}
4032

41-
if (xQueueReceive(messageQueue, &msg, delay)) {
33+
if (xQueueReceive(messageQueue, &msg, delay) == pdTRUE) {
4234
switch (msg) {
4335
case Messages::GoToSleep:
44-
StopMeasurement();
45-
state = States::Idle;
36+
if (state == States::Running) {
37+
state = States::Idle;
38+
} else if (state == States::Measuring) {
39+
state = States::BackgroundWaiting;
40+
StopMeasurement();
41+
}
4642
break;
4743
case Messages::WakeUp:
48-
state = States::Running;
49-
if (measurementStarted) {
50-
lastBpm = 0;
44+
if (state == States::Idle) {
45+
state = States::Running;
46+
} else if (state == States::BackgroundMeasuring) {
47+
state = States::Measuring;
48+
} else if (state == States::BackgroundWaiting) {
49+
state = States::Measuring;
5150
StartMeasurement();
5251
}
5352
break;
5453
case Messages::StartMeasurement:
55-
if (measurementStarted) {
54+
if (state == States::Measuring || state == States::BackgroundMeasuring) {
5655
break;
5756
}
57+
state = States::Measuring;
5858
lastBpm = 0;
5959
StartMeasurement();
60-
measurementStarted = true;
6160
break;
6261
case Messages::StopMeasurement:
63-
if (!measurementStarted) {
62+
if (state == States::Running || state == States::Idle) {
6463
break;
6564
}
65+
if (state == States::Measuring) {
66+
state = States::Running;
67+
} else if (state == States::BackgroundMeasuring) {
68+
state = States::Idle;
69+
}
6670
StopMeasurement();
67-
measurementStarted = false;
6871
break;
6972
}
7073
}
7174

72-
if (measurementStarted) {
73-
int8_t ambient = ppg.Preprocess(heartRateSensor.ReadHrs(), heartRateSensor.ReadAls());
74-
int bpm = ppg.HeartRate();
75-
76-
// If ambient light detected or a reset requested (bpm < 0)
77-
if (ambient > 0) {
78-
// Reset all DAQ buffers
79-
ppg.Reset(true);
80-
// Force state to NotEnoughData (below)
81-
lastBpm = 0;
82-
bpm = 0;
83-
} else if (bpm < 0) {
84-
// Reset all DAQ buffers except HRS buffer
85-
ppg.Reset(false);
86-
// Set HR to zero and update
87-
bpm = 0;
88-
controller.Update(Controllers::HeartRateController::States::Running, bpm);
89-
}
90-
91-
if (lastBpm == 0 && bpm == 0) {
92-
controller.Update(Controllers::HeartRateController::States::NotEnoughData, bpm);
93-
}
94-
95-
if (bpm != 0) {
96-
lastBpm = bpm;
97-
controller.Update(Controllers::HeartRateController::States::Running, lastBpm);
98-
}
75+
if (state == States::BackgroundWaiting) {
76+
HandleBackgroundWaiting();
77+
} else if (state == States::BackgroundMeasuring || state == States::Measuring) {
78+
HandleSensorData(&lastBpm);
9979
}
10080
}
10181
}
@@ -120,3 +100,54 @@ void HeartRateTask::StopMeasurement() {
120100
ppg.Reset(true);
121101
vTaskDelay(100);
122102
}
103+
104+
void HeartRateTask::HandleBackgroundWaiting() {
105+
if (xTaskGetTickCount() - backgroundMeasurementWaitingStart >= DURATION_BETWEEN_BACKGROUND_MEASUREMENTS) {
106+
state = States::BackgroundMeasuring;
107+
StartMeasurement();
108+
}
109+
}
110+
111+
void HeartRateTask::HandleSensorData(int* lastBpm) {
112+
int8_t ambient = ppg.Preprocess(heartRateSensor.ReadHrs(), heartRateSensor.ReadAls());
113+
int bpm = ppg.HeartRate();
114+
115+
// If ambient light detected or a reset requested (bpm < 0)
116+
if (ambient > 0) {
117+
// Reset all DAQ buffers
118+
ppg.Reset(true);
119+
} else if (bpm < 0) {
120+
// Reset all DAQ buffers except HRS buffer
121+
ppg.Reset(false);
122+
// Set HR to zero and update
123+
bpm = 0;
124+
}
125+
126+
if (*lastBpm == 0 && bpm == 0) {
127+
controller.Update(Controllers::HeartRateController::States::NotEnoughData, bpm);
128+
}
129+
130+
if (bpm != 0) {
131+
*lastBpm = bpm;
132+
controller.Update(Controllers::HeartRateController::States::Running, bpm);
133+
if (state == States::BackgroundMeasuring) {
134+
StopMeasurement();
135+
state = States::BackgroundWaiting;
136+
backgroundMeasurementWaitingStart = xTaskGetTickCount();
137+
}
138+
}
139+
}
140+
141+
int HeartRateTask::CurrentTaskDelay() {
142+
switch (state) {
143+
case States::Measuring:
144+
case States::BackgroundMeasuring:
145+
return ppg.deltaTms;
146+
case States::Running:
147+
return 100;
148+
case States::BackgroundWaiting:
149+
return 10000;
150+
default:
151+
return portMAX_DELAY;
152+
}
153+
}

src/heartratetask/HeartRateTask.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <queue.h>
55
#include <components/heartrate/Ppg.h>
66

7+
#define DURATION_BETWEEN_BACKGROUND_MEASUREMENTS 5 * 60 * 1000 // 5 Minutes assuming 1 Hz
8+
79
namespace Pinetime {
810
namespace Drivers {
911
class Hrs3300;
@@ -17,7 +19,7 @@ namespace Pinetime {
1719
class HeartRateTask {
1820
public:
1921
enum class Messages : uint8_t { GoToSleep, WakeUp, StartMeasurement, StopMeasurement };
20-
enum class States { Idle, Running };
22+
enum class States { Idle, Running, Measuring, BackgroundWaiting, BackgroundMeasuring };
2123

2224
explicit HeartRateTask(Drivers::Hrs3300& heartRateSensor, Controllers::HeartRateController& controller);
2325
void Start();
@@ -29,13 +31,17 @@ namespace Pinetime {
2931
void StartMeasurement();
3032
void StopMeasurement();
3133

34+
void HandleBackgroundWaiting();
35+
void HandleSensorData(int* lastBpm);
36+
int CurrentTaskDelay();
37+
3238
TaskHandle_t taskHandle;
3339
QueueHandle_t messageQueue;
3440
States state = States::Running;
3541
Drivers::Hrs3300& heartRateSensor;
3642
Controllers::HeartRateController& controller;
3743
Controllers::Ppg ppg;
38-
bool measurementStarted = false;
44+
TickType_t backgroundMeasurementWaitingStart = 0;
3945
};
4046

4147
}

0 commit comments

Comments
 (0)