Как стать автором
Обновить

Arduino + max30102 + ЦОС = SpO2

Время на прочтение4 мин
Количество просмотров15K

Arduino + max30102 + ЦОС = SpO2

Однажды увидев на али оксиметр, стало интересно как же он устроен. А разобравшись, удивился его простоте и решил его повторить.

Немного разобравшись, оказалось все не так сложно и пришел в результате к следующим модулям:

  • готовый измерительный модуль на max30102 (сердце измерения оксигинации). Модуль конечно может быть любым, главное чтобы на основе max30102.

  • мозги для управления выше указанным, модуль на stm32f103.

  • и то куда все это выводить led дисплей на i2c. 

Ну и конечно нашелся готовый проект какого-то китайца: https://github.com/Jasoji/stm32-max30102 со своими ошибками и проблемами, но об этом всем дальше.

Исходник моего проекта, сделанного в Eclipse.

Опустим схемную часть, там отсутствует аналоговая электроника и все довольно таки прозрачно.

Как ни странно проект заработал сразу, будучи собранным и залитым в модуль. Но вот стабильность его работы никак не устроила, постоянные срывы измерения и значения в пределах 60-80, необходимость держать палец на весу и желательно им не дергать. В общем сплошное расстройство. Пробовал конечно и другие библиотеки для расчета сатурации, но и там ничуть не лучше результат измерения.

Исследование кода показало почему были такие рваные и нестабильные показания. В файле max30102.c в функции max30102_cal, есть такие строчки:

if (R >= 0.36 && R < 0.66)

   spo2 = (uint8_t)(107 - 20 * R);

else if (R >= 0.66 && R < 1)

   spo2 = (uint8_t)(129.64 - 54 * R);

Где указаны волшебные коэффициенты, по которым и определяется правильность вычисленных показаний. А показания для этой части вытаскиваются напрямую из макса в потоковом режиме, и если в текущем цикле показания не прошли этот фильтр... то и не будут они использованы. Т.е. пока дергается палец, показания через этот фильтр не пройдут. А достаточно всего лишь малейшего движения мышц.

Самое печальное, что эти коэффициенты находятся в лабораторных условиях для конкретных сборок (имеется ввиду max30102 и им подобные). Короче их лучше не трогать и эти коэффициенты описаны в документации на эту микруху, а еще там описана методика и принцип измерения.

А единственный фильтр который был, это ограничение АЦП в max30102 шестью битами. Это довольно грубый фильтр в результате которого с выхода идет почти синус, ну и график для отрисовки соответствующий. А хотелось бы отображения нормального сердцебиения.

Вторая проблема это перепутанные местами значения красного и инфракрасного.

Поэтому приступим к изменениям:

  • изменение красного и инфракрасного

  • увеличение настроек АЦП (хочется видеть сердцебиение и не синус)

  • создание цифрового фильтра для поиска экстремумов и потокового расчета сатурации

На первой очереди путаница с показаниями АЦП красного и инфракрасного фотодиода. Как показало исследование вопроса, уровень отраженного сигнала с ИК диода будет выше чем от красного и значения АЦП соответственно выше, поэтому код для исправления следующий:

if(s.red > s.iRed) {	// Уровень с ик диода выше чем с красного<o:p>

        sampleBuff[0].red = s.iRed;

    	    sampleBuff[0].iRed = s.red;

    } else {

    	    sampleBuff[0].red = s.red;

    	    sampleBuff[0].iRed = s.iRed;

}

В общем этот код выставляет красный и инфракрасный правильным образом.

Дальнейшая проблема всплыла когда увеличил разрядность АЦП, оказалось что имеющийся код не справляется с поиском экстремумов для расчета сатурации.

Это то что я увидел когда вытащил показания АЦП наружу. Внутри-процессорная отладка наше все).

Если значения ИК будут в районе 108к, то значение красного в районе 101к. И это среднее значение еще и плавает в пределах пары своих амплитуд. И в этот момент я замер дабы не шевелить пальцем, по крайней мере мне так казалось. Печально конечно что халявы не вышло и придется городить ЦОС. И это только первая проблема, вторая проблема ниже:

Видите эта подставка с проседанием по амплитуде, это так работает сердце и из-за этого не так просто найти экстремум.

А теперь приступим к решению проблем.

Начнем с формулы. 

SpO2 = aR2+bR+c 

Где  

R = (ACred/DCred) / (ACired/DCired) 

a,b,c - калибровочные коэффициенты (именно они находятся в лабораторных условиях, для конкретной измерительной схемы). Для max30102 значения можно найти в документации на эту микруху.

ACred - размах одного периода от максимума до минимума в относительных единицах.

DCred - постоянная составляющая сигнала. Я брал среднеквадратичное значение АЦП за последние несколько секунд.

т.е. выходит что сатурация измеряется по одному сердцебиению.

Далее необходимо найти экстремумы.

В простейшем случае синусоподобного сигнала это не так сложно, но т.к. судя по первой картинке у нас сигнал прыгает не только по амплитуде, но и в средней величине. А это значит что необходимо знать среднюю величину сигнала. Вот тут и ищем средне квадратичный уровень сигнала с АЦП, от которого в дальнейшем ищем максимум и минимум.

Но у каждого импульса есть небольшая просадка амплитуды и она каждый раз разная, что тоже надо учитывать.

Поэтому для измерения уровня оксигинации есть два подхода:

1. Выставить минимальное разрешение АЦП, что автоматически отфильтрует эту просадку. Но тут при выводе рисунка колебания, сердцебиение будет больше похоже на синус.

2.Если же увеличить разрешение АЦП, то придется искуственно снижать разрешение для получения синуса и далнейшего поиска экстремума.

Нас интересует второй подход. Оригинальный сигнал с АЦП выкидываем сразу на дисплей (там сердцебиение в своем оригинале).

  • Дальше сигнал пропускам через фильтр и получаем почти синус.

  • Ищем местоположение экстремума на синусе.

  • В том же месте где был найден экстремум в синусе, ищем тот же экстремум но в оригинальном сигнале.

  • Найденные значения в формулу расчета.

Вот собственно и все... дальше остается подставить в формулу и вывести график на экран.

Что еще можно сказать про этот проект, сатурация меряется довольно точно. И легко можно понять что и измерения правильны, по гармоничности колебаний на графике. И если задержать дыхание и терпеть до последнего, то можно видеть просадку сатурации с 99% до 95%, что в принципе является нормой.

Теги:
Хабы:
Всего голосов 12: ↑7 и ↓5+6
Комментарии25

Публикации

Истории

Работа

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань