- Digitrode
- цифровая электроника вычислительная техника встраиваемые системы
- Пульсоксиметр своими руками на основе Arduino и MAX30102
- Arduino + max30102 + ЦОС = SpO2
- Arduino + max30102 + ЦОС = SpO2
- Делаем пульсоксиметр и фотоплетизмограф на микроконтроллере ATtiny85
- ATtiny85 SSD1306 MAX30102
- Аппаратная часть и работа прибора
- Программная часть
- Загрузки
- Материалы по теме
Digitrode
цифровая электроника вычислительная техника встраиваемые системы
Пульсоксиметр своими руками на основе Arduino и MAX30102
Если вы недавно посетили врача, скорее всего, медсестра проверила ваши основные жизненно важные функции. Это вес, рост, артериальное давление, а также частота сердечных сокращений (ЧСС) и сатурация кислорода в периферической крови (SpO2). Возможно, последние два параметра были получены с помощью светящегося красным электронным датчиком, прикрепляемым к пальцу, который отображал соответствующие числа на крошечном экране за считанные минуты. Этот датчик называется пульсоксиметром, и вы можете сделать такой самостоятельно на основе микросхемы MAX30102.
Пульсоксиметры могут приблизительно определять частоту сердечных сокращений, анализируя реакцию временного ряда отраженного красного и инфракрасного света. Здесь мы используем MAX30102 и Arduino для моздания такого устройства.
Пульсоксиметр MAX30102 – это недорогой датчик, совместимый с Arduino, который позволяет рассчитывать частоту сердечных сокращений. MAX30102 использует двухпроводную связь I2C для взаимодействия с платой Arduino. Мы используем порты I2C на выводах A4/A5 на плате Arduino. Схема подключения показана далее.
Для работы с датчиком нужна библиотека его функций. Sparkfun предоставляет библиотеку, которая обеспечивает связь между Arduino и MAX30102. В среде Arduino IDE перейдите в меню «Управление библиотеками» и введите «max30» в строку поиска. Загрузите библиотеку «Sparkfun MAX3010x Pulse and Proximity Sensor Library».
Далее представлен простой код программы Arduino. Он производит выборку данных от MAX30102 с частотой 400 Гц и выводит их через последовательный порт. При 400 Гц и последовательной скорости передачи 115200 компьютер способен без проблем читать каждую точку данных.
Если вплотную к MAX30102 поднести палец, вывод плоттера последовательного порта Arduino должен выглядеть следующим образом.
Нам не нужно беспокоиться о сложности отследить форму каждого графика, поскольку мы обработаем данные в Python и полностью проанализируем данные красного и ИК-диапазона от датчика MAX30102. В следующем разделе мы будем считывать данные 400 Гц в реальном времени в Python и выводить их в удобном виде. В качестве приемника данных с обработкой на Python можно использовать Raspberry Pi.
В приведенном выше коде Arduino единственное изменение, которое нам нужно сделать, это добавить функцию «micros()», чтобы прикрепить временную метку к показаниям данных значений красного и ИК-отражения. Обновленный код Arduino выглядит следующим образом.
Алгоритм высокоскоростного последовательного считывания для Python для считывания значений последовательного вывода Arduino показан далее. Код Python получит данные и сохранит их в файл .csv для последующего анализа. Причина, по которой мы сохраняем их сразу, заключается в том, что данные поступают с такой высокой скоростью, что мы хотим минимизировать объем обработки, выполняемой между последовательными сборами.
Окончательный график, созданный приведенным выше кодом Python, должен выглядеть следующим образом.
Источник
Arduino + max30102 + ЦОС = SpO2
Arduino + max30102 + ЦОС = SpO2
Однажды увидев на али оксиметр, стало интересно как же он устроен. А разобравшись, удивился его простоте и решил его повторить.
Немного разобравшись, оказалось все не так сложно и пришел в результате к следующим модулям:
готовый измерительный модуль на max30102 (сердце измерения оксигинации). Модуль конечно может быть любым, главное чтобы на основе max30102.
мозги для управления выше указанным, модуль на stm32f103.
и то куда все это выводить led дисплей на i2c.
Ну и конечно нашелся готовый проект какого-то китайца: https://github.com/Jasoji/stm32-max30102 со своими ошибками и проблемами, но об этом всем дальше.
Опустим схемную часть, там отсутствует аналоговая электроника и все довольно таки прозрачно.
Как ни странно проект заработал сразу, будучи собранным и залитым в модуль. Но вот стабильность его работы никак не устроила, постоянные срывы измерения и значения в пределах 60-80, необходимость держать палец на весу и желательно им не дергать. В общем сплошное расстройство. Пробовал конечно и другие библиотеки для расчета сатурации, но и там ничуть не лучше результат измерения.
Исследование кода показало почему были такие рваные и нестабильные показания. В файле max30102.c в функции max30102_cal, есть такие строчки:
Где указаны волшебные коэффициенты, по которым и определяется правильность вычисленных показаний. А показания для этой части вытаскиваются напрямую из макса в потоковом режиме, и если в текущем цикле показания не прошли этот фильтр. то и не будут они использованы. Т.е. пока дергается палец, показания через этот фильтр не пройдут. А достаточно всего лишь малейшего движения мышц.
Самое печальное, что эти коэффициенты находятся в лабораторных условиях для конкретных сборок (имеется ввиду max30102 и им подобные). Короче их лучше не трогать и эти коэффициенты описаны в документации на эту микруху, а еще там описана методика и принцип измерения.
А единственный фильтр который был, это ограничение АЦП в max30102 шестью битами. Это довольно грубый фильтр в результате которого с выхода идет почти синус, ну и график для отрисовки соответствующий. А хотелось бы отображения нормального сердцебиения.
Вторая проблема это перепутанные местами значения красного и инфракрасного.
Поэтому приступим к изменениям:
изменение красного и инфракрасного
увеличение настроек АЦП (хочется видеть сердцебиение и не синус)
создание цифрового фильтра для поиска экстремумов и потокового расчета сатурации
На первой очереди путаница с показаниями АЦП красного и инфракрасного фотодиода. Как показало исследование вопроса, уровень отраженного сигнала с ИК диода будет выше чем от красного и значения АЦП соответственно выше, поэтому код для исправления следующий:
В общем этот код выставляет красный и инфракрасный правильным образом.
Дальнейшая проблема всплыла когда увеличил разрядность АЦП, оказалось что имеющийся код не справляется с поиском экстремумов для расчета сатурации.
Это то что я увидел когда вытащил показания АЦП наружу. Внутри-процессорная отладка наше все).
Если значения ИК будут в районе 108к, то значение красного в районе 101к. И это среднее значение еще и плавает в пределах пары своих амплитуд. И в этот момент я замер дабы не шевелить пальцем, по крайней мере мне так казалось. Печально конечно что халявы не вышло и придется городить ЦОС. И это только первая проблема, вторая проблема ниже:
Видите эта подставка с проседанием по амплитуде, это так работает сердце и из-за этого не так просто найти экстремум.
А теперь приступим к решению проблем.
Начнем с формулы.
R = (ACred/DCred) / (ACired/DCired)
a,b,c — калибровочные коэффициенты (именно они находятся в лабораторных условиях, для конкретной измерительной схемы). Для max30102 значения можно найти в документации на эту микруху.
ACred — размах одного периода от максимума до минимума в относительных единицах.
DCred — постоянная составляющая сигнала. Я брал среднеквадратичное значение АЦП за последние несколько секунд.
т.е. выходит что сатурация измеряется по одному сердцебиению.
Далее необходимо найти экстремумы.
В простейшем случае синусоподобного сигнала это не так сложно, но т.к. судя по первой картинке у нас сигнал прыгает не только по амплитуде, но и в средней величине. А это значит что необходимо знать среднюю величину сигнала. Вот тут и ищем средне квадратичный уровень сигнала с АЦП, от которого в дальнейшем ищем максимум и минимум.
Но у каждого импульса есть небольшая просадка амплитуды и она каждый раз разная, что тоже надо учитывать.
Поэтому для измерения уровня оксигинации есть два подхода:
1. Выставить минимальное разрешение АЦП, что автоматически отфильтрует эту просадку. Но тут при выводе рисунка колебания, сердцебиение будет больше похоже на синус.
2.Если же увеличить разрешение АЦП, то придется искуственно снижать разрешение для получения синуса и далнейшего поиска экстремума.
Нас интересует второй подход. Оригинальный сигнал с АЦП выкидываем сразу на дисплей (там сердцебиение в своем оригинале).
Дальше сигнал пропускам через фильтр и получаем почти синус.
Ищем местоположение экстремума на синусе.
В том же месте где был найден экстремум в синусе, ищем тот же экстремум но в оригинальном сигнале.
Найденные значения в формулу расчета.
Вот собственно и все. дальше остается подставить в формулу и вывести график на экран.
Что еще можно сказать про этот проект, сатурация меряется довольно точно. И легко можно понять что и измерения правильны, по гармоничности колебаний на графике. И если задержать дыхание и терпеть до последнего, то можно видеть просадку сатурации с 99% до 95%, что в принципе является нормой.
Источник
Делаем пульсоксиметр и фотоплетизмограф на микроконтроллере ATtiny85
ATtiny85 SSD1306 MAX30102
Примечание: прибор не предназначен для использования в медицинских целях.
Устройство позволяет измерять частоту пульса, уровень кислорода в крови и динамический график сердечного ритма – фотоплетизмограмму.
Arduino-проект, получивший название tinyPulsePPG (Рисунок 1), реализован на микроконтроллере (МК) Microchip ATtiny85 и в режиме реального времени отображает динамическую фотоплетизмограмму (график сердечного ритма), частоту пульса и значения SpO2, которые позволяет оценить процентное содержание кислорода в крови. В приборе используется OLED дисплей с разрешением 128×32 точки на контроллере SSD1306 и модуль цифрового датчика MAX30102 компании Maxim. Следует заметить, что расчет значения SpO2 очень приблизительный, никаких калибровок не производилось.
Рисунок 1. | Пульсоксиметр и фотоплетизмограф на микроконтроллере ATtiny85. |
Основной целью проекта является демонстрация возможности реализовать функциональное устройство на МК с объемом оперативной памяти 512 Байт. Это означает, что данные, поступающие от датчика MAX30102, должны обрабатываться на лету. Большинство подобных проектов на Arduino работают иначе: сначала считываются примерно 100 сэмплов, а затем обрабатывают их.
Аппаратная часть и работа прибора
Принципиальная схема прибора изображена на Рисунке 2. МК ATtiny85 настроен на работу с тактовой частотой 16 МГц с использованием ядра ATtinyCore для среды Arduino. Дополнительную информацию по настройке и загрузке Arduino программ в МК ATtiny85 смотрите в [1]. Следовательно, согласно спецификации на МК, напряжение питания должно быть больше 4.5 В. Тем не менее, в ходе проверки МК показал стабильную работу от Li-Ion (Li-Po) аккумулятора в диапазоне напряжений 3.7 В – 4.2 В.
Рисунок 2. | Принципиальная схема пульсоксиметра на МК ATtiny85. |
Устройство собрано на макетной плате, но можно применить и монтажную плату для быстрого прототипирования. Модуль пульсоксиметра на датчике MAX30102 и OLED дисплей подключаются к микроконтроллеру по интерфейсу I 2 C.
Собрав схему и запрограммировав МК, после подачи питания на дисплее прибора на дисплее вы увидите надпись «PLACE FINGER», а также дополнительную информацию о напряжении питания и режиме работы (Рисунок 3).
Рисунок 3. | Включение пульсоксиметра в режиме работы без фильтрации данных (RAW) по инфракрасному светодиоду датчика (IR). |
Когда вы поместите палец на датчик, на дисплее будет отображаться график сердечного ритма, частота пульса и два оценочных значения количества кислорода в крови (почему два значения SpO2, объясним ниже), как на видео ниже.
Красный светодиод мигает с частотой сердцебиения, дисплей обновляется каждые 50 мс. Единственная кнопка в приборе предназначена для пробуждения системы, когда она переходит в спящий режим (через 10 секунд, если на датчик не активен), а также для переключения между четырьмя режимами работы. Четыре режима работы позволяют пользователю наблюдать форму сигнала отдельно на красном и инфракрасном светодиоде датчика. В режиме работы «RAW» на дисплее отображается график сердечного ритма без фильтрации (усреднения) данных. В режиме «Avg» график сердечного ритма строится по усредненным данным (Рисунок 4). Форма сигнала сердечного ритма в этом режиме видна на видео ниже.
Рисунок 4. | Включение пульсоксиметра в режиме работы с усреднением данных (Avg) по инфракрасному светодиоду датчика (IR). |
Программная часть
Проблема с драйвером датчика MAX30102 заключается в том, что используемый в приборе датчик выпускается на плате MH-ET LIVE. В спецификации на датчик подразумевается, но не указывается явно, что LED1 – красный светодиод, LED2 – инфракрасный (ИК). Однако, если сигнал управления на LED1 равен 0, красный светодиод остается включенным (как на Рисунке 3), если же сигнал управления на LED2 равен 0, то красный светодиод гаснет. Очевидный вывод состоит в том, что LED1 – это ИК светодиод, а LED2 – красный, который также участвует в измерениях уровня насыщения крови кислородом (см. описание ниже). Мы упоминаем этот момент по причине того, что самый распространенный драйвер датчика MAX30102 для проектов на Arduino – это драйвер SparkFun 3010x, в котором однозначно определено, что LED1 – красный, LED2 – ИК. Это может быть справедливо для модулей с датчиком серии MAX30105, установленных на платах SparkFun, но, похоже, не относится к датчику MAX30102 на плате MH-ET LIVE.
Уровень кислорода в крови обозначает насыщение периферийных капилляров кислородом. Более конкретно, это процент насыщенного кислородом гемоглобина по сравнению с общим количеством гемоглобина в крови (насыщенный и ненасыщенный кислородом гемоглобин).
Насыщенный и ненасыщенный гемоглобин имеют разные характеристики поглощения света для красных и ИК длин волн. На этом принципе основана работа датчиков, таких как MAX30102. В вычислениях используется следующее соотношение:
R = (AC_red/DC_red)/(AC_IR/DC_IR)
где AC_xxx является переменной составляющей сигнала xxx, а DC_xxx является постоянной составляющей сигнала xxx. В приборе вычисляются два значения R. Верхнее значение на дисплее (следующее после частоты пульса) вычисляется по классической формуле:
R = 104 — 1.7 × R
Нижнее значение вычисляется с помощью таблицы из Arduino библиотеки драйвера, которая является приближением формулы:
-45.060 × R × R + 30.354 × R + 94.845
Переменная составляющая вычисляется как размах амплитуды сигнала (от пика до пика) после удаления постоянной составляющей. Постоянная составляющая вычисляется с помощью экспоненциального фильтра скользящего среднего, также фильтр применяется при вычислении переменной составляющей. Автор недостаточно экспериментировал с константами в этих фильтрах, чтобы определить насколько надежным является этот метод вычислений указанных величин.
Построение графика сердечного ритма основывается на красном и ИК сигналах от датчика, и также проходят две стадии фильтрации. Первой, как описано выше, является удаление постоянной составляющей. Второй – это фильтр скользящего среднего, который действует как фильтр нижних частот для удаления переходных процессов до того, как сигнал поступит в детектор пульса. Форму сигнала после каждого из этих фильтров можно отобразить, но в целом более интересна форма сигнала без фильтров.
Например, дикротические выемки, которые можно увидеть на полученном с помощью прибора графике сердечного ритма (Рисунок 1) – «второе движение вверх на нисходящей части траектории, соответствующее увеличению давления в аорте при закрытии аортального клапана. – словарь Merriam Webster». Автор заметил, что если эти дикротические выемки более ярко выраженные – у более молодых людей – они могут преодолеть фильтрацию второго уровня и привести к ошибочному выходному сигналу детектора пульса, который, по сути, ищет пики и впадины в сигнале. Работа над проектом продолжается!
Исходный код (скетч Arduino), необходимые библиотеки, проект корпуса (Рисунок 5) для печати на 3D принтере доступны для скачивания в разделе загрузок.
Рисунок 5. | Простой корпус для прибора, напечатанный на 3D принтере. |
Дополнительно автор добавил версию прибора (nanoPulsePPG) для стандартных плат Arduino и протестировал работу на плате Arduino Nano, но также должно работать на плате Arduino Uno. Таким образом, вы можете экспериментировать с исходным кодом и датчиком.
Загрузки
Материалы по теме
Перевод: Vadim по заказу РадиоЛоцман
Источник