目標
このミニプロジェクト/チュートリアルの目標は、最小限のコンポーネントで非常にシンプルな HR モニターとスクロールする ECG ディスプレイを作成することです。
要件:
クイック背景
心臓の筋肉は電気信号を生成します。それらの信号の一部は皮膚の表面で検出できます。
表面電極を使用してこれらの信号を拾うことができます。問題は、皮膚上の電気信号はこれだけではないということです。ありがたいことに、私たちが確認したい信号のほとんどは 1 ~ 40Hz 付近に限定されています。
プロセス
電極として機能する 1/4 インチ ケーブルを取り出し、心臓付近の皮膚に差し込みます。次に、USB オーディオ インターフェイスを使用してアナログ信号を増幅し、デジタルに変換します。最後にPythonでフィルタリングして表示します。
ステップ
ステップ 1: 1/4 インチ ケーブルには、スリーブと先端の 2 つの部分があります。両方の部分が皮膚に接触する必要があります。スリーブを手で持ち、先端に押し当てるだけです。胸部の左側/胸郭の上部 (ケーブルによってはさらに多くのチャンネルがある場合がありますが、すべてのチャンネルが接続されていることを確認してから開始してください)。
ステップ 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.
メモ
ケーブルを動かさないでください。正確な心拍数を取得するには、移動後数秒待つ必要がある場合があります。ガーミン ウォッチと照合して確認したところ、一貫して同様の値が返されました。
出力
免責事項
技術的には
あなたの体を回路の一部にしていることを覚えておいてください。ケーブルは、壁の電源コンセントに接続されているコンピュータに接続されているインターフェイスに接続されています...これはご自身の責任で試してください。私は専門家ではありません。ただいろいろなものをいじって楽しむのが好きなので、共有したいと思っています。
次のステップ
この方法は、ECG 信号のさまざまな部分をすべて明確に表示するにはあまりうまく機能しません。電極はかなり擦り傷があり、最低限のフィルタリングを行いました。
ここから、ソフトウェア側をさらに深く掘り下げて追加のフィルターを試したり、実際の回路を作成して実際の電極を使用したりできます。この種の電極の袋はアマゾンでかなり安いです (接着剤が面倒なので注意してください)。回路については、いくつかの異なる構成を試しましたが、私にとって最も簡単で最もうまく機能したのは、JFET オペアンプを使用した単純な計装アンプ回路でした (ブレッドボード上に組み立てられました)。 3 つの電極。どこに配置するかは図を参照してください。 ADC にオーディオ インターフェイスを使用する場合、ここのコードは 3 電極ブレッドボードのセットアップで動作するはずです (ゲインの調整が必要な場合があります)
なぜ
このミニプロジェクトのインスピレーションは、ギター ケーブルを持ちながら DAW の EQ プラグインをいじっているときに生まれました。
以上がシンプルなDIY HRモニターECGディスプレイの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。