M5Unit-HEART 0.2.1 git rev:e0975a4
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{};
110 uint32_t mask{0x3FFFF};
112 inline uint32_t ir() const
113 {
114 return mask & ((static_cast<uint32_t>(raw[3]) << 16) | (static_cast<uint32_t>(raw[4]) << 8) |
115 static_cast<uint32_t>(raw[5]));
116 }
118 inline uint32_t red() const
119 {
120 return mask & ((static_cast<uint32_t>(raw[0]) << 16) | (static_cast<uint32_t>(raw[1]) << 8) |
121 static_cast<uint32_t>(raw[2]));
122 }
123};
124
130 std::array<uint8_t, 2> raw{0x80, 0x00}; // [0]:integer [1]:fraction sentinel:0x80(-128) is outside operating range
132 inline float temperature() const
133 {
134 return celsius();
135 }
137 inline float celsius() const
138 {
139 return (raw[0] != 0x80) ? static_cast<int8_t>(raw[0]) + raw[1] * 0.0625f
140 : std::numeric_limits<float>::quiet_NaN();
141 }
143 inline float fahrenheit() const
144 {
145 return celsius() * 9.0f / 5.0f + 32.f;
146 }
147};
148
150namespace command {
151// STATUS
152constexpr uint8_t READ_INTERRUPT_STATUS_1{0x00};
153constexpr uint8_t READ_INTERRUPT_STATUS_2{0x01};
154constexpr uint8_t INTERRUPT_ENABLE_1{0x02};
155constexpr uint8_t INTERRUPT_ENABLE_2{0x03};
156// FIFO
157constexpr uint8_t FIFO_WRITE_POINTER{0x04};
158constexpr uint8_t FIFO_OVERFLOW_COUNTER{0x05};
159constexpr uint8_t FIFO_READ_POINTER{0x06};
160constexpr uint8_t FIFO_DATA_REGISTER{0x07};
161// CONFIGURATION
162constexpr uint8_t FIFO_CONFIGURATION{0x08};
163constexpr uint8_t MODE_CONFIGURATION{0x09};
164constexpr uint8_t SPO2_CONFIGURATION{0x0A};
165constexpr uint8_t LED_CONFIGURATION_1{0x0C};
166constexpr uint8_t LED_CONFIGURATION_2{0x0D};
167// MultiLED
168constexpr uint8_t MULTI_LED_MODE_CONTROL_12{0x11};
169constexpr uint8_t MULTI_LED_MODE_CONTROL_34{0x12};
170// TEMPERATURE
171constexpr uint8_t TEMP_INTEGER{0x1F};
172constexpr uint8_t TEMP_FRACTION{0x20};
173constexpr uint8_t TEMP_CONFIGURATION{0x21};
174// PART ID
175constexpr uint8_t READ_REVISION_ID{0xFE};
176constexpr uint8_t READ_PART_ID{0xFF};
177
178} // namespace command
179
180struct SpO2Configuration;
182
183} // namespace max30102
184
190class UnitMAX30102 : public Component, public PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data> {
191 M5_UNIT_COMPONENT_HPP_BUILDER(UnitMAX30102, 0x57);
192
193public:
199 struct config_t {
205 max30102::Mode mode{max30102::Mode::SpO2};
207 bool start_periodic{true};
209 max30102::ADC adc_range{max30102::ADC::Range4096nA};
211 max30102::Sampling sampling_rate{max30102::Sampling::Rate400};
213 max30102::LEDPulse pulse_width{max30102::LEDPulse::Width411};
215 uint8_t ir_current{0x1F};
217 uint8_t red_current{0x1F};
219 max30102::FIFOSampling fifo_sampling_average{max30102::FIFOSampling::Average4};
220 };
221
224 explicit UnitMAX30102(const uint8_t addr = DEFAULT_ADDRESS)
225 : Component(addr), _data{new m5::container::CircularBuffer<max30102::Data>(max30102::MAX_FIFO_DEPTH)}
226 {
227 auto ccfg = component_config();
228 ccfg.clock = 400 * 1000U;
229 ccfg.stored_size = max30102::MAX_FIFO_DEPTH;
230 component_config(ccfg);
231 }
232 virtual ~UnitMAX30102()
233 {
234 }
235
237 virtual bool begin() override;
239 virtual void update(const bool force = false) override;
240
243
245 {
246 return _cfg;
247 }
249 inline void config(const config_t& cfg)
250 {
251 _cfg = cfg;
252 }
254
258 inline uint32_t ir() const
259 {
260 return !empty() ? oldest().ir() : 0;
261 }
263 inline uint32_t red() const
264 {
265 return !empty() ? oldest().red() : 0;
266 }
272 inline uint8_t retrieved() const
273 {
274 return _retrieved;
275 }
280 [[deprecated("Please use retrieved()")]] inline uint8_t retrived() const
281 {
282 return retrieved();
283 }
288 inline uint8_t overflow() const
289 {
290 return _overflow;
291 }
293
299 uint32_t calculateSamplingRate();
304 [[deprecated("Please use calculateSamplingRate()")]] inline uint32_t caluculateSamplingRate()
305 {
306 return calculateSamplingRate();
307 }
308
311
316 {
317 return PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data>::startPeriodicMeasurement();
318 }
331 inline bool startPeriodicMeasurement(const max30102::Mode mode, const max30102::ADC range,
332 const max30102::Sampling rate, const max30102::LEDPulse width,
333 const max30102::FIFOSampling avg, const uint8_t ir_current,
334 const uint8_t red_current)
335 {
336 return PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data>::startPeriodicMeasurement(
337 mode, range, rate, width, avg, ir_current, red_current);
338 }
345 {
346 return PeriodicMeasurementAdapter<UnitMAX30102, max30102::Data>::stopPeriodicMeasurement();
347 }
349
352
357 bool readMode(max30102::Mode& mode);
364 bool writeMode(const max30102::Mode mode);
370 bool readShutdownControl(bool& shdn);
377 bool writeShutdownControl(const bool shdn);
379
407
416 inline bool readSpO2ADCRange(max30102::ADC& range)
417 {
418 max30102::Sampling rate{};
419 max30102::LEDPulse width{};
420 return readSpO2Configuration(range, rate, width);
421 }
424 {
425 max30102::ADC range{};
426 max30102::LEDPulse width{};
427 return readSpO2Configuration(range, rate, width);
428 }
431 {
432 max30102::ADC range{};
433 max30102::Sampling rate{};
434 return readSpO2Configuration(range, rate, width);
435 }
444 bool writeSpO2Configuration(const max30102::ADC range, const max30102::Sampling rate,
445 const max30102::LEDPulse width);
447 bool writeSpO2ADCRange(const max30102::ADC range);
453
459
465 inline bool readLEDCurrent(uint8_t& raw, const uint8_t slot)
466 {
467 return read_led_current(slot, raw);
468 }
476 inline bool readLEDCurrent(float& mA, const uint8_t slot)
477 {
478 return read_led_current(slot, mA);
479 }
486 inline bool writeLEDCurrent(const uint8_t slot, const uint8_t raw)
487 {
488 return write_led_current(slot, raw);
489 }
497 template <typename T, typename std::enable_if<std::is_floating_point<T>::value, std::nullptr_t>::type = nullptr>
498 inline bool writeLEDCurrent(const uint8_t slot, const T mA)
499 {
500 return write_led_current(slot, static_cast<float>(mA));
501 }
503
508
523 bool writeMultiLEDModeControl(const max30102::Slot slot1, const max30102::Slot slot2);
525
528
538
541
548 bool readFIFOConfiguration(max30102::FIFOSampling& avg, bool& rollover, uint8_t& almostFull);
557 bool writeFIFOConfiguration(const max30102::FIFOSampling avg, const bool rollover, const uint8_t almostFull);
558
560 inline bool readFIFOReadPointer(uint8_t& rptr)
561 {
562 rptr = 0xFF;
563 return read_register8(max30102::command::FIFO_READ_POINTER, rptr);
564 }
566 inline bool writeFIFOReadPointer(const uint8_t rptr)
567 {
568 return writeRegister8(max30102::command::FIFO_READ_POINTER, rptr);
569 }
571 inline bool readFIFOWritePointer(uint8_t& wptr)
572 {
573 wptr = 0xFF;
574 return read_register8(max30102::command::FIFO_WRITE_POINTER, wptr);
575 }
577 inline bool writeFIFOWritePointer(const uint8_t wptr)
578 {
579 return writeRegister8(max30102::command::FIFO_WRITE_POINTER, wptr);
580 }
582 inline bool readFIFOOverflowCounter(uint8_t& cnt)
583 {
584 cnt = 0xFF;
585 return read_register8(max30102::command::FIFO_OVERFLOW_COUNTER, cnt);
586 }
588 inline bool writeFIFOOverflowCounter(const uint8_t cnt)
589 {
590 return writeRegister8(max30102::command::FIFO_OVERFLOW_COUNTER, cnt);
591 }
593 inline bool resetFIFO()
594 {
595 return reset_FIFO();
596 }
598
604 bool reset();
605
613 bool readRevisionID(uint8_t& rev);
614
615protected:
616 bool read_register(const uint8_t reg, uint8_t* buf, const size_t len);
617 bool read_register8(const uint8_t reg, uint8_t& v);
618
619 bool start_periodic_measurement();
620 bool start_periodic_measurement(const max30102::Mode mode, const max30102::ADC range, const max30102::Sampling rate,
621 const max30102::LEDPulse width, const max30102::FIFOSampling avg,
622 const uint8_t ir_current, const uint8_t red_current);
623 bool stop_periodic_measurement();
624
625 bool write_spo2_configuration(const max30102::SpO2Configuration& sc);
626
627 bool read_led_current(const uint8_t idx, uint8_t& raw);
628 bool read_led_current(const uint8_t idx, float& mA);
629 bool write_led_current(const uint8_t idx, const uint8_t raw);
630 bool write_led_current(const uint8_t idx, const float mA);
631
632 bool write_fifo_sampling_average(const max30102::FIFOSampling avg);
633
634 bool read_FIFO();
635 bool reset_FIFO(const bool circling_read_ptr = true);
636
637 bool read_measurement_temperature(max30102::TemperatureData& td);
638
639 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitMAX30102, max30102::Data);
640
641protected:
642 std::unique_ptr<m5::container::CircularBuffer<max30102::Data>> _data{};
643 max30102::Mode _mode{};
644 uint8_t _retrieved{}, _overflow{};
645 uint32_t _mask{}; // Valid bits based on ADC range
646 max30102::Slot _slot[2]{};
647 config_t _cfg{};
648};
649
650} // namespace unit
651} // namespace m5
652#endif
Pulse oximetry and heart-rate sensor.
bool readMode(max30102::Mode &mode)
Read the operation mode.
Definition unit_MAX30102.cpp:325
bool writeFIFOReadPointer(const uint8_t rptr)
Write the FIFO read pointer.
Definition unit_MAX30102.hpp:566
bool writeMultiLEDModeControl(const max30102::Slot slot1, const max30102::Slot slot2)
Write the MultiLED Mode to Slot 1-2.
Definition unit_MAX30102.cpp:494
uint32_t red() const
Oldest Red.
Definition unit_MAX30102.hpp:263
bool resetFIFO()
Reset FIFO pointer and counter.
Definition unit_MAX30102.hpp:593
bool writeLEDCurrent(const uint8_t slot, const uint8_t raw)
Write the LED current.
Definition unit_MAX30102.hpp:486
bool writeSpO2LEDPulseWidth(const max30102::LEDPulse width)
Write the LED pulse width.
Definition unit_MAX30102.cpp:440
bool writeSpO2Configuration(const max30102::ADC range, const max30102::Sampling rate, const max30102::LEDPulse width)
Write the SpO2 configuration.
Definition unit_MAX30102.cpp:410
bool readFIFOOverflowCounter(uint8_t &cnt)
Read the FIFO overflow counter.
Definition unit_MAX30102.hpp:582
bool readSpO2SamplingRate(max30102::Sampling &rate)
Read the sampling rate.
Definition unit_MAX30102.hpp:423
uint8_t retrieved() const
Number of data last retrieved.
Definition unit_MAX30102.hpp:272
bool stopPeriodicMeasurement()
Stop periodic measurement.
Definition unit_MAX30102.hpp:344
bool reset()
Reset.
Definition unit_MAX30102.cpp:682
bool writeFIFOWritePointer(const uint8_t wptr)
Write the FIFO write pointer.
Definition unit_MAX30102.hpp:577
uint32_t caluculateSamplingRate()
Deprecated alias of calculateSamplingRate()
Definition unit_MAX30102.hpp:304
bool writeFIFOOverflowCounter(const uint8_t cnt)
Write the FIFO overflow counter.
Definition unit_MAX30102.hpp:588
bool measureTemperatureSingleshot(max30102::TemperatureData &td)
Measure temperature single shot.
Definition unit_MAX30102.cpp:526
bool readRevisionID(uint8_t &rev)
Read the revision ID.
Definition unit_MAX30102.cpp:703
bool writeMode(const max30102::Mode mode)
Write the operation mode.
Definition unit_MAX30102.cpp:336
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:331
bool writeSpO2ADCRange(const max30102::ADC range)
Write the ADC range.
Definition unit_MAX30102.cpp:420
UnitMAX30102(const uint8_t addr=DEFAULT_ADDRESS)
Constructor.
Definition unit_MAX30102.hpp:224
uint32_t calculateSamplingRate()
Calculate the sampling rate from the current settings.
Definition unit_MAX30102.cpp:709
bool writeSpO2SamplingRate(const max30102::Sampling rate)
Write the sampling rate.
Definition unit_MAX30102.cpp:430
bool readShutdownControl(bool &shdn)
Read the shutdown control.
Definition unit_MAX30102.cpp:354
bool readLEDCurrent(uint8_t &raw, const uint8_t slot)
Read the LED current.
Definition unit_MAX30102.hpp:465
bool readFIFOConfiguration(max30102::FIFOSampling &avg, bool &rollover, uint8_t &almostFull)
Read the FIFO configuration.
Definition unit_MAX30102.cpp:549
bool readFIFOWritePointer(uint8_t &wptr)
Read the FIFO write pointer.
Definition unit_MAX30102.hpp:571
bool startPeriodicMeasurement()
Start periodic measurement in the current settings.
Definition unit_MAX30102.hpp:315
bool readMultiLEDModeControl(max30102::Slot &slot1, max30102::Slot &slot2)
Read the MultiLED Mode from Slot 1-2.
Definition unit_MAX30102.cpp:482
config_t config()
Gets the configuration.
Definition unit_MAX30102.hpp:244
bool readFIFOReadPointer(uint8_t &rptr)
Read the FIFO read pointer.
Definition unit_MAX30102.hpp:560
bool readSpO2ADCRange(max30102::ADC &range)
Read the ADC range.
Definition unit_MAX30102.hpp:416
uint32_t ir() const
Oldest IR.
Definition unit_MAX30102.hpp:258
virtual void update(const bool force=false) override
Update the unit.
Definition unit_MAX30102.cpp:260
uint8_t retrived() const
Deprecated alias of retrieved()
Definition unit_MAX30102.hpp:280
bool readSpO2Configuration(max30102::ADC &range, max30102::Sampling &rate, max30102::LEDPulse &width)
Read the SpO2 configuration.
Definition unit_MAX30102.cpp:380
bool readLEDCurrent(float &mA, const uint8_t slot)
Read the LED current.
Definition unit_MAX30102.hpp:476
bool writeFIFOConfiguration(const max30102::FIFOSampling avg, const bool rollover, const uint8_t almostFull)
Write the FIFO configuration.
Definition unit_MAX30102.cpp:565
void config(const config_t &cfg)
Set the configuration.
Definition unit_MAX30102.hpp:249
bool writeShutdownControl(const bool shdn)
Write the shutdown control.
Definition unit_MAX30102.cpp:365
uint8_t overflow() const
The number of samples lost.
Definition unit_MAX30102.hpp:288
virtual bool begin() override
Begin the unit.
Definition unit_MAX30102.cpp:225
bool readSpO2LEDPulseWidth(max30102::LEDPulse &width)
Read the LED pulse width.
Definition unit_MAX30102.hpp:430
bool writeLEDCurrent(const uint8_t slot, const T mA)
Write the LED current.
Definition unit_MAX30102.hpp:498
Top level namespace of M5Stack.
For MAX30102.
Unit-related namespace.
Settings for begin.
Definition unit_MAX30102.hpp:199
max30102::LEDPulse pulse_width
LED pulse width if start on begin.
Definition unit_MAX30102.hpp:213
max30102::FIFOSampling fifo_sampling_average
FIFO sampling average if start on begin.
Definition unit_MAX30102.hpp:219
bool start_periodic
Start periodic measurement on begin?
Definition unit_MAX30102.hpp:207
max30102::ADC adc_range
ADC range if start on begin.
Definition unit_MAX30102.hpp:209
max30102::Mode mode
Operating mode if start on begin.
Definition unit_MAX30102.hpp:205
max30102::Sampling sampling_rate
Sampling rate if start on begin.
Definition unit_MAX30102.hpp:211
uint8_t ir_current
LED current for IR if start on begin.
Definition unit_MAX30102.hpp:215
uint8_t red_current
LED current for Red if start on begin (only SpO2 MODE)
Definition unit_MAX30102.hpp:217
Measurement data group.
Definition unit_MAX30102.hpp:108
std::array< uint8_t, 6 > raw
Raw data [0...2]:Red [3...5]:IR.
Definition unit_MAX30102.hpp:109
uint32_t mask
Definition unit_MAX30102.hpp:110
uint32_t red() const
Gets the Red value.
Definition unit_MAX30102.hpp:118
uint32_t ir() const
Gets the IR value.
Definition unit_MAX30102.hpp:112
Measurement data group for temperature.
Definition unit_MAX30102.hpp:129
float fahrenheit() const
Temperature (Fahrenheit)
Definition unit_MAX30102.hpp:143
float celsius() const
Temperature (Celsius)
Definition unit_MAX30102.hpp:137
float temperature() const
Temperature (Celsius)
Definition unit_MAX30102.hpp:132
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