Общие сведения
Датчик пульсоксиметрии MAX30102 — плата с интегрированным сенсорным модулем, которая позволяет определять частоту сердечных сокращений, то есть пульс, а так же уровень насыщения крови кислородом (SpO2). Помимо этого, в сенсор встроен температурный датчик, с помощью которого вы можете получить значение температуры (в Цельсиях и Фаренгейтах) окружающей среды.
Видео
Характеристики
- Оптический модуль с возможностью измерения ЧСС (пульс), SpO2 (степень насыщения крови кислородом) и температуры среды;
- Адрес на шине I2C: 0x57;
- Входное напряжение: 5В;
- Габариты датчика: 15.5мм х 19.5мм х 2.5мм (без гребёнки);
- Рабочая температура: -40°С ... +85°С;
Подключение
Для удобства подключения к Arduino воспользуйтесь Trema Shield, Trema Power Shield, Motor Shield или Trema Set Shield.
Так как датчик работает по шине I2C, то его выводы подключаются следующим образом:
MAX30102 | Trema Shield |
---|---|
VIN | Vcc |
SDA | SDA |
SCL | SCL |
GND | Gnd |
Питание
Датчик питается от напряжения 5 В.
Подробнее о датчике
Датчик предназначен для создания портативных носимых приборов контроля сердечного ритма и насыщенности крови кислородом.
В состав самой микросхемы входят светодиоды (ИК- и красного цвета), а так же фотоприемник и оптические элементы. Важно так же отметить, что полученные сигналы имеют низкий уровень шума. В ходе измерений испускаемый красный и инфракрасный свет регулируется встроенными программными методами за счёт изменения интенсивности свечения и его (свечения) длительности.
Датчик может быть программно переведен в режим ожидания, а благодаря технологии сверхнизкого потребления энергии в режиме ожидания ток потребления будет практически нулевой.
Примеры
Во время измерения любых значений необходимо, чтобы палец находился в постоянном зафиксированном положении и давил на сенсор с постоянным неизменяющимся давлением (лёгкое нажатие), или же, в случае с расположением на запястье, находился в неподвижном положении всё время измерений. Для решения этой задачи предлагается воспользоваться обычной канцелярской резинкой или ремешком, которые стоит продеть в петли модуля и зафиксировать модуль на пальце или запястье. В противном случае точность измерений может существенно снизиться.
Вывод значений ЧСС в монитор порта.
#include "Wire.h" // Подключаем библиотеку для работы с шиной I2C #include "MAX30105.h" // Подключаем библиотеку для работы с модулем #include "heartRate.h" // Подключаем блок для работы с ЧСС (пульс) MAX30105 PARTICLE_SENSOR; // Создаём объект для работы с библиотекой //--------------------------// const byte RATE_SIZE = 4; // Коэффициент усреднения. ЧЕм больше число, тем больше усреднение показаний. byte rates[RATE_SIZE]; // Массив со значениями ЧСС byte rateSpot = 0; // Переменная с порядковым номером значения в массиве long lastBeat = 0; // Время последнего зафиксированного удара float beatsPerMinute; // Создаём переменную для хранения значения ЧСС int beatAvg; // Создаём переменную для хранения усреднённого значения ЧСС //----------------------------------------------------// void setup() { Serial.begin(115200); // Инициируем работу с монитором последовательного порта на скорости 115200 бод if (!PARTICLE_SENSOR.begin()) { // Инициируем работу с модулем. Если инициализация не прошла, то Serial.println("MAX30105 was not found"); // выводим сообщение об этом в монитор последовательного порта while (1); // и останавливаем дальнейшее выполнение скетча } Serial.println("Place your finger on the sensor"); // выводим сообщение "Положите палец сверху на сенсор" PARTICLE_SENSOR.setup(); // Устанавливаем настройки для сенсора по умолчанию PARTICLE_SENSOR.setPulseAmplitudeRed(0x0A); // Выключаем КРАСНЫЙ светодиод для того, чтобы модуль начал работу PARTICLE_SENSOR.setPulseAmplitudeGreen(0); // Выключаем ЗЕЛЁНЫЙ светодиод } //------------------------------------------------------// void loop() { long irValue = PARTICLE_SENSOR.getIR(); // Считываем значение отражённого ИК-светодиода (отвечающего за пульс) и if (checkForBeat(irValue) == true) { // если пульс был зафиксирован, то long delta = millis() - lastBeat; // находим дельту по времени между ударами lastBeat = millis(); // Обновляем счётчик beatsPerMinute = 60 / (delta / 1000.0); // Вычисляем количество ударов в минуту if (beatsPerMinute < 255 && beatsPerMinute > 20) { // Если количество ударов в минуту находится в промежутке между 20 и 255, то rates[rateSpot++] = (byte)beatsPerMinute; // записываем это значение в массив значений ЧСС rateSpot %= RATE_SIZE; // Задаём порядковый номер значения в массиве, возвращая остаток от деления и присваивая его переменной rateSpot beatAvg = 0; // Обнуляем переменную и for (byte x = 0 ; x < RATE_SIZE ; x++) { // в цикле выполняем усреднение значений (чем больше RATE_SIZE, тем сильнее усреднение) beatAvg += rates[x]; // путём сложения всех элементов массива } beatAvg /= RATE_SIZE; // а затем деления всей суммы на коэффициент усреднения (на общее количество элементов в массиве) } } Serial.print("IR="); // Выводим в монитор последовательного порта текст про значение ИК-светдиода Serial.print(irValue); // Выводим в монитор последовательного порта значение с ИК-светодиода Serial.print(", BPM="); // Выводим в монитор последовательного порта текст про значение ЧСС Serial.print(beatsPerMinute); // Выводим в монитор последовательного порта значение ЧСС Serial.print(", Avg BPM="); // Выводим в монитор последовательного порта текст про усреднённую ЧСС Serial.print(beatAvg); // Выводим в монитор последовательного порта значение усреднённой ЧСС if (irValue < 50000) Serial.print(" No finger?"); // Если значение ИК-светодиода меньше указанного, то выводим текст о том, что палец убран с датчика Serial.println(); // Выводим в монитор последовательного порта переход на новую строку }
Вывод значений температуры окружающей среды в монитор порта.
#include "Wire.h" // Подключаем библиотеку для работы с шиной I2C #include "MAX30105.h" // Подключаем библиотеку для работы с модулем MAX30105 PARTICLE_SENSOR; // Создаём объект для работы с библиотекой void setup() { Serial.begin(9600); // Инициируем работу с монитором последовательного порта на скорости 9600 бод if (!PARTICLE_SENSOR.begin()) { // Инициируем работу с модулем. Если инициализация не прошла, то Serial.println("MAX30105 was not found."); // выводим сообщение об этом в монитор последовательного порта while (1); // и останавливаем дальнейшее выполнение скетча } // Встроенные светодиоды потребляют незначительный ток, // однако, если вы хотите исключить их возможное влияние // на результат, то используйте следующую строку: PARTICLE_SENSOR.setup(0); // Настраиваем сенсор на работу с выключенными светодиодами // Если же вы хотите запустить сенсор в стандартном // режиме, то раскомментируйте следующую строку: //PARTICLE_SENSOR.setup(); // Устанавливаем настройки для сенсора по умолчанию PARTICLE_SENSOR.enableDIETEMPRDY(); // Включаем поддержку прерываний для датчика температуры. Это ОБЯЗАТЕЛЬНЫЙ параметр } void loop() { float temperature = PARTICLE_SENSOR.readTemperature(); // Создаём переменную с плавающей точкой и записываем в неё полученное от датчика значение (в Цельсиях) Serial.print("temperature C = "); // Выводим в монитор последовательного порта текст Serial.print(temperature, 4); // Выводим в монитор последовательного порта значение температуры в Цельсиях float temperatureF = PARTICLE_SENSOR.readTemperatureF(); // Создаём переменную с плавающей точкой и записываем в неё полученное от датчика значение (в Фаренгейтах) Serial.print(" | temperature F = "); // Выводим в монитор последовательного порта текст Serial.print(temperatureF, 4); // Выводим в монитор последовательного порта значение температуры в Фаренгейтах Serial.println(); // Переходим на новую строку }
Вывод значений
уровня SpO2
в монитор порта.
#define MAX_BRIGHTNESS 255 // Задаём переменную максимальной яркости свечения светодиода //--------------------------------------------------// #include "Wire.h" // Подключаем библиотеку для работы с шиной I2C #include "MAX30105.h" // Подключаем библиотеку для работы с модулем #include "spo2_algorithm.h" // Подключаем блок работы с насыщением крови кислородом MAX30105 PARTICLE_SENSOR; // Создаём объект для работы с библиотекой //--------------------------------------------------// // 32-битная переменная занимает в памяти 4 байта. Дальше используется 2 массива, каждый из которых содержит 100 значений. // Если эти переменные будут 32-х битные, то они займут 100*4*2 = 800 байт. Arduino UNO имеет всего 2 Килобайт (2048 байт) памяти, // поэтому при создании всех остальных переменных её объёма памяти не хватит. В связи с этим при запуске скетча выполняется проверка // типа платы. Если это Arduino UNO (имеющая на борту микроконтроллер ATmega328), то будут созданы 16-битные массивы, чтобы занимать // в 2 раза меньше места. Так как данные с сенсора считываются в 32-битном формате, то при записи в 16-битный массив эти значения // будут автоматически обрезаны. #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) uint16_t irBuffer[100]; // 16-битный массив данных от сенсора со значениями от ИК-светодиода uint16_t redBuffer[100]; // 16-битный массив данных от сенсора со значениями от красного светодиода #else uint32_t irBuffer[100]; // 32-битный массив данных от сенсора со значениями от ИК-светодиода uint32_t redBuffer[100]; // 32-битный массив данных от сенсора со значениями от красного светодиода #endif //--------------------------------------------------// int32_t bufferLength; // длина буфера данных int32_t spo2; // значение SpO2 (насыщенности крови кислородом) int8_t validSPO2; // флаг валидности значений сенсора по SpO2 int32_t heartRate; // значение ЧСС int8_t validHeartRate; // флаг валидности значений сенсора по ЧСС //--------------------------------------------------// void setup() { Serial.begin(115200); // инициируем работу с монитором последовательного порта на скорости 115200 бод if (!PARTICLE_SENSOR.begin()) { // инициируем работу с сенсором. Если этого не произошло, то Serial.println(F("MAX30105 was not found.")); // Выводим сообщением об этом и while (1); // останавливаем дальнейшее выполнение скетча } Serial.println(F("Press any key!")); // Прежде, чем переходить к считыванию, выводим в монитор порта сообщение и while (Serial.available() == 0); // ждём отправки любого символа в монитор порта (нажмите Enter, находясь в строке отправки) Serial.read(); // Если символ получен, то скетч будет выполнен дальше //------------------------------------------------// // Блок настроек сенсора для работы в режиме определения насыщенности крови кислородом и определения ЧСС: byte ledBrightness = 60; // Задаём яркость работы светодиода, при этом потребление тока будет следующим: 0 - 0мА, 255 - 50 мА byte sampleAverage = 4; // Устанавливаем коэффициент усреднения. Возможные варианты значений: 1, 2, 4, 8, 16, 32 byte ledMode = 2; // Устанавливаем режим работы светодиодов на сенсоре: 1 - только красный (Red only), 2 - красный и ИК (Red + IR), 3 - красный, ИК и зелёный (Red + IR + Green) byte sampleRate = 100; // Устанавливаем частоту дискретизации (сглаживания сигнала). Варианты: 50, 100, 200, 400, 800, 1000, 1600, 3200 int pulseWidth = 411; // Устанавливаем ширину импульса. Варианты: 69, 118, 215, 411 int adcRange = 4096; // Устанавливаем диапазон значений с АЦП. Варианты: 2048(11 бит), 4096(12 бит), 8192(13 бит), 16384(14 бит) //------------------------------------------------// // Настраиваем сенсор согласно вышеуказанным настройкам PARTICLE_SENSOR.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); } //----------------------------------------------------// void loop() { bufferLength = 100; // Устанавливаем длину буфера равным 100 (куда будут записаны пакеты по 25 значений в течении 4 секунд) // считываем первые 100 значений и определяем диапазон значений сигнала: for (byte i = 0 ; i < bufferLength ; i++) { // проходим в цикле по буферу и while (PARTICLE_SENSOR.available() == false) // отправляем сенсору запрос на получение новых данных PARTICLE_SENSOR.check(); redBuffer[i] = PARTICLE_SENSOR.getRed(); // Записываем в массив значения сенсора, полученные при работе с КРАСНЫМ светодиодом irBuffer[i] = PARTICLE_SENSOR.getIR(); // Записываем в массив значения сенсора, полученные при работе с ИК светодиодом PARTICLE_SENSOR.nextSample(); // Как только в буфер было записано 100 значений - отправляем сенсору команду начать вычислять значения ЧСС и SpO2 Serial.print(F("red=")); // Выводим текст в монитор последовательного порта Serial.print(redBuffer[i], DEC); // Выводим значение переменной redBuffer[i] в монитор последовательного порта Serial.print(F(", ir=")); // Выводим текст в монитор последовательного порта Serial.println(irBuffer[i], DEC); // Выводим значение переменной irBuffer[i] в монитор последовательного порта } // Вычисляем значения ЧСС и SpO2 по первым полученным 100 значениям: maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); // Непрерывно считываем значений с сенсора и вычисляем значения ЧСС и SpO2 каждую секунду while (1) { // Сбрасываем первые полученные 25 значений из буфера, а оставшиеся 75 сдвигаем влево в массиве for (byte i = 25; i < 100; i++) { redBuffer[i - 25] = redBuffer[i]; irBuffer[i - 25] = irBuffer[i]; } // Получаем новые 25 значений прежде чем переходить к вычислению ЧСС for (byte i = 75; i < 100; i++) { while (PARTICLE_SENSOR.available() == false) { // Опрашиваем сенсор на предмет наличия новых значений PARTICLE_SENSOR.check(); } redBuffer[i] = PARTICLE_SENSOR.getRed(); // Записываем в массив значения сенсора, полученные при работе с КРАСНЫМ светодиодом irBuffer[i] = PARTICLE_SENSOR.getIR(); // Записываем в массив значения сенсора, полученные при работе с ИК светодиодом PARTICLE_SENSOR.nextSample(); // Как только в буфер было записано 100 значений - отправляем сенсору команду начать вычислять значения ЧСС и SpO2 Serial.print(F("red=")); // Выводим текст в монитор последовательного порта Serial.print(redBuffer[i], DEC); // Выводим значение переменной redBuffer[i] в монитор последовательного порта Serial.print(F(", ir=")); // Выводим текст в монитор последовательного порта Serial.print(irBuffer[i], DEC); // Выводим значение переменной irBuffer[i] в монитор последовательного порта Serial.print(F(", HR=")); // Выводим текст в монитор последовательного порта Serial.print(heartRate, DEC); // Выводим значение переменной heartRate в монитор последовательного порта Serial.print(F(", HRvalid=")); // Выводим текст в монитор последовательного порта Serial.print(validHeartRate, DEC); // Выводим значение переменной validHeartRate в монитор последовательного порта Serial.print(F(", SPO2=")); // Выводим текст в монитор последовательного порта Serial.print(spo2, DEC); // Выводим значение переменной spo2 в монитор последовательного порта Serial.print(F(", SPO2Valid=")); // Выводим текст в монитор последовательного порта Serial.println(validSPO2, DEC); // Выводим значение переменной validSPO2 в монитор последовательного порта } // После получения очередного пакета из 25 значений повторно считаем значения ЧСС и SpO2 maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate); } }
Вывод значений ЧСС на светодиодную матрицу 64х32 с анимацией:
#include "Wire.h" // Подключаем библиотеку для работы с шиной I2C #include "MAX30105.h" // Подключаем библиотеку для работы с модулем #include "heartRate.h" // Подключаем блок для работы с ЧСС (пульс) #include "RGBmatrixPanel.h" // Подключаем библиотеку для работы с матрицей //----------------------------// // Используем эти выводы, если матрица подключена к Arduino UNO //#define CLK 8 //#define OE 9 //#define LAT 10 // Используем эти выводы, если матрица подключена к Arduino MEGA //#define CLK 11 //#define OE 9 //#define LAT 10 // Используем эти выводы, если матрица подключена к Piranha ULTRA #define CLK 11 // Вывод Arduino, к которому подключён вывод CLK матрицы #define OE 12 // Вывод Arduino, к которому подключён вывод OE матрицы #define LAT 13 // Вывод Arduino, к которому подключён вывод LAT матрицы #define A A0 // Вывод Arduino, к которому подключён вывод A матрицы #define B A1 // Вывод Arduino, к которому подключён вывод B матрицы #define C A2 // Вывод Arduino, к которому подключён вывод C матрицы #define D A3 // Вывод Arduino, к которому подключён вывод D матрицы #define RATE_SIZE 5 // Коэффициент усреднения, равный количеству элементов в массиве усреднения #define ZUMMER 2 // Вывод, к которому подключен зуммер #define OFF 0 // Переменная, имеющая значение LOW или 0 #define ON 1 // Переменная, имеющая значение HIGH или 1 MAX30105 PARTICLE_SENSOR; // Создаём объект для работы с библиотекой //----------------------------// // Объявляем объект MATRIX для работы с матрицей 64х32, включаем двойную буферизацию RGBmatrixPanel MATRIX(A, B, C, D, CLK, LAT, OE, false, 64); //----------------------------// byte rates[RATE_SIZE]; // Массив со значениями ЧСС byte rateSpot = 0; // Переменная с порядковым номером значения в массиве bool no_finger_flag = true; // Флаг отсутствия приложенного к сенсору пальца bool new_beat_flag = true; // Флаг считывания нового удара пульса long lastBeat = 0; // Время последнего зафиксированного удара float beatsPerMinute; // Создаём переменную для хранения значения ЧСС int beatAvg; // Создаём переменную для хранения усреднённого значения ЧСС //----------------------------// // Указываем 2 массива с изображениями сердца - малого размера и большого, для создания анимации static const unsigned char PROGMEM small_heart[] = { 0x03, 0xC0, 0xF0, 0x06, 0x71, 0x8C, 0x0C, 0x1B, 0x06, 0x18, 0x0E, 0x02, 0x10, 0x0C, 0x03, 0x10, 0x04, 0x01, 0x10, 0x04, 0x01, 0x10, 0x40, 0x01, 0x10, 0x40, 0x01, 0x10, 0xC0, 0x03, 0x08, 0x88, 0x02, 0x08, 0xB8, 0x04, 0xFF, 0x37, 0x08, 0x01, 0x30, 0x18, 0x01, 0x90, 0x30, 0x00, 0xC0, 0x60, 0x00, 0x60, 0xC0, 0x00, 0x31, 0x80, 0x00, 0x1B, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x00, }; static const unsigned char PROGMEM large_heart[] = { 0x01, 0xF0, 0x0F, 0x80, 0x06, 0x1C, 0x38, 0x60, 0x18, 0x06, 0x60, 0x18, 0x10, 0x01, 0x80, 0x08, 0x20, 0x01, 0x80, 0x04, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0xC0, 0x00, 0x08, 0x03, 0x80, 0x00, 0x08, 0x01, 0x80, 0x00, 0x18, 0x01, 0x80, 0x00, 0x1C, 0x01, 0x80, 0x00, 0x14, 0x00, 0x80, 0x00, 0x14, 0x00, 0x80, 0x00, 0x14, 0x00, 0x40, 0x10, 0x12, 0x00, 0x40, 0x10, 0x12, 0x00, 0x7E, 0x1F, 0x23, 0xFE, 0x03, 0x31, 0xA0, 0x04, 0x01, 0xA0, 0xA0, 0x0C, 0x00, 0xA0, 0xA0, 0x08, 0x00, 0x60, 0xE0, 0x10, 0x00, 0x20, 0x60, 0x20, 0x06, 0x00, 0x40, 0x60, 0x03, 0x00, 0x40, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x30, 0x0C, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00 }; //--------------------------------------------// void setup() { PARTICLE_SENSOR.begin(); // Инициируем работу с сенсором MATRIX.begin(); // Инициируем работу с матрицей MATRIX.setTextWrap(false); // Отключаем перенос текста на следующую строку MATRIX.setTextSize(1); // Устанавливаем размер текста равным 1 (6 пикселей на символ) pinMode(ZUMMER, OUTPUT); // Настраиваем вывод, к которому подключен зуммер, работать в режиме ВЫХОДА PARTICLE_SENSOR.setup(); // Запускаем сенсор с настройками по умолчанию PARTICLE_SENSOR.setPulseAmplitudeRed(0x0A); // Выключаем КРАСНЫЙ светодиод для того, чтобы модуль начал работу PARTICLE_SENSOR.setPulseAmplitudeGreen(0); // Выключаем ЗЕЛЁНЫЙ светодиод } //----------------------------------------------------------------------------// void loop() { long irValue = PARTICLE_SENSOR.getIR(); // Считываем значение отражённого ИК-светодиода (отвечающего за пульс) и if (irValue > 50000) { // если был зафиксирован приложенный к сенсору палец, то no_finger_flag = true; // устанавливаем флаг отсутствия пальца if (new_beat_flag == true) { // Проверяем, если флаг нового удара пульса установлен, то new_beat_flag = false; // сбрасываем флаг нового удара сердца MATRIX.fillScreen(0); // Очищаем экран MATRIX.drawBitmap(5, 5, small_heart, 24, 21, MATRIX.Color333(3, 0, 0)); // Выводим изображение сердца малого размера MATRIX.setCursor(37, 5); // Устанавливаем курсор MATRIX.print("BPM:"); // Выводим текст MATRIX.setCursor(40, 20); // Устанавливаем курсор MATRIX.print(beatAvg); // Выводим количество ударов в минуту MATRIX.swapBuffers(false); // Выводим изображение из буфера на матрицу } if (checkForBeat(irValue) == true) { // Если зафиксирован новый удар пульса, то new_beat_flag = true; // устанавливаем флаг нового удара long delta = millis() - lastBeat; // вычисляем дельту по времени между 2 соседними ударами lastBeat = millis(); // обновляем счётчик времени beatsPerMinute = 60 / (delta / 1000.0); // вычисляем "сырое" количество ударов в минуту if (beatsPerMinute < 255 && beatsPerMinute > 20) { // Дополнительно отфильтровываем значение ударов в минуту и если оно попадает в выборку, то rates[rateSpot++] = (byte)beatsPerMinute; // записываем новое значение в массив усреднения rateSpot %= RATE_SIZE; // Задаём порядковый номер значения в массиве, возвращая остаток от деления и присваивая его переменной rateSpot beatAvg = 0; // Обнуляем переменную и for (byte x = 0 ; x < RATE_SIZE ; x++) // в цикле выполняем усреднение значений (чем больше RATE_SIZE, тем сильнее усреднение) beatAvg += rates[x]; // путём сложения всех элементов массива beatAvg /= RATE_SIZE; // а затем деления всей суммы на коэффициент усреднения (на общее количество элементов в массиве) } digitalWrite(ZUMMER, ON); // Включаем зуммер MATRIX.fillRect(0, 0, 32, 32, MATRIX.Color333(0, 0, 0)); // Выводим квадрат размером 32х32, закрашенный чёрным, чтобы затереть изображение сердца малого размера MATRIX.drawBitmap(0, 0, large_heart, 32, 32, MATRIX.Color333(3, 0, 0)); // Выводим рисунок сердца большого размера MATRIX.swapBuffers(false); // Выводим изображение из буфера на матрицу delay(100); // Ждём 100мс, чтобы зуммер и матрица отобразили изменения и включились digitalWrite(ZUMMER, OFF); // Выключаем зуммер } } if (irValue < 50000 && no_finger_flag == true ) { // Если пале убран с сенсора, то for (byte x = 0 ; x < RATE_SIZE ; x++) { // проходим в цикле по массиву усреднения и rates[x] = 0; // обнуляем его } beatAvg = 0; // обнуляем переменную со значением усреднённой ЧСС no_finger_flag = false; // сбрасываем флаг отсутствия пальца на сенсоре, чтобы не заходить в этот блок при каждом выполнении цикла new_beat_flag = true; // Устанавливаем флаг обнаружения пальца, чтобы в следующий проход цикла зайти в блок определения пульса MATRIX.fillScreen(0); // Очищаем экран MATRIX.setTextColor(MATRIX.Color333(3, 3, 3)); // Устанавливаем цвет текста MATRIX.setCursor(3, 12); // Устанавливаем крусор MATRIX.println("No finger!"); // Выводим тект о том, что палец не приложен MATRIX.swapBuffers(false); // Выводим изображение из буфера на матрицу } }
Комплектация
- 1x Датчик пульсоксиметрии MAX30102;
- 1x 4-контактная гребёнка;
Ссылки
- DataSheet;
- Библиотека SparkFun_MAX3010x_Sensor_Library;