цифровая электроника
вычислительная техника
встраиваемые системы

 



Пульсоксиметр своими руками на основе Arduino и MAX30102

Автор: Mike(admin) от 23-09-2020, 07:55

Если вы недавно посетили врача, скорее всего, медсестра проверила ваши основные жизненно важные функции. Это вес, рост, артериальное давление, а также частота сердечных сокращений (ЧСС) и сатурация кислорода в периферической крови (SpO2). Возможно, последние два параметра были получены с помощью светящегося красным электронным датчиком, прикрепляемым к пальцу, который отображал соответствующие числа на крошечном экране за считанные минуты. Этот датчик называется пульсоксиметром, и вы можете сделать такой самостоятельно на основе микросхемы MAX30102.


Пульсоксиметр своими руками на основе Arduino и MAX30102

Пульсоксиметры могут приблизительно определять частоту сердечных сокращений, анализируя реакцию временного ряда отраженного красного и инфракрасного света. Здесь мы используем MAX30102 и Arduino для моздания такого устройства.


Пульсоксиметр MAX30102 – это недорогой датчик, совместимый с Arduino, который позволяет рассчитывать частоту сердечных сокращений. MAX30102 использует двухпроводную связь I2C для взаимодействия с платой Arduino. Мы используем порты I2C на выводах A4/A5 на плате Arduino. Схема подключения показана далее.


Пульсоксиметр своими руками на основе Arduino и MAX30102

Для работы с датчиком нужна библиотека его функций. Sparkfun предоставляет библиотеку, которая обеспечивает связь между Arduino и MAX30102. В среде Arduino IDE перейдите в меню «Управление библиотеками» и введите «max30» в строку поиска. Загрузите библиотеку «Sparkfun MAX3010x Pulse and Proximity Sensor Library».


Пульсоксиметр своими руками на основе Arduino и MAX30102

Далее представлен простой код программы Arduino. Он производит выборку данных от MAX30102 с частотой 400 Гц и выводит их через последовательный порт. При 400 Гц и последовательной скорости передачи 115200 компьютер способен без проблем читать каждую точку данных.



#include <Wire.h>
#include "MAX30105.h"

MAX30105 particleSensor;

void setup()
{
  Serial.begin(115200);
  while(!Serial);
  delay(100);
  Serial.println("");
  Serial.println("MAX30102");
  Serial.println("");
  delay(100);

  if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false) 
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
    while (1);
  }

  byte ledBrightness = 70;
  byte sampleAverage = 1;
  byte ledMode = 2;
  int sampleRate = 400; 
  int pulseWidth = 69; 
  int adcRange = 16384;

  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
}

void loop() {
  particleSensor.check(); 
  while (particleSensor.available()) {
      Serial.print(particleSensor.getFIFOIR());
      Serial.print(",");
      Serial.println(particleSensor.getFIFORed());
      particleSensor.nextSample();      
  }
}

Если вплотную к MAX30102 поднести палец, вывод плоттера последовательного порта Arduino должен выглядеть следующим образом.


Пульсоксиметр своими руками на основе Arduino и MAX30102

Нам не нужно беспокоиться о сложности отследить форму каждого графика, поскольку мы обработаем данные в Python и полностью проанализируем данные красного и ИК-диапазона от датчика MAX30102. В следующем разделе мы будем считывать данные 400 Гц в реальном времени в Python и выводить их в удобном виде. В качестве приемника данных с обработкой на Python можно использовать Raspberry Pi.


В приведенном выше коде Arduino единственное изменение, которое нам нужно сделать, это добавить функцию «micros()», чтобы прикрепить временную метку к показаниям данных значений красного и ИК-отражения. Обновленный код Arduino выглядит следующим образом.



#include <Wire.h>
#include "MAX30105.h"

MAX30105 particleSensor; 

void setup()
{
  Serial.begin(115200);
  while(!Serial); 
  delay(100);
  Serial.println("");
  Serial.println("MAX30102");
  delay(100);

  if (particleSensor.begin(Wire, I2C_SPEED_FAST) == false)
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
    while (1);
  }

  byte ledBrightness = 70;
  byte sampleAverage = 1;
  byte ledMode = 2;
  int sampleRate = 400;
  int pulseWidth = 69;
  int adcRange = 16384;

  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); 
}

void loop() {
  particleSensor.check(); 
  while (particleSensor.available()) {
      Serial.print(micros());
      Serial.print(",");
      Serial.print(particleSensor.getFIFOIR());
      Serial.print(",");
      Serial.println(particleSensor.getFIFORed());
      particleSensor.nextSample();      
  }
}

Алгоритм высокоскоростного последовательного считывания для Python для считывания значений последовательного вывода Arduino показан далее. Код Python получит данные и сохранит их в файл .csv для последующего анализа. Причина, по которой мы сохраняем их сразу, заключается в том, что данные поступают с такой высокой скоростью, что мы хотим минимизировать объем обработки, выполняемой между последовательными сборами.



import serial,time,csv,os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

plt.style.use('ggplot')

ser = serial.Serial('/dev/ttyUSB0',
                    baudrate=115200)
datafile_name = 'test_data.csv'
if os.path.isfile(datafile_name):
    os.remove(datafile_name)

all_data = []
start_word = False
while True:
    try:        
        curr_line = ser.readline()
        if start_word == False:
            if curr_line[0:-2]==b'MAX30102':
                start_word = True
                print("Program Start")
                continue
            else:
                continue
        all_data.append(curr_line)
    except KeyboardInterrupt:
        break   
print("Exited Loop")

t_vec,ir_vec,red_vec = [],[],[]
ir_prev,red_prev = 0.0,0.0
for ii in range(3,len(all_data)):
    try:
        curr_data = (all_data[ii][0:-2]).decode("utf-8").split(',')
    except:
        continue
    
    if len(curr_data)==3:

        if abs((float(curr_data[1])-ir_prev)/float(curr_data[1]))>1.01 or\
        abs((float(curr_data[2])-red_prev)/float(curr_data[2]))>1.01:
            continue
        
        t_vec.append(float(curr_data[0])/1000000.0)
        ir_vec.append(float(curr_data[1]))
        red_vec.append(float(curr_data[2]))
        ir_prev = float(curr_data[1])
        red_prev = float(curr_data[2])

print('Sample Rate: {0:2.1f}Hz'.format(1.0/np.mean(np.abs(np.diff(t_vec)))))

with open(datafile_name,'a') as f:
    writer = csv.writer(f,delimiter=',')
    for t,x,y in zip(t_vec,ir_vec,red_vec):
        writer.writerow([t,x,y])

fig = plt.figure(figsize=(12,8))
ax1 = fig.add_subplot(111)
ax1.set_xlabel('Time [s]',fontsize=24)
ax1.set_ylabel('IR Amplitude',fontsize=24,color='#CE445D',labelpad=10)
ax1.tick_params(axis='both',which='major',labelsize=16)
plt1 = ax1.plot(t_vec,ir_vec,label='IR',color='#CE445D',linewidth=4)
ax1_2 = plt.twinx()
ax1_2.grid('off')
ax1_2.set_ylabel('Red Amplitude',fontsize=24,color='#37A490',labelpad=10)
ax1_2.tick_params(axis='y',which='major',labelsize=16)
plt2 = ax1_2.plot(t_vec,red_vec,label='Red',color='#37A490',linewidth=4)
lns = plt1+plt2
labels = [l.get_label() for l in lns]
ax1_2.legend(lns,labels,fontsize=16)
plt.xlim([t_vec[0],t_vec[-1]])
plt.tight_layout(pad=1.2)
plt.savefig('max30102_python_example.png',dpi=300,facecolor=[252/255,252/255,252/255])
plt.show()

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


Пульсоксиметр своими руками на основе Arduino и MAX30102



© digitrode.ru


Теги: пульсоксиметр, Arduino, MAX30102




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

Комментарии:

Оставить комментарий