M5Unit-HEART 0.1.0 git rev:05c3b01
Loading...
Searching...
No Matches
unit_MAX30102.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_HEART_UNIT_MAX30102_HPP
11#define M5_UNIT_HEART_UNIT_MAX30102_HPP
12
13#include <M5UnitComponent.hpp>
14#include <m5_utility/stl/extension.hpp>
15#include <m5_utility/container/circular_buffer.hpp>
16#include <limits> // NaN
17
18namespace m5 {
19namespace unit {
24namespace max30102 {
25
30enum class Mode : uint8_t {
31 None,
32 HROnly = 0x02,
33 SpO2,
34 MultiLED = 0x07,
35};
36
43enum class ADC : uint8_t {
48};
49
55enum class Sampling : uint8_t {
56 Rate50,
57 Rate100,
58 Rate200,
59 Rate400,
60 Rate800,
61 Rate1000,
62 Rate1600,
63 Rate3200,
64};
65
70enum class LEDPulse : uint8_t {
71 Width69,
72 Width118,
73 Width215,
74 Width411,
75};
76
81enum class Slot : uint8_t {
82 None,
83 Red,
84 IR,
85};
86
91enum class FIFOSampling : uint8_t {
92 Average1,
93 Average2,
94 Average4,
95 Average8,
96 Average16,
97 Average32,
98 // Average32, duplicated
99 // Average32, duplicated
100};
101
102constexpr uint8_t MAX_FIFO_DEPTH{32};
103
108struct Data {
109 std::array<uint8_t, 6> raw{}; // [0...2]:Red [3...5]:IR
110 uint32_t mask{0x3FFFF}; // Valid bits based on ADC range
112 inline uint32_t ir() const
113 {
114 return mask & (((uint32_t)raw[3] << 16) | ((uint32_t)raw[4] << 8) | ((uint32_t)raw[5]));
115 }
117 inline uint32_t red() const
118 {
119 return mask & (((uint32_t)raw[0] << 16) | ((uint32_t)raw[1] << 8) | ((uint32_t)raw[2]));
120 }
121};
122
128 std::array<uint8_t, 2> raw{0xFF, 0xFF}; // [0]:integer [1]:fraction
130 inline float temperature() const
131 {
132 return celsius();
133 }
135 inline float celsius() const
136 {
137 return (raw[0] != 0xFF) ? (int8_t)raw[0] + raw[1] * 0.0625f : std::numeric_limits<float>::quiet_NaN();
138 }
140 inline float fahrenheit() const
141 {
142 return celsius() * 9.0f / 5.0f + 32.f;
143 }
144};
145
147namespace command {
148// STATUS
149constexpr uint8_t READ_INTERRUPT_STATUS_1{0x00};
150constexpr uint8_t READ_INTERRUPT_STATUS_2{0x01};
151constexpr uint8_t INTERRUPT_ENABLE_1{0x02};
152constexpr uint8_t INTERRUPT_ENABLE_2{0x03};
153// FIFO
154constexpr uint8_t FIFO_WRITE_POINTER{0x04};
155constexpr uint8_t FIFO_OVERFLOW_COUNTER{0x05};
156constexpr uint8_t FIFO_READ_POINTER{0x06};
157constexpr uint8_t FIFO_DATA_REGISTER{0x07};
158// CONFIGURATION
159constexpr uint8_t FIFO_CONFIGURATION{0x08};
160constexpr uint8_t MODE_CONFIGURATION{0x09};
161constexpr uint8_t SPO2_CONFIGURATION{0x0A};
162constexpr uint8_t LED_CONFIGURATION_1{0x0C};
163constexpr uint8_t LED_CONFIGURATION_2{0x0D};
164// MultiLED
165constexpr uint8_t MULTI_LED_MODE_CONTROL_12{0x11};
166constexpr uint8_t MULTI_LED_MODE_CONTROL_34{0x12};
167// TEMPERATURE
168constexpr uint8_t TEMP_INTEGER{0x1F};
169constexpr uint8_t TEMP_FRACTION{0x20};
170constexpr uint8_t TEMP_CONFIGURATION{0x21};
171// PART ID
172constexpr uint8_t READ_REVISION_ID{0xFE};
173constexpr uint8_t READ_PART_ID{0xFF};
174
175} // namespace command
176
177struct SpO2Configuration;
179
180} // namespace max30102
181
187class UnitMAX30102 : public Component, public PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data> {
188 M5_UNIT_COMPONENT_HPP_BUILDER(UnitMAX30102, 0x57);
189
190public:
196 struct config_t {
202 max30102::Mode mode{max30102::Mode::SpO2};
204 bool start_periodic{true};
206 max30102::ADC adc_range{max30102::ADC::Range4096nA};
208 max30102::Sampling sampling_rate{max30102::Sampling::Rate400};
210 max30102::LEDPulse pulse_width{max30102::LEDPulse::Width411};
212 uint8_t ir_current{0x1F};
214 uint8_t red_current{0x1F};
216 max30102::FIFOSampling fifo_sampling_average{max30102::FIFOSampling::Average4};
217 };
218
219 explicit UnitMAX30102(const uint8_t addr = DEFAULT_ADDRESS)
220 : Component(addr), _data{new m5::container::CircularBuffer<max30102::Data>(max30102::MAX_FIFO_DEPTH)}
221 {
222 auto ccfg = component_config();
223 ccfg.clock = 400 * 1000U;
224 ccfg.stored_size = max30102::MAX_FIFO_DEPTH;
225 component_config(ccfg);
226 }
227 virtual ~UnitMAX30102()
228 {
229 }
230
231 virtual bool begin() override;
232 virtual void update(const bool force = false) override;
233
236
238 {
239 return _cfg;
240 }
242 inline void config(const config_t& cfg)
243 {
244 _cfg = cfg;
245 }
247
251 inline uint32_t ir() const
252 {
253 return !empty() ? oldest().ir() : 0;
254 }
256 inline uint32_t red() const
257 {
258 return !empty() ? oldest().red() : 0;
259 }
265 inline uint8_t retrived() const
266 {
267 return _retrived;
268 }
273 inline uint8_t overflow() const
274 {
275 return _overflow;
276 }
278
284 uint32_t caluculateSamplingRate();
285
288
293 {
294 return PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data>::startPeriodicMeasurement();
295 }
308 inline bool startPeriodicMeasurement(const max30102::Mode mode, const max30102::ADC range,
309 const max30102::Sampling rate, const max30102::LEDPulse width,
310 const max30102::FIFOSampling avg, const uint8_t ir_current,
311 const uint8_t red_current)
312 {
313 return PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data>::startPeriodicMeasurement(
314 mode, range, rate, width, avg, ir_current, red_current);
315 }
322 {
323 return PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data>::stopPeriodicMeasurement();
324 }
326
329
334 bool readMode(max30102::Mode& mode);
341 bool writeMode(const max30102::Mode mode);
347 bool readShutdownControl(bool& shdn);
354 bool writeShutdownControl(const bool shdn);
356
384
393 inline bool readSpO2ADCRange(max30102::ADC& range)
394 {
395 max30102::Sampling rate{};
396 max30102::LEDPulse width{};
397 return readSpO2Configuration(range, rate, width);
398 }
401 {
402 max30102::ADC range{};
403 max30102::LEDPulse width{};
404 return readSpO2Configuration(range, rate, width);
405 }
408 {
409 max30102::ADC range{};
410 max30102::Sampling rate{};
411 return readSpO2Configuration(range, rate, width);
412 }
421 bool writeSpO2Configuration(const max30102::ADC range, const max30102::Sampling rate,
422 const max30102::LEDPulse width);
424 bool writeSpO2ADCRange(const max30102::ADC range);
430
436
442 inline bool readLEDCurrent(uint8_t& raw, const uint8_t slot)
443 {
444 return read_led_current(slot, raw);
445 }
453 inline bool readLEDCurrent(float& mA, const uint8_t slot)
454 {
455 return read_led_current(slot, mA);
456 }
463 inline bool writeLEDCurrent(const uint8_t slot, const uint8_t raw)
464 {
465 return write_led_current(slot, raw);
466 }
474 template <typename T, typename std::enable_if<std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
475 inline bool writeLEDCurrent(const uint8_t slot, const T mA)
476 {
477 return write_led_current(slot, (float)mA);
478 }
480
485
500 bool writeMultiLEDModeControl(const max30102::Slot slot1, const max30102::Slot slot2);
502
505
515
518
525 bool readFIFOConfiguration(max30102::FIFOSampling& avg, bool& rollover, uint8_t& almostFull);
534 bool writeFIFOConfiguration(const max30102::FIFOSampling avg, const bool rollover, const uint8_t almostFull);
535
537 inline bool readFIFOReadPointer(uint8_t& rptr)
538 {
539 rptr = 0xFF;
540 return read_register8(max30102::command::FIFO_READ_POINTER, rptr);
541 }
543 inline bool writeFIFOReadPointer(const uint8_t rptr)
544 {
545 return writeRegister8(max30102::command::FIFO_READ_POINTER, rptr);
546 }
548 inline bool readFIFOWritePointer(uint8_t& wptr)
549 {
550 wptr = 0xFF;
551 return read_register8(max30102::command::FIFO_WRITE_POINTER, wptr);
552 }
554 inline bool writeFIFOWritePointer(const uint8_t wptr)
555 {
556 return writeRegister8(max30102::command::FIFO_WRITE_POINTER, wptr);
557 }
559 inline bool readFIFOOverflowCounter(uint8_t& cnt)
560 {
561 cnt = 0xFF;
562 return read_register8(max30102::command::FIFO_OVERFLOW_COUNTER, cnt);
563 }
565 inline bool writeFIFOOverflowCounter(const uint8_t cnt)
566 {
567 return writeRegister8(max30102::command::FIFO_OVERFLOW_COUNTER, cnt);
568 }
570 inline bool resetFIFO()
571 {
572 return reset_FIFO();
573 }
575
581 bool reset();
582
590 bool readRevisionID(uint8_t& rev);
591
592protected:
593 bool read_register(const uint8_t reg, uint8_t* buf, const size_t len);
594 bool read_register8(const uint8_t reg, uint8_t& v);
595
596 bool start_periodic_measurement();
597 bool start_periodic_measurement(const max30102::Mode mode, const max30102::ADC range, const max30102::Sampling rate,
598 const max30102::LEDPulse width, const max30102::FIFOSampling avg,
599 const uint8_t ir_current, const uint8_t red_current);
600 bool stop_periodic_measurement();
601
602 bool write_spo2_configuration(const max30102::SpO2Configuration& sc);
603
604 bool read_led_current(const uint8_t idx, uint8_t& raw);
605 bool read_led_current(const uint8_t idx, float& mA);
606 bool write_led_current(const uint8_t idx, const uint8_t raw);
607 bool write_led_current(const uint8_t idx, const float mA);
608
609 bool write_fifo_sampling_average(const max30102::FIFOSampling avg);
610
611 bool read_FIFO();
612 bool reset_FIFO(const bool circling_read_ptr = true);
613
614 bool read_measurement_temperature(max30102::TemperatureData& td);
615
616 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitMAX30102, max30102::Data);
617
618protected:
619 std::unique_ptr<m5::container::CircularBuffer<max30102::Data>> _data{};
620 max30102::Mode _mode{};
621 uint8_t _retrived{}, _overflow{};
622 uint32_t _mask{}; // Valid bits based on ADC range
623 max30102::Slot _slot[2]{};
624 config_t _cfg{};
625};
626
627} // namespace unit
628} // namespace m5
629#endif
Pulse oximetry and heart-rate sensor.
bool readMode(max30102::Mode &mode)
Read the operation mode.
Definition unit_MAX30102.cpp:323
bool writeFIFOReadPointer(const uint8_t rptr)
Write the FIFO read pointer.
Definition unit_MAX30102.hpp:543
bool writeMultiLEDModeControl(const max30102::Slot slot1, const max30102::Slot slot2)
Write the MultiLED Mode to Slot 1-2.
Definition unit_MAX30102.cpp:492
uint32_t red() const
Oldest Red.
Definition unit_MAX30102.hpp:256
bool resetFIFO()
Reset FIFO pointer and counter.
Definition unit_MAX30102.hpp:570
bool writeLEDCurrent(const uint8_t slot, const uint8_t raw)
Write the LED current.
Definition unit_MAX30102.hpp:463
bool writeSpO2LEDPulseWidth(const max30102::LEDPulse width)
Write the LED pulse width.
Definition unit_MAX30102.cpp:438
bool writeSpO2Configuration(const max30102::ADC range, const max30102::Sampling rate, const max30102::LEDPulse width)
Write the SpO2 configuration.
Definition unit_MAX30102.cpp:408
bool readFIFOOverflowCounter(uint8_t &cnt)
Read the FIFO overflow counter.
Definition unit_MAX30102.hpp:559
bool readSpO2SamplingRate(max30102::Sampling &rate)
Read the sampling rate.
Definition unit_MAX30102.hpp:400
bool stopPeriodicMeasurement()
Stop periodic measurement.
Definition unit_MAX30102.hpp:321
bool reset()
Reset.
Definition unit_MAX30102.cpp:693
bool writeFIFOWritePointer(const uint8_t wptr)
Write the FIFO write pointer.
Definition unit_MAX30102.hpp:554
uint32_t caluculateSamplingRate()
Calculate the sampling rate from the current settings.
Definition unit_MAX30102.cpp:719
bool writeFIFOOverflowCounter(const uint8_t cnt)
Write the FIFO overflow counter.
Definition unit_MAX30102.hpp:565
bool measureTemperatureSingleshot(max30102::TemperatureData &td)
Measure tempeature single shot.
Definition unit_MAX30102.cpp:524
bool readRevisionID(uint8_t &rev)
Read the revision ID.
Definition unit_MAX30102.cpp:713
bool writeMode(const max30102::Mode mode)
Write the operation mode.
Definition unit_MAX30102.cpp:334
bool startPeriodicMeasurement(const max30102::Mode mode, const max30102::ADC range, const max30102::Sampling rate, const max30102::LEDPulse width, const max30102::FIFOSampling avg, const uint8_t ir_current, const uint8_t red_current)
Start periodic measurement.
Definition unit_MAX30102.hpp:308
bool writeSpO2ADCRange(const max30102::ADC range)
Write the ADC range.
Definition unit_MAX30102.cpp:418
bool writeSpO2SamplingRate(const max30102::Sampling rate)
Write the sampling rate.
Definition unit_MAX30102.cpp:428
bool readShutdownControl(bool &shdn)
Read the shutdown control.
Definition unit_MAX30102.cpp:352
bool readLEDCurrent(uint8_t &raw, const uint8_t slot)
Read the LED current.
Definition unit_MAX30102.hpp:442
bool readFIFOConfiguration(max30102::FIFOSampling &avg, bool &rollover, uint8_t &almostFull)
Read the FIFO configuration.
Definition unit_MAX30102.cpp:547
bool readFIFOWritePointer(uint8_t &wptr)
Read the FIFO write pointer.
Definition unit_MAX30102.hpp:548
bool startPeriodicMeasurement()
Start periodic measurement in the current settings.
Definition unit_MAX30102.hpp:292
bool readMultiLEDModeControl(max30102::Slot &slot1, max30102::Slot &slot2)
Read the the MultiLED Mode form Slot 1-2.
Definition unit_MAX30102.cpp:480
config_t config()
Gets the configration.
Definition unit_MAX30102.hpp:237
bool readFIFOReadPointer(uint8_t &rptr)
Read the FIFO read pointer.
Definition unit_MAX30102.hpp:537
bool readSpO2ADCRange(max30102::ADC &range)
Read the ADC range.
Definition unit_MAX30102.hpp:393
uint32_t ir() const
Oldest IR.
Definition unit_MAX30102.hpp:251
uint8_t retrived() const
Number of data last retrieved.
Definition unit_MAX30102.hpp:265
bool readSpO2Configuration(max30102::ADC &range, max30102::Sampling &rate, max30102::LEDPulse &width)
Read the SpO2 configuration.
Definition unit_MAX30102.cpp:378
bool readLEDCurrent(float &mA, const uint8_t slot)
Read the LED current.
Definition unit_MAX30102.hpp:453
bool writeFIFOConfiguration(const max30102::FIFOSampling avg, const bool rollover, const uint8_t almostFull)
Write the FIFO configuration.
Definition unit_MAX30102.cpp:563
void config(const config_t &cfg)
Set the configration.
Definition unit_MAX30102.hpp:242
bool writeShutdownControl(const bool shdn)
Write the shutdown control.
Definition unit_MAX30102.cpp:363
uint8_t overflow() const
The number of samples lost.
Definition unit_MAX30102.hpp:273
bool readSpO2LEDPulseWidth(max30102::LEDPulse &width)
Read the LED pulse width.
Definition unit_MAX30102.hpp:407
bool writeLEDCurrent(const uint8_t slot, const T mA)
Write the LED current.
Definition unit_MAX30102.hpp:475
Top level namespace of M5stack.
For MAX30102.
Unit-related namespace.
Settings for begin.
Definition unit_MAX30102.hpp:196
max30102::LEDPulse pulse_width
LED pulse width if start on begin.
Definition unit_MAX30102.hpp:210
max30102::FIFOSampling fifo_sampling_average
FIFO sampling average if start on begin.
Definition unit_MAX30102.hpp:216
bool start_periodic
Start periodic measurement on begin?
Definition unit_MAX30102.hpp:204
max30102::ADC adc_range
ADC range if start on begin.
Definition unit_MAX30102.hpp:206
max30102::Mode mode
Operating mode if start on begin.
Definition unit_MAX30102.hpp:202
max30102::Sampling sampling_rate
Sampling rate if start on begin.
Definition unit_MAX30102.hpp:208
uint8_t ir_current
LED current for IR if start on begin.
Definition unit_MAX30102.hpp:212
uint8_t red_current
LED current for Red if start on begin (only SpO2 MODE)
Definition unit_MAX30102.hpp:214
Measurement data group.
Definition unit_MAX30102.hpp:108
uint32_t red() const
Red value.
Definition unit_MAX30102.hpp:117
uint32_t ir() const
IR value.
Definition unit_MAX30102.hpp:112
Measurement data group for temperature.
Definition unit_MAX30102.hpp:127
float fahrenheit() const
temperature (Fahrenheit)
Definition unit_MAX30102.hpp:140
float celsius() const
Temperature (Celsius)
Definition unit_MAX30102.hpp:135
float temperature() const
Temperature (Celsius)
Definition unit_MAX30102.hpp:130
Mode
Operation mode.
Definition unit_MAX30102.hpp:30
@ MultiLED
Multi-LED mode (Red and IR)
ADC
SpO2 ADC Range Control.
Definition unit_MAX30102.hpp:43
@ Range8192nA
LSB size 31.25 Full scale 8192.
@ Range4096nA
LSB size 15.63 Full scale 4096.
@ Range16384nA
LSB size 62.5 Full scale 16384.
@ Range2048nA
LSB size 7.81 Full scale 2048.
Sampling
Sampling rate for pulse/conversion.
Definition unit_MAX30102.hpp:55
Slot
Multi-LED mode control.
Definition unit_MAX30102.hpp:81
LEDPulse
LED pulse width (the IR and RED have the same pulse width)
Definition unit_MAX30102.hpp:70
@ Width69
68.95 us (ADC 15 bits)
@ Width411
410.75 us (ADC 18 bits)
@ Width118
117.78 us (ADC 16 bits)
@ Width215
215.44 us (ADC 17 bits)
FIFOSampling
Number of samples averaged per FIFO sample.
Definition unit_MAX30102.hpp:91