firmware/src/modules/Telemetry/Sensor/MAX30102Sensor.cpp
Jonathan Bennett 473ef1bc03
Step one of Linux Sensor support (#6673)
* First addition of __has_include for sensor support

* Add __has_include blocks for sensors

* Put BMP and BME back in the right sensors

* Make TelemetrySensor::setup() a pure virtual finction

* Split environmental_base to environmental_extra, to compile the working sensor libs for Native

* Remove hard-coded checks for ARCH_PORTDUINO

* Un-clobber bmx160

* Move BusIO to environmental_extra due to Armv7 compile error

* Move to forked BusIO for the moment

* Enable HAS_SENSOR for Portduino

* Move back to Adafruit BusIO after patch
2025-04-28 18:35:13 -05:00

83 lines
3.0 KiB
C++

#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY && __has_include(<MAX30105.h>)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "MAX30102Sensor.h"
#include "TelemetrySensor.h"
#include <spo2_algorithm.h>
MAX30102Sensor::MAX30102Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_MAX30102, "MAX30102") {}
int32_t MAX30102Sensor::runOnce()
{
LOG_INFO("Init sensor: %s", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
if (max30102.begin(*nodeTelemetrySensorsMap[sensorType].second, _speed, nodeTelemetrySensorsMap[sensorType].first) ==
true) // MAX30102 init
{
byte brightness = 60; // 0=Off to 255=50mA
byte sampleAverage = 4; // 1, 2, 4, 8, 16, 32
byte leds = 2; // 1 = Red only, 2 = Red + IR
byte sampleRate = 100; // 50, 100, 200, 400, 800, 1000, 1600, 3200
int pulseWidth = 411; // 69, 118, 215, 411
int adcRange = 4096; // 2048, 4096, 8192, 16384
max30102.enableDIETEMPRDY(); // Enable the temperature ready interrupt
max30102.setup(brightness, sampleAverage, leds, sampleRate, pulseWidth, adcRange);
LOG_DEBUG("MAX30102 Init Succeed");
status = true;
} else {
LOG_ERROR("MAX30102 Init Failed");
status = false;
}
return initI2CSensor();
}
void MAX30102Sensor::setup() {}
bool MAX30102Sensor::getMetrics(meshtastic_Telemetry *measurement)
{
uint32_t ir_buff[MAX30102_BUFFER_LEN];
uint32_t red_buff[MAX30102_BUFFER_LEN];
int32_t spo2;
int8_t spo2_valid;
int32_t heart_rate;
int8_t heart_rate_valid;
float temp = max30102.readTemperature();
measurement->variant.environment_metrics.temperature = temp;
measurement->variant.environment_metrics.has_temperature = true;
measurement->variant.health_metrics.temperature = temp;
measurement->variant.health_metrics.has_temperature = true;
for (byte i = 0; i < MAX30102_BUFFER_LEN; i++) {
while (max30102.available() == false)
max30102.check();
red_buff[i] = max30102.getRed();
ir_buff[i] = max30102.getIR();
max30102.nextSample();
}
maxim_heart_rate_and_oxygen_saturation(ir_buff, MAX30102_BUFFER_LEN, red_buff, &spo2, &spo2_valid, &heart_rate,
&heart_rate_valid);
LOG_DEBUG("heart_rate=%d(%d), sp02=%d(%d)", heart_rate, heart_rate_valid, spo2, spo2_valid);
if (heart_rate_valid) {
measurement->variant.health_metrics.has_heart_bpm = true;
measurement->variant.health_metrics.heart_bpm = heart_rate;
} else {
measurement->variant.health_metrics.has_heart_bpm = false;
}
if (spo2_valid) {
measurement->variant.health_metrics.has_spO2 = true;
measurement->variant.health_metrics.spO2 = spo2;
} else {
measurement->variant.health_metrics.has_spO2 = true;
}
return true;
}
#endif