Измеряем частоту сердечных сокращений и SpO2 с помощью Ардуино

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

Что такое SpO2

Перед началом создания нашего устройства мы немного разберемся в том, что такое SpO2? SpO2 - это уровень насыщения крови кислородом.

Нормальный показатель SpO2 у здорового человека: 94 - 99%. На всякий случай - если у вас данный показатель ниже - нужно обратиться к специалисту для постановки диагноза и выяснения причин.

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

Ниже перечислим в каких ситуациях обычно требуется следить за уровнем SpO2:

  • во время операции, при использовании наркоза;
  • при использовании кислородной терапии;
  • при восстановлении после тяжелой операции.

Шаг 1. Комплектующие

Для реализации на основе Ардуино устройства измерения частоты сердечных сокращений и уровня насыщения крови кислородом нам понадобятся совсем небольшое количество комплектующих:

  • Arduino UNO x 1
  • Adafruit OLED 128x32 дисплей x 1
  • Зуммер x 1
  • MAX30102 модуль x 1

Мы собираемся связать MAX30102 (модуль пульсоксиметрии и пульсометра) с платой Arduino UNO, а затем создать проект для измерения BPM с помощью этого модуля, OLED-дисплея и зуммера.

BPM - это «удары в минуту». Для нормального человека во время отдыха они находятся на уровне 65-75, а у спортсменов эта величина быть ниже этого уровня. SpO2, как мы сказали выше, - это уровень насыщения кислородом и для нормального человека он выше 95%.

Давайте посмотрим на наши компоненты для этого урока.

Ардуино Уно

Max30102

Зуммер

Дисплей OLED 128x32

Шаг 2. Схема соединения

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

Шаг 3. Код проекта и библиотеки

Перед началом работы с кодом нам необходимо установить все необходимые библиотеки, которые мы укажем после в скетче для Ардуино. Ниже вы можете скачать библиотеки в zip-архивах, а также скопировать или скачать код проекта.

Библиотеки

Код проекта

Вы можете скачать или скопировать скетч ниже:

#include <Adafruit_GFX.h>        //OLED библиотека
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include "MAX30105.h"           //MAX3010x библиотека
#include "heartRate.h"          //Алгоритм расчета сердечного ритма

MAX30105 particleSensor;

const byte RATE_SIZE = 4; //Увеличьте это для большего усреднения. 4 это хорошо.
byte rates[RATE_SIZE]; //Массив ЧСС
byte rateSpot = 0;
long lastBeat = 0; //Время, когда произошел последний удар
float beatsPerMinute;
int beatAvg;

#define SCREEN_WIDTH 128 // Ширина OLED-дисплея, в пикселях
#define SCREEN_HEIGHT 32 // Высота OLED-дисплея в пикселях
#define OLED_RESET    -1 // Сбросить pin # (или -1, если используется общий сброс Arduino)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Объявление отображаемого имени (дисплей)

static const unsigned char PROGMEM logo2_bmp[] =
{ 0x03, 0xC0, 0xF0, 0x06, 0x71, 0x8C, 0x0C, 0x1B, 0x06, 0x18, 0x0E, 0x02, 0x10, 0x0C, 0x03, 0x10,              //Logo2 и Logo3 - две картинки bmp, которые отображаются на OLED при вызове
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 logo3_bmp[] =
{ 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() {  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Запустите дисплей OLED
  display.display();
  delay(3000);
  // Инициализировать датчик
  particleSensor.begin(Wire, I2C_SPEED_FAST); //Использовать порт I2C по умолчанию, скорость 400 кГц
  particleSensor.setup(); //Настройте датчик с настройками по умолчанию
  particleSensor.setPulseAmplitudeRed(0x0A); //Установите красный светодиод на низкий уровень, чтобы указать, что датчик работает
}

void loop() {
 long irValue = particleSensor.getIR();    //Считывая значение ИК, мы узнаем, есть ли палец на датчике или нет
                                           //Также обнаружение сердцебиения
if(irValue > 7000){                                           //Если обнаружен палец
    display.clearDisplay();                                   //Очистить дисплей
    display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE);       //Нарисуйте первое изображение BMP (маленькое сердце)
    display.setTextSize(2);                                   //Рядом с ним отображается средний BPM, вы можете отобразить BPM, если хотите
    display.setTextColor(WHITE); 
    display.setCursor(50,0);                
    display.println("BPM");             
    display.setCursor(50,18);                
    display.println(beatAvg); 
    display.display();
    
  if (checkForBeat(irValue) == true)                        //Если сердцебиение обнаружено
  {
    display.clearDisplay();                                //Очистить дисплей
    display.drawBitmap(0, 0, logo3_bmp, 32, 32, WHITE);    //Нарисуйте вторую картинку (большее сердце)
    display.setTextSize(2);                                //И все равно отображает средний BPM
    display.setTextColor(WHITE);             
    display.setCursor(50,0);                
    display.println("BPM");             
    display.setCursor(50,18);                
    display.println(beatAvg); 
    display.display();
    tone(3,1000);                                        //И запустить зуммер на 100 мс, вы можете уменьшить, если будет лучше
    delay(100);
    noTone(3);                                          //Отключите зуммер, чтобы получить эффект «бип»
    //Мы почувствовали ритм!
    long delta = millis() - lastBeat;                   //Измерьте продолжительность между двумя ударами
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);           //Расчет BPM

    if (beatsPerMinute < 255 && beatsPerMinute > 20)               //Чтобы вычислить среднее значение, мы храним некоторые значения (4), а затем делаем некоторые математические вычисления для вычисления среднего значения.
    {
      rates[rateSpot++] = (byte)beatsPerMinute; //Сохранить это в массиве
      rateSpot %= RATE_SIZE; 

      //Принять среднее значение
      beatAvg = 0;
      for (byte x = 0 ; x < RATE_SIZE ; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

}
  if (irValue < 7000){       //Если палец не обнаружен, он информирует пользователя и устанавливает среднее значение BPM в 0, или оно будет сохранено для следующего измерения.
     beatAvg=0;
     display.clearDisplay();
     display.setTextSize(1);                    
     display.setTextColor(WHITE);             
     display.setCursor(30,5);                
     display.println("Please Place "); 
     display.setCursor(30,15);
     display.println("your finger ");  
     display.display();
     noTone(3);
     }

}

Шаг 4. Растровые изображения для OLED

Сердце (маленькое), которое вы видите, является растровым изображением, и каждый раз, когда датчик обнаруживает сердцебиение, мы какое-то время переключаемся на другое растровое изображение (большое), и оно создает впечатление сердцебиения вместе со звуковым сигналом зуммера. Вот два растровых изображения, которые мы вызываем в коде:

Чтобы сделать это, найдите изображение (чёрное с белым фоном), которое вы хотите видеть на экране. Не забывайте о размере, мы используем 128x32 px, а изображения меньше - 32x32 px и  24x21 px.

Скачайте LCD Assistant (ниже) и откройте его (установка не требуется):

А вот и ваши "цифры":

Вот так мы вызываем в коде:

display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE);

Что значит:

display.drawBitmap(Starting x pos, Starting y pos, Bitmap name, Width, Height, Color);

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

Шаг 5. Тесты и итоговый результат

Скетч, который мы используем в этом уроке, довольно понятен и является лишь примером из библиотек Sparkfun_MAX3010x. Для кода, который сделан для OLED-дисплея и Зуммера, это модифицированная версия примера «HeartRate» (он просит вас положить палец на датчик).

После того, как вы положите палец, некоторое время сохраняйте спокойствие, пока не начнете слышать "звуки" зуммера, синхронизированные с биением вашего сердца. С ним синхронизируется анимация OLED-экрана и вы сможете прочитать правильный BPM.

На этом всё. Наше устройство готово к работе.

UPD по поводу SpO²

Как написал автор урока - невозможно было загрузить оба кода и показать их на OLED, поэтому SpO² использовался только с последовательным монитором, но можно проверить код в примере библиотеки.

Оба кода одновременно не удалось запустить из-за нехватки места в памяти на UNO. Попытки изменить (сжать) код, не удались. Вы можете попробовать использовать MEGA вместо Uno.

20 февраля 2019 в 16:35 | Обновлено 27 октября 2020 в 13:07 (редакция)
Опубликовано: | Оригинал
Уроки, ,

4 комментария

  1. Alex
    17 октября 2020 в 01:56

    Что значит «На этом всё. Наше устройство готово к работе»? В названии упоминается «и SpO2» (сатурация). Где в коде хоть малейшее упоминание и SpO2? Уберите его из названия и будет «На этом всё». Но главная функция датчика так и останется не задействованной.

    Ответить
    1. Владимир Смирнов
      27 октября 2020 в 04:04

      Здравствуйте, как упоминал автор, невозможно было загрузить оба кода и показать их на OLED, поэтому SpO² использовал только с последовательным монитором, но можно проверить код в примере библиотеки.

      Оба кода одновременно не удалось запустить из-за нехватки места в памяти на UNO. Попытки изменить (сжать) код, не удались. Вы можете попробовать использовать MEGA вместо Uno.

      Ответить
  2. АЛЕКСЕЙ
    26 октября 2020 в 22:32

    Проект классный но до конца не доработан. Прибор SpO2 не определяет.

    Ответить
    1. Владимир Смирнов
      27 октября 2020 в 04:03

      Здравствуйте, как упоминал автор, невозможно было загрузить оба кода и показать их на OLED, поэтому SpO² использовал только с последовательным монитором, но можно проверить код в примере библиотеки.

      Оба кода одновременно не удалось запустить из-за нехватки места в памяти на UNO. Попытки изменить (сжать) код, не удались. Вы можете попробовать использовать MEGA вместо Uno.

      Ответить

Добавить комментарий

Ваш E-mail не будет никому виден. Обязательные поля отмечены *