Цель
Цель этого мини-проекта/учебника — создать очень простой монитор ЧСС и прокручиваемый дисплей ЭКГ с минимальным количеством компонентов.
Требования:
Быстрая справка
Мышцы сердца создают электрические сигналы. Некоторые из этих сигналов можно обнаружить на поверхности кожи.
Мы можем улавливать эти сигналы с помощью поверхностных электродов. Проблема в том, что это не единственные электрические сигналы на коже. К счастью, большинство сигналов, которые мы хотим видеть, ограничены диапазоном 1–40 Гц.
Процесс
Мы возьмем кабель диаметром 1/4 дюйма, который будет действовать как электрод, и воткнем его в кожу в районе сердца. Затем мы воспользуемся аудиоинтерфейсом USB для усиления и преобразования аналогового сигнала в цифровой. Наконец, мы фильтруем и отображаем в Python
.Шаги
Шаг 1: Кабель диаметром 1/4 дюйма состоит из двух частей: втулки и наконечника. Обе части должны соприкасаться с кожей — просто возьмите втулку рукой и прижмите ее к левую сторону груди/верхнюю часть грудной клетки (некоторые кабели могут иметь больше каналов, просто убедитесь, что все они имеют контакт, чтобы начать). Отрегулируйте усиление аудиоинтерфейса (я поворачиваю свой полностью вверх).
Шаг 2: Запустите приведенный ниже код. Убедитесь, что строка input_device_index указывает на ваш аудиоинтерфейс. Что мы делаем, так это берем фрагменты входящего звука, преобразуем их в частотную область с помощью FFT, устанавливаем все ненужные частоты на 0, а затем преобразуем обратно во временную область. Затем мы находим пики для расчета ЧСС, а затем строим график с прокруткой.
import numpy as np import pyaudio as pa import struct import matplotlib.pyplot as plt from scipy.signal import decimate, find_peaks CHUNK = 4410 #.1 second FORMAT = pa.paInt16 CHANNELS = 1 RATE = 44100 # in Hz fstep = RATE/CHUNK p = pa.PyAudio() values = [] dsf=44 #down sample factor rds=RATE/dsf #down sampled rate stream = p.open( format = FORMAT, channels = CHANNELS, rate = RATE, input_device_index=3, #adjust based on input input=True, frames_per_buffer=CHUNK ) #set up graph fig,ax = plt.subplots(1) x = np.arange(0,2*CHUNK,2) line, = ax.plot(x, np.random.rand(CHUNK)) ax.set_ylim(-100,100) ax.set_xlim(0,2500) text = ax.text(0.05, 0.95, str(0), transform=ax.transAxes, fontsize=14, verticalalignment='top') fig.show() def getFiltered(x,hp=1,lp=41): #this sets the unneeded freqs to 0 fft=np.fft.fft(x) hptrim=len(fft)/RATE*hp lptrim=len(fft)/RATE*lp fft[int(lptrim):-int(lptrim)]=0 fft[0:int(hptrim)]=0 return np.real(np.fft.ifft(fft)) def getHR(x): pdis = int(0.6 * rds) #minimum distance between peaks. stops rapid triggering. also caps max hr, so adjust peaks, _ = find_peaks(x, distance=pdis, height=0.1) intervals = np.diff(peaks)/rds # in seconds hr = 60 / intervals # in BPM return peaks,round(np.mean(hr),0) #peaks,avg hr while 1: data = stream.read(CHUNK) dataInt = struct.unpack(str(CHUNK) 'h', data) filtered=getFiltered(dataInt) #filter (working with full chunk) dsed=decimate(filtered, 44) #down sample (turns chunk into ds chunk) values=np.concatenate((values,dsed)) #puts the chunks into an array peaks,hr = getHR(values*-1) # gets the peaks and determins avg HR. text.set_text(str(hr)) line.set_xdata(np.arange(len(values))) line.set_ydata(values*-10) #the negative is bc it comes in upside down with my set up. the *10 is just for fun ax.set_xlim(max(0,len(values)-2500),len(values)) #keep the graph scrolling vlines = ax.vlines(peaks,ymin=-100,ymax=100,colors='red', linestyles='dashed') # pop some lines at the peaks fig.canvas.draw() fig.canvas.flush_events() vlines.remove() if len(values)>10000: #keeps the array managably sized, and graph scrolling pretty values=values[5000:] #5 seconds @ ~1000 sr.
Примечания
Держите трос неподвижно — возможно, вам придется подождать несколько секунд после движения, чтобы получить точные данные о частоте пульса. Я сверил их со своими часами Garmin, и они постоянно показывали схожие значения.
Выход
Отказ от ответственности
Имейте в виду, что технически вы делаете ваше тело частью контура. Кабель подключен к интерфейсу, который подключен к компьютеру, который подключен к сетевой розетке... Попробуйте это на свой страх и риск. Я не эксперт — мне просто нравится играться с вещами, и я хотел поделиться.
Дальнейшие шаги
Этот метод на самом деле не очень хорошо работает для четкого просмотра всех частей сигнала ЭКГ. Электрод сильно потерт, и я применил минимум фильтрации.
Он также не очень хорошо справляется с обнаружением более мелких сигналов, таких как ЭМГ.
Здесь вы можете копнуть глубже в программном обеспечении и поиграть с дополнительными фильтрами или создать реальную схему и использовать настоящие электроды. Пакет с электродами для подобных вещей на Amazon стоит довольно дешево (будьте осторожны, клей раздражает). Что касается схемы, я попробовал несколько различных конфигураций: самой простой/подходящей для меня оказалась простая схема инструментального усилителя с использованием операционного усилителя JFET (собранная на макетной плате). 3 электрода, просто посмотрите на схему, где их разместить. Если вы используете аудиоинтерфейс для АЦП, приведенный здесь код должен работать с настройкой трехэлектродного макета (возможно, придется отрегулировать усиление)
Почему
Вдохновение для этого мини-проекта пришло во время игры с плагином эквалайзера в DAW, держа в руках гитарный кабель.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3