„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Einfacher DIY-Herzfrequenzmonitor + EKG-Anzeige

Einfacher DIY-Herzfrequenzmonitor + EKG-Anzeige

Veröffentlicht am 09.11.2024
Durchsuche:491

Ziel
Das Ziel dieses Miniprojekts/Tutorials ist es, mit minimalen Komponenten einen supereinfachen HR-Monitor und eine scrollende EKG-Anzeige zu erstellen.

Anforderungen:

  • Python
  • Audio-Interface
  • 1/4"-Kabel/Gitarrenkabel/Instrumentenkabel (es muss nur über das Audio-Interface in den Computer gelangen)

Kurzhintergrund

Die Muskeln im Herzen erzeugen elektrische Signale. Einige dieser Signale sind auf der Hautoberfläche erkennbar.

Wir können diese Signale mithilfe von Oberflächenelektroden erfassen. Das Problem ist, dass dies nicht die einzigen elektrischen Signale auf der Haut sind. Glücklicherweise sind die meisten Signale, die wir sehen möchten, auf etwa 1-40 Hz beschränkt.

Verfahren

Wir nehmen unser 1/4-Zoll-Kabel, das als unsere Elektrode dient, und stechen es in der Nähe des Herzens in unsere Haut. Anschließend verwenden wir die USB-Audioschnittstelle, um das analoge Signal zu verstärken und in ein digitales umzuwandeln . Schließlich filtern und zeigen wir in Python an.

Schritte

Schritt 1: Ein 1/4-Zoll-Kabel besteht aus zwei Teilen, der Hülle und der Spitze. Beide Teile müssen Kontakt mit Ihrer Haut haben – halten Sie einfach die Hülle mit der Hand fest und drücken Sie sie gegen die linke Seite Ihrer Brust/oberer Brustkorb (einige Kabel haben möglicherweise mehr Kanäle, stellen Sie einfach sicher, dass sie alle Kontakt haben, um zu starten. Passen Sie die Verstärkung am Audio-Interface an (ich drehe meines ganz nach oben).

Simple DIY HR Monitor ECG Display

Schritt 2: Führen Sie den folgenden Code aus. Stellen Sie sicher, dass die Zeile „input_device_index“ auf Ihr Audio-Interface zeigt. Wir nehmen Teile des eingehenden Audiomaterials, konvertieren es mit fft in den Frequenzbereich, setzen alle unnötigen Frequenzen auf 0 und konvertieren es dann zurück in den Zeitbereich. Als nächstes suchen wir die Spitzen, um die Herzfrequenz zu berechnen, und zeichnen sie dann in einer scrollbaren Form auf.

numpy als np importieren Pyaudio als PA importieren Struktur importieren matplotlib.pyplot als plt importieren aus scipy.signal import decimate, find_peaks CHUNK = 4410 #.1 Sekunde FORMAT = pa.paInt16 KANÄLE = 1 RATE = 44100 # in Hz fstep = RATE/CHUNK p = pa.PyAudio() Werte = [] dsf=44 #Down-Sample-Faktor rds=RATE/dsf #Down-Sampling-Rate stream = p.open( format = FORMAT, Kanäle = KANÄLE, Rate = RATE, input_device_index=3, #Anpassung basierend auf der Eingabe Eingabe=Wahr, frames_per_buffer=CHUNK ) #Grafik einrichten fig,ax = plt.subplots(1) x = np.arange(0,2*CHUNK,2) Linie, = 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 setzt die nicht benötigten Frequenzen auf 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) #minimaler Abstand zwischen Spitzen. stoppt schnelles Auslösen. Begrenzt auch die maximale Stunde, also anpassen Peaks, _ = find_peaks(x, distance=pdis, height=0.1) Intervalle = np.diff(peaks)/rds # in Sekunden Std. = 60 / Intervalle # in BPM returnpeaks,round(np.mean(hr),0) #peaks,avg hr während 1: data = stream.read(CHUNK) dataInt = struct.unpack(str(CHUNK) 'h', data) filtered=getFiltered(dataInt) #filter (arbeitet mit vollständigem Chunk) dsed=decimate(filtered, 44) #down sample (verwandelt Chunk in ds Chunk) Values=np.concatenate((values,dsed)) #fügt die Chunks in ein Array ein Peaks,hr = getHR(values*-1) # ruft die Spitzen ab und bestimmt die durchschnittliche Herzfrequenz. text.set_text(str(hr)) line.set_xdata(np.arange(len(values))) line.set_ydata(values*-10) #Das Negative ist, weil es bei meinem Setup verkehrt herum ankommt. Das *10 ist nur zum Spaß ax.set_xlim(max(0,len(values)-2500),len(values)) #das Diagramm weiter scrollen lassen vlines = ax.vlines(peaks,ymin=-100,ymax=100,colors='red', linestyles='dashed') # Platziere einige Linien an den Spitzen fig.canvas.draw() fig.canvas.flush_events() vlines.remove() if len(values)>10000: #hält die Größe des Arrays überschaubar und sorgt für ein hübsches Scrollen des Diagramms Werte=Werte[5000:] #5 Sekunden @ ~1000 sr.
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.

Notizen Halten Sie das Kabel ruhig – möglicherweise müssen Sie nach der Bewegung einige Sekunden warten, um eine genaue Herzfrequenz zu erhalten. Ich habe es mit meiner Garmin-Uhr verglichen und es wurden durchweg ähnliche Werte zurückgegeben.

Ausgabe
Simple DIY HR Monitor ECG Display

Haftungsausschluss Denken Sie daran, dass Sie Ihren Körper technisch gesehen zu einem Teil des Kreislaufs machen. Das Kabel wird an die Schnittstelle angeschlossen, die mit dem Computer verbunden ist, der
an die Steckdose angeschlossen ist... Versuchen Sie dies auf eigene Gefahr. Ich bin kein Experte – es macht mir einfach Spaß, mit Dingen herumzuspielen, und ich wollte sie teilen. Nächste Schritte

Diese Methode funktioniert nicht wirklich gut, um alle verschiedenen Teile eines EKG-Signals sauber zu erkennen. Die Elektrode ist stark abgenutzt und ich habe nur minimal gefiltert. Es eignet sich auch nicht gut für die Erkennung kleinerer Signale wie bei EMG.

Von hier aus können Sie tiefer in die Software einsteigen und mit zusätzlichen Filtern herumspielen oder einen tatsächlichen Schaltkreis erstellen und echte Elektroden verwenden. Eine Tüte Elektroden für so etwas gibt es bei Amazon ziemlich günstig (Achtung, der Kleber nervt). Für eine Schaltung habe ich ein paar verschiedene Konfigurationen ausprobiert – was ich am einfachsten fand/für mich am besten funktionierte, war eine einfache Instrumentenverstärkerschaltung mit einem JFET-Operationsverstärker (zusammengebaut auf einem Steckbrett). 3 Elektroden, schauen Sie sich einfach ein Diagramm an, wo Sie sie platzieren können. Wenn Sie die Audioschnittstelle für den ADC verwenden, sollte der Code hier mit dem 3-Elektroden-Steckbrett-Setup funktionieren (möglicherweise muss die Verstärkung angepasst werden)

Warum

Die Inspiration für dieses Miniprojekt entstand, als ich mit einem EQ-Plug-in in einer DAW herumspielte, während ich ein Gitarrenkabel in der Hand hielt.

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/benwwq/simple-diy-hr-monitorecg-display-4ol5?1 Bei Verstößen wenden Sie sich bitte an [email protected], um ihn zu löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3