Merge pull request #3588 from mjearlb/master

Update 0.02
master
thyttan 2024-10-14 17:51:59 +02:00 committed by GitHub
commit 13d982881b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 48 deletions

View File

@ -1 +1,4 @@
0.01: New App. 0.01: New App.
0.02:
- Removed HRV functionality
- Added milliseconds to the timestamps

View File

@ -2,7 +2,6 @@ let isMeasuring = false;
let currentHR = null; let currentHR = null;
let lcdTimeout; let lcdTimeout;
let logData = []; let logData = [];
let bpmValues = [];
function startMeasure() { function startMeasure() {
logData = []; logData = [];
@ -14,11 +13,11 @@ function startMeasure() {
setTimeout(() => { setTimeout(() => {
Bangle.setHRMPower(1); // starts HRM Bangle.setHRMPower(1); // starts HRM
Bangle.on('HRM', handleHeartRate); Bangle.on('HRM', handleHeartRate); // Use function handleHeartRate
Bangle.buzz(200, 10); // Buzz to indicate measurement start Bangle.buzz(200, 10); // Buzz to indicate measurement start
drawScreen(); drawScreen();
}, 500); }, 500);
} } // startMeasure
function stopMeasure() { function stopMeasure() {
isMeasuring = false; isMeasuring = false;
@ -29,50 +28,26 @@ function stopMeasure() {
saveDataToCSV(); // Save data to CSV when measurement stops saveDataToCSV(); // Save data to CSV when measurement stops
Bangle.buzz(200, 10); // Buzz to indicate measurement stop Bangle.buzz(200, 10); // Buzz to indicate measurement stop
drawScreen(); drawScreen();
} } //stopMeasure
function handleHeartRate(hrm) { function handleHeartRate(hrm) {
if (isMeasuring && hrm.confidence > 90) { if (isMeasuring && hrm.confidence > 90) {
// Build the timestamp
let date = new Date(); let date = new Date();
let dateStr = require("locale").date(date); let dateStr = require("locale").date(date);
let timeStr = require("locale").time(date, 1); let timeStr = require("locale").time(date, 1);
let seconds = date.getSeconds(); let seconds = date.getSeconds();
let timestamp = `${dateStr} ${timeStr}:${seconds}`; // Concatenate date, time, and seconds let milliseconds = date.getMilliseconds();
// Concatenate date, time, seconds, & milliseconds
let timestamp = `${dateStr} ${timeStr}:${seconds}.${milliseconds}`;
currentHR = hrm.bpm; currentHR = hrm.bpm;
logData.push({ timestamp: timestamp, heartRate: currentHR }); logData.push({ timestamp: timestamp, heartRate: currentHR });
bpmValues.push(currentHR); // Store heart rate for HRV calculation
if (bpmValues.length > 30) bpmValues.shift(); // Keep last 30 heart rate values
// Calculate and add SDNN (standard deviation of NN intervals) to the last log entry
logData[logData.length - 1].hrv = calcSDNN();
drawScreen(); drawScreen();
} // if
} } // handleHeartRate
}
function calcSDNN() {
if (bpmValues.length < 5) return 0; // No calculation if insufficient data
// Calculate differences between adjacent heart rate values
const differences = [];
for (let i = 1; i < bpmValues.length; i++) {
differences.push(Math.abs(bpmValues[i] - bpmValues[i - 1]));
}
// Calculate mean difference
const meanDifference = differences.reduce((acc, val) => acc + val, 0) / differences.length;
// Calculate squared differences from mean difference
const squaredDifferences = differences.map(diff => Math.pow(diff - meanDifference, 2));
// Calculate mean squared difference
const meanSquaredDifference = squaredDifferences.reduce((acc, val) => acc + val, 0) / squaredDifferences.length;
// Calculate SDNN (standard deviation of NN intervals)
const sdnn = Math.sqrt(meanSquaredDifference);
return sdnn;
}
function drawScreen(message) { function drawScreen(message) {
g.clear(); // Clear the display g.clear(); // Clear the display
@ -121,12 +96,12 @@ function drawScreen(message) {
g.drawString('No data', g.getWidth() / 2, g.getHeight() / 2 + 5); g.drawString('No data', g.getWidth() / 2, g.getHeight() / 2 + 5);
g.setFont('6x8', 1); g.setFont('6x8', 1);
g.drawString(message || 'Press button to start', g.getWidth() / 2, g.getHeight() / 2 + 30); g.drawString(message || 'Press button to start', g.getWidth() / 2, g.getHeight() / 2 + 30);
} } // if
} } // if
// Update the display // Update the display
g.flip(); g.flip();
} } // drawScreen
function saveDataToCSV() { function saveDataToCSV() {
let fileName = "phystrax_hrm.csv"; let fileName = "phystrax_hrm.csv";
@ -135,13 +110,12 @@ function saveDataToCSV() {
// Check if the file is empty (i.e., newly created) // Check if the file is empty (i.e., newly created)
if (file.getLength() === 0) { if (file.getLength() === 0) {
// Write the header if the file is empty // Write the header if the file is empty
file.write("Timestamp,Heart Rate(bpm),HRV(ms)\n"); file.write("Timestamp,Heart Rate(bpm)\n");
} } // if
// Append the data // Append the data
logData.forEach(entry => { logData.forEach(entry => {
let scaledHRV = entry.hrv * 13.61; file.write(`${entry.timestamp},${entry.heartRate}\n`);
file.write(`${entry.timestamp},${entry.heartRate},${scaledHRV}\n`);
}); });
} }
@ -151,7 +125,7 @@ setWatch(function() {
startMeasure(); startMeasure();
} else { } else {
stopMeasure(); stopMeasure();
} } // if
}, BTN1, { repeat: true, edge: 'rising' }); }, BTN1, { repeat: true, edge: 'rising' }); // setWatch
drawScreen(); drawScreen();

View File

@ -2,7 +2,7 @@
"name": "PhysTrax", "name": "PhysTrax",
"shortName":"PhysTrax", "shortName":"PhysTrax",
"icon": "app.png", "icon": "app.png",
"version":"0.01", "version":"0.02",
"description": "Tracking physiological measurements to support active learning in classrooms", "description": "Tracking physiological measurements to support active learning in classrooms",
"tags": "health", "tags": "health",
"interface": "interface.html", "interface": "interface.html",