[Отладка, Программирование микроконтроллеров, Прототипирование] Arduino + max30102 + ЦОС = SpO2
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Arduino + max30102 + ЦОС = SpO2Однажды увидев на али оксиметр, стало интересно как же он устроен, а разобравшись, удивился его простоте и решил его повторить.Немного разобравшись, оказалось все не так сложно и пришел в результате к следующим модулям:
- готовый измерительный модуль на max30102 (сердце измерения оксигинации). Модуль конечно может быть любым, главное чтобы на основе max30102.- мозги для управления выше указанным, модуль на stm32f103. - и то куда все это выводить led дисплей на i2c. Ну и конечно нашелся готовый проект какого то китайца: https://github.com/Jasoji/stm32-max30102 со своими ошибками и проблемами, но об этом всем дальше.Исходник моего проекта сделанного в Eclipse: https://Tranider@bitbucket.org/Tranider/stm32_oxymeterОпустим схемную часть, там отсутствует аналоговая электроника и все довольно таки прозрачно.Как ни странно проект заработал сразу, будучи собранным и залитым в модуль. Но вот стабильность его работы ни как не устроила, постоянные срывы измерения и значения в пределах 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%, что в принципе является нормой.
===========
Источник:
habr.com
===========
Похожие новости:
- [C++, C, Программирование микроконтроллеров, Компьютерное железо] Размещение кучи FreeRTOS в разделе CCMRAM для STM32
- [Программирование микроконтроллеров, DIY или Сделай сам] FDCAN на STM32
- [Разработка систем связи, Программирование микроконтроллеров] Составное устройство USB на STM32. Часть 4: Два-в-одном
- [Тестирование IT-систем, Анализ и проектирование систем, Отладка] Язык моделирования Alloy и приключения с параллельными запросами к базе данных (перевод)
- [Отладка, Программирование микроконтроллеров] Полноценная GDB отладка через USB на плате BluePill (STM32F103С8T6)
- [Python, Программирование, Программирование микроконтроллеров] Маленькие Python для маленьких embedded-программистов: CircuitPython и MicroPython для MeowBit
- [Разработка веб-сайтов, Программирование, Анализ и проектирование систем, SQL, Прототипирование] Применяем NOCODE и LOWCODE для вычислений
- [Разработка систем связи, Программирование микроконтроллеров] Составное устройство USB на STM32. Часть 3: Звуковое устройство отдельно, виртуальный СОМ-порт отдельно
- [Open source, Программирование микроконтроллеров, DIY или Сделай сам] Поговорим с мышами? Или Soft USB HOST на Esp32
- [Отладка, Микросервисы, Serverless] Руководство по отладке бессерверных приложений (перевод)
Теги для поиска: #_otladka (Отладка), #_programmirovanie_mikrokontrollerov (Программирование микроконтроллеров), #_prototipirovanie (Прототипирование), #_oksimetr (Оксиметр), #_saturatsija (Сатурация), #_max30102, #_otladka (
Отладка
), #_programmirovanie_mikrokontrollerov (
Программирование микроконтроллеров
), #_prototipirovanie (
Прототипирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:05
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Arduino + max30102 + ЦОС = SpO2Однажды увидев на али оксиметр, стало интересно как же он устроен, а разобравшись, удивился его простоте и решил его повторить.Немного разобравшись, оказалось все не так сложно и пришел в результате к следующим модулям: - готовый измерительный модуль на max30102 (сердце измерения оксигинации). Модуль конечно может быть любым, главное чтобы на основе max30102.- мозги для управления выше указанным, модуль на stm32f103. - и то куда все это выводить led дисплей на i2c. Ну и конечно нашелся готовый проект какого то китайца: https://github.com/Jasoji/stm32-max30102 со своими ошибками и проблемами, но об этом всем дальше.Исходник моего проекта сделанного в Eclipse: https://Tranider@bitbucket.org/Tranider/stm32_oxymeterОпустим схемную часть, там отсутствует аналоговая электроника и все довольно таки прозрачно.Как ни странно проект заработал сразу, будучи собранным и залитым в модуль. Но вот стабильность его работы ни как не устроила, постоянные срывы измерения и значения в пределах 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.Если же увеличить разрешение ацп, то придется искуственно снижать разрешение для получения синуса и далнейшего поиска экстремума.Нас интересует второй подход. Оригинальный сигнал с АЦП выкидываем сразу на дисплей (там сердцебиение в своем оригинале).
=========== Источник: habr.com =========== Похожие новости:
Отладка ), #_programmirovanie_mikrokontrollerov ( Программирование микроконтроллеров ), #_prototipirovanie ( Прототипирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:05
Часовой пояс: UTC + 5