But
Le but de ce miniprojet/tutoriel est de créer un moniteur HR super simple et un affichage ECG défilant avec un minimum de composants.
Exigences:
Contexte rapide
Les muscles du cœur créent des signaux électriques. Certains de ces signaux sont détectables à la surface de la peau.
Nous pouvons capter ces signaux à l’aide d’électrodes de surface. Le problème est que ce ne sont pas les seuls signaux électriques sur la peau. Heureusement, la plupart des signaux que nous souhaitons voir se limitent à environ 1-40 Hz.
Processus
Nous allons prendre notre câble 1/4", qui fera office d'électrode et l'enfoncer dans notre peau à proximité du cœur. Ensuite, nous utilisons l'interface audio USB pour amplifier et convertir le signal analogique en numérique. . Enfin, nous filtrons et affichons en python
.Mesures
Étape 1 : Un câble de 1/4" est composé de deux parties, le manchon et la pointe. Les deux parties doivent entrer en contact avec votre peau - tenez simplement le manchon avec votre main et écrasez-le contre le côté gauche de votre poitrine/cage thoracique supérieure (certains câbles peuvent avoir plus de canaux, assurez-vous simplement qu'ils ont tous un contact pour démarrer). Ajustez le gain sur l'interface audio (je monte le mien au maximum).
Étape 2 : Exécutez le code ci-dessous. Assurez-vous de vérifier que la ligne input_device_index pointe vers votre interface audio. Ce que nous faisons, c'est prendre des morceaux de l'audio entrant, les convertir dans le domaine fréquentiel à l'aide de fft, définir toutes les fréquences inutiles sur 0, puis les reconvertir dans le domaine temporel. Ensuite, nous trouvons les pics pour calculer la FC puis dessinons de manière à défiler.
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.
Remarques
Maintenez le câble immobile : vous devrez peut-être attendre quelques secondes après le mouvement pour obtenir une fréquence cardiaque précise. Je l'ai vérifié avec ma montre Garmin et elle a systématiquement renvoyé des valeurs similaires.
Sortir
Clause de non-responsabilité
Gardez à l’esprit que vous faites techniquement en sorte que votre corps fasse partie du circuit. Le câble est connecté à l'interface qui est connectée à l'ordinateur qui est connecté à la prise de courant murale... Essayez ceci à vos propres risques. Je ne suis pas un expert, j'aime juste jouer avec des trucs et je voulais les partager.
Étapes suivantes
Cette méthode ne fonctionne pas vraiment très bien pour voir clairement toutes les différentes parties d'un signal ECG. L'électrode est super éraflée et j'ai fait un strict minimum de filtrage.
Il ne fonctionne pas non plus bien dans la détection de signaux plus petits comme pour l'EMG.
À partir de là, vous pouvez approfondir le côté logiciel et jouer avec des filtres supplémentaires, ou créer un circuit réel et utiliser de vraies électrodes. Un sac d'électrodes pour ce genre de chose est assez bon marché sur Amazon (attention, l'adhésif est gênant). Pour un circuit, j'ai essayé quelques configurations différentes - ce que j'ai trouvé le plus simple/qui fonctionnait le mieux pour moi était un simple circuit amplificateur d'instrumentation utilisant un ampli-op JFET (assemblé sur une planche à pain). 3 électrodes, il suffit de chercher un schéma pour savoir où les mettre. Si vous utilisez l'interface audio pour l'ADC, le code ici devrait fonctionner avec la configuration de la planche à pain à 3 électrodes (il faudra peut-être ajuster le gain)
Pourquoi
L'inspiration pour ce mini-projet est née en jouant avec un plug-in d'égalisation dans une DAW tout en tenant un câble de guitare.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3