Skip to content

Commit a3a30a2

Browse files
committed
add heart rate measurments in the background
1 parent 020a7fd commit a3a30a2

3 files changed

Lines changed: 94 additions & 51 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
22

33
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
44

5-
project(pinetime VERSION 1.12.0 LANGUAGES C CXX ASM)
5+
project(pinetime VERSION 1.11.1 LANGUAGES C CXX ASM)
66

77
set(CMAKE_C_STANDARD 99)
88
set(CMAKE_CXX_STANDARD 14)

src/heartratetask/HeartRateTask.cpp

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -24,78 +24,59 @@ void HeartRateTask::Process(void* instance) {
2424
}
2525

2626
void HeartRateTask::Work() {
27-
int lastBpm = 0;
27+
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+
backgroundMeasurementWaitingStart = xTaskGetTickCount();
41+
StopMeasurement();
42+
}
4643
break;
4744
case Messages::WakeUp:
48-
state = States::Running;
49-
if (measurementStarted) {
50-
lastBpm = 0;
45+
if (state == States::Idle) {
46+
state = States::Running;
47+
} else if (state == States::BackgroundMeasuring) {
48+
state = States::Measuring;
49+
} else if (state == States::BackgroundWaiting) {
50+
state = States::Measuring;
5151
StartMeasurement();
5252
}
5353
break;
5454
case Messages::StartMeasurement:
55-
if (measurementStarted) {
55+
if (state == States::Measuring || state == States::BackgroundMeasuring) {
5656
break;
5757
}
58+
state = States::Measuring;
5859
lastBpm = 0;
5960
StartMeasurement();
60-
measurementStarted = true;
6161
break;
6262
case Messages::StopMeasurement:
63-
if (!measurementStarted) {
63+
if (state == States::Running || state == States::Idle) {
6464
break;
6565
}
66+
if (state == States::Measuring) {
67+
state = States::Running;
68+
} else if (state == States::BackgroundMeasuring) {
69+
state = States::Idle;
70+
}
6671
StopMeasurement();
67-
measurementStarted = false;
6872
break;
6973
}
7074
}
7175

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-
}
76+
if (state == States::BackgroundWaiting) {
77+
HandleBackgroundWaiting();
78+
} else if (state == States::BackgroundMeasuring || state == States::Measuring) {
79+
HandleSensorData();
9980
}
10081
}
10182
}
@@ -120,3 +101,58 @@ void HeartRateTask::StopMeasurement() {
120101
ppg.Reset(true);
121102
vTaskDelay(100);
122103
}
104+
105+
void HeartRateTask::HandleBackgroundWaiting() {
106+
if (xTaskGetTickCount() - backgroundMeasurementWaitingStart >= DURATION_BETWEEN_BACKGROUND_MEASUREMENTS) {
107+
state = States::BackgroundMeasuring;
108+
StartMeasurement();
109+
}
110+
}
111+
112+
void HeartRateTask::HandleSensorData() {
113+
int8_t ambient = ppg.Preprocess(heartRateSensor.ReadHrs(), heartRateSensor.ReadAls());
114+
int bpm = ppg.HeartRate();
115+
116+
// If ambient light detected or a reset requested (bpm < 0)
117+
if (ambient > 0) {
118+
// Reset all DAQ buffers
119+
ppg.Reset(true);
120+
// Force state to NotEnoughData (below)
121+
lastBpm = 0;
122+
bpm = 0;
123+
} else if (bpm < 0) {
124+
// Reset all DAQ buffers except HRS buffer
125+
ppg.Reset(false);
126+
// Set HR to zero and update
127+
bpm = 0;
128+
controller.Update(Controllers::HeartRateController::States::Running, bpm);
129+
}
130+
131+
if (lastBpm == 0 && bpm == 0) {
132+
controller.Update(Controllers::HeartRateController::States::NotEnoughData, bpm);
133+
}
134+
135+
if (bpm != 0) {
136+
lastBpm = bpm;
137+
controller.Update(Controllers::HeartRateController::States::Running, lastBpm);
138+
if (state == States::BackgroundMeasuring) {
139+
StopMeasurement();
140+
state = States::BackgroundWaiting;
141+
backgroundMeasurementWaitingStart = xTaskGetTickCount();
142+
}
143+
}
144+
}
145+
146+
int HeartRateTask::CurrentTaskDelay() {
147+
switch (state) {
148+
case States::Measuring:
149+
case States::BackgroundMeasuring:
150+
return ppg.deltaTms;
151+
case States::Running:
152+
return 100;
153+
case States::BackgroundWaiting:
154+
return 500;
155+
default:
156+
return portMAX_DELAY;
157+
}
158+
}

src/heartratetask/HeartRateTask.h

Lines changed: 9 additions & 2 deletions
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,18 @@ namespace Pinetime {
2931
void StartMeasurement();
3032
void StopMeasurement();
3133

34+
void HandleBackgroundWaiting();
35+
void HandleSensorData();
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+
int lastBpm = 0;
45+
TickType_t backgroundMeasurementWaitingStart;
3946
};
4047

4148
}

0 commit comments

Comments
 (0)