[Перевод] Пульсоксиметр своими руками
Во время самоизоляции я попытался сделать пульсоксиметр из того, что уже есть у меня в закромах
Я бы хотел измерить уровень насыщения крови кислородом в процентах в моей крови при помощи самостоятельно изготовленного пульсоксиметра. Я не эксперт в медицина, поэтому данный проект не имеет диагностической ценности. Это просто образовательный проект, подходящий для изучения принципов работы прибора.
Компоненты:
- Arduino Uno.
- Датчик KY-039 — его можно собрать из двух резисторов и фотодиода.
- Красный светодиод.
- Резистор на 330 Ом — 2 шт.
- Дисплей LCD 16×2 I2C.
Я разбил инструкцию на 5 частей:
- Насыщение крови кислородом и COVID-19.
- Как работает измеритель пульса.
- Измерение пульса через обнаружение пиков сигнала с датчика.
- Изменение датчика пульса KY-039 для измерения насыщения крови кислородом.
- Как измеряется насыщение.
Подробности
1. Насыщение крови кислородом и COVID-19
В данном невероятном периоде нашей жизни мы многое узнали о вирусах, лёгких, хирургических масках и о том, как правильно мыть руки. Все читали о таких симптомах, как кашель, повышение температуры и затруднение дыхания. Мы также знаем, что один из способов измерить затруднения дыхания — это узнать количество кислорода в крови.
Это можно сделать косвенным методом при помощи такого медицинского устройства, как пульсоксиметр. Вы, наверное, уже видели его — это неинвазивное устройство, цепляющееся на палец, за работу которого отвечают мигающие огоньки.
Его даже можно купить на Amazon:
Если у вас всё в порядке со здоровьем, насыщение кислородом вашей крови составляет 95% или выше. Когда оно опускается ниже 90%, вы кашляете и у вас повышается температура — это проблема.
Так давайте же попробуем собрать пульсоксиметр!
2. Как работает измеритель пульса
Перед измерением насыщения крови кислородом нам нужно понять, как работает датчик пульса. У меня есть датчик KY-0039 с инфракрасным светодиодом и фотодиодом (вероятно, OP550A или LTR-301).
To measure oxygen saturation, we first need to learn how an heartbeat sensor work. I’ve got an heartbeat sensor named KY-0039 which is made with an infrared led and a photodiode. (it should be this OP550A or LTR-301)
Я нашёл его в наборе из нескольких датчиков:
Как видно по схеме, это просто инфракрасный светодиод, светящий на фотодиод. У него есть ещё два резистора, для защиты светодиода и получения слабого сигнала с датчика. Палец помещается между фотодиодом и светодиодом, как на фото:
Излучаемый инфракрасным светодиодом свет частично поглощается ногтем, кожей и остальными частями пальца. Но поглощение не остаётся неизменным, поскольку оно меняется вместе с потоком крови, идущей по венам. Когда сокращается сердце, оно проталкивает кровь по венам, в результате чего меняется поглощение света. С контакта S датчика KY-039 можно снимать данные о токе, генерируемом светом, поглощённым фотодиодом.
3. Измерение пульса через обнаружение пиков сигнала с датчика
Качественно считать значение изменяющегося сигнала — задача непростая. В данном случае сигнал слабый, а шума много, поэтому для того, чтобы найти какие-то осмысленные значения, нам придётся провести определённые вычисления.
Выражаю благодарность Йохану Ха за его пост с объяснениями того, как строить среднее значение для небольшой выборки данных, а также удалять шум настольной лампы (содержащийся в её свете). Однако я обнаружил, что мой датчик хорошо считывает сигнал, в условиях хорошей освещённости, а если накрыть его тёмной тряпочкой, то шума становится больше.
В своём коде Ха создаёт массив, где хранит значения, а потом уменьшает их, вычисляя среднее на основе X последних значений, прочитанных с датчика. Он также описывает способ найти тот момент, когда сигнал начинает расти (когда N подряд значений сигнала превышают опорное), чтобы искать пики.
При помощи программы SerialPlot мне удалось лучше подобрать необходимое количество измерений, которое позволит нам корректно определить N (константа rise_threshold в коде). На примере графика ниже — если задать это число больше 7, то некоторые удары пульса программа пропустит и не заметит:
Когда мы научились находить пики, мы можем их подсчитать — или подсчитать время между пиками, и так определить количество сердечных сокращений в минуту.
4. Взламываем датчик пульса KY-039 для измерения насыщения крови кислородом
Наша кровь поглощает свет по-разному в зависимости от длины его волны. Красный свет лучше поглощает кровь, содержащая больше кислорода, поэтому мы можем сравнить измерения и найти процентное содержание кислорода в крови. Это значение называется Sp02%.
Sp02% полностью называется «насыщение кислородом периферийных капилляров», и обозначает примерное содержание кислорода в крови. Точнее, это процентное соотношение насыщенного кислородом гемоглобина по сравнению с общим количеством гемоглобина в крови.
У нашего датчика KY-039 есть только один инфракрасный (950 нм) светодиод. Нам нужно добавить к схеме красный светодиод (600 нм), подсоединить его к контакту Arduino, а кроме того, нам надо отсоединить инфракрасный светодиод от Vcc и подключить его к ещё одному контакту Arduino. Я также использовал два резистора на 330 Ом для защиты светодиода.
Схема изменённого датчика:
Теперь мы можем включать инфракрасный светодиод, считывать показания с контакта S датчика KY-039, а потом выключать инфракрасный светодиод и включать красный светодиод, и снова считывать показания с контакта S.
Что получилось:
Если мы построим два графика, мы увидим, что значения, полученные с ИД всегда меньше, чем значения красного светодиода.
5. Как измеряется насыщение
Насыщение измеряется как функция параметра R, который определяется через максимум и минимум двух сигналов:
Rnum = (REDmax - REDmin) / REDmin;
Rden = (IRmax - IRmin) / IRmin;
R = Rnum / Rden;
Уровень насыщения кислородом (SpO2%) — это функция от R (подробности я нашёл в данной работе одного студента из Миланского политехнического).
У каждого инструмента функция от R получается своей, и чтобы найти правильную функцию, соотносящую R и SpO2%, новый пульсоксиметр нужно откалибровать по показаниям другого пульсоксиметра.
Как указано в 3-м разделе, подсчитать количество пиков довольно легко. Но нам кроме этого нужно ещё найти максимумы и минимумы двух кривых (для красного светодиода и для инфракрасного светодиода).
Для этого нам нужно оценить «период» сердцебиений (длительность каждого из них) и поделить его на скорость считывания показаний (в моём коде это 40 мс — 20 для красного светодиода и 20 для инфракрасного светодиода). Период сердцебиения — это время между двумя пиками кривых сигнала.
Теперь мы можем проанализировать N последних запросов (N = период / 40) и найти REDmax, REDmin, IRmax и IRmin. Затем через max и min мы можем вычислить R. R, N и период вычисляются после каждого сокращения сердца.
Как откалибровать самодельный пульсоксиметр, чтобы перейти от R к SpO2%?
Функцию, связывающую R с SpO2%, можно аппроксимировать прямой (SpO2 = K * R + M). Нам понадобятся две точки, чтобы определить параметры K и M, определяющие уравнение прямой — то есть, две пары значений SpO2% и R. Единственный способ найти их — использовать другой пульсоксиметр и прочесть значения с него.
Во время калибровки необходимо быть внимательным — на наш самодельный пульсоксиметр освещение, поэтому уровень освещения нужно поддерживать одинаковым во всех случаях. Я пробовал закрывать его тёмной тканью, однако при отсутствии света сигнал получается слишком слабым и его сложно отличить от шума.
Рекомендую делать много измерений. Для получения двух разных точек на графике рекомендую понижать значения SpO2%, задерживая дыхание или выдыхая и вдыхая их пластикового пакета.
Найдя две хороших точки, вам останется решить уравнение 2-го порядка. Так можно будет найти параметры K и M.
Я в итоге решил добавить ещё и дисплей, чтобы сразу видеть все показания, а также добавил в код массив измерений. Я вывожу на дисплей измерения, только когда нахожу не менее 5 значений подряд, не сильно отличающихся друг от друга. Таким образом я избавляюсь от шума, вызванного недостаточно качественными компонентами или освещением. Однако всё равно измерения R получаются не очень стабильными, и коэффициент насыщения сильно скачет. Думаю, результаты были бы лучше, если бы я смог усилить сигнал.
Скачать код для Arduino
Чтобы не зависеть от окружающего освещения, я добавил в схему ещё один, белый светодиод, и стал считывать показания, закрывая всё тёмной тканью. Так получается гораздо лучше, чем просто прикрывать всё тканью — идёт сильный сигнал, не зависящий от освещения в помещении.