Goal
The goal of this miniproject/tutorial is to make a super simple HR monitor and scrolling ECG display with minimal components.
Requirements:
- python
- audio interface
- 1/4" cable/guitar cable/instrument cable (it just needs to get into the computer via the audio interface)
Quick Background
The muscles in the heart create electrical signals. Some of those signals are detectable on the surface of the skin.
We can pick those signals up using surface electrodes. The problem is, these aren't the only electrical signals on the skin. Thankfully, most of the signals we want to see are confined to around 1-40Hz.
Process
We are going to take our 1/4" cable, which will act as our electrode and poke it into our skin in the vicinity of the heart. Then we use the USB audio interface to amplify and convert the analogue signal to digital. Finally we filter and display in python.
Steps
Step 1: A 1/4" cable has two parts, the sleeve and the tip. Both parts need to make contact with your skin- just hold the sleeve with your hand and mash it against the left side of your chest/upper rib cage (some cables may have more channels, just make sure they all have contact to start). Adjust gain on audio interface (I turn mine all the way up).
Step 2: Run the below code. Make sure to check that the input_device_index line is pointing to your audio interface. What we are doing is taking chunks of the incoming audio, converting to the frequency domain using fft, setting all unnecessary frequencies to 0, and then converting back to the time domain. Next we find the peaks to calculate the HR then graph in a way that scrolls.
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.
Notes
Hold the cable still - you may need to wait a few seconds after movement to get an accurate heart rate. I checked it against my garmin watch, and it consistently returned similar values.
Output
Disclaimer
Keep in mind, you are technically making your body a part of the circuit. The cable is connected to the interface which is connected to the computer which is connected to the wall power outlet... Try this at your own risk. I am no expert- I just enjoy playing around with stuff, and wanted to share.
Next Steps
This method doesn't really work very well for cleanly seeing all of the different parts of an ECG signal. The electrode is super scuffed and I did a bare minimum of filtering.
It also doesn't do well in detecting smaller signals like for EMG.
From here you can dig deeper on the software side and play around with additional filters, or create an actual circuit and use real electrodes. A bag of electrodes for this type of thing is pretty cheap on amazon (heads up, the adhesive is annoying). For a circuit, I've tried a few different configurations- what I found simplest/worked the best for me was a simple instrumentation amplifier circuit using a JFET opamp (put together on a on a breadboard). 3 electrodes, just look up a diagram for where to put them. If you use the audio interface for the ADC, the code here should work with the 3 electrode breadboard set up (might have to adjust the gain)
Why
The inspiration for this miniproject came about while playing around with a EQ plug-in in a DAW while holding a guitar cable.
The above is the detailed content of Simple DIY HR Monitor ECG Display. For more information, please follow other related articles on the PHP Chinese website!

TomergelistsinPython,youcanusethe operator,extendmethod,listcomprehension,oritertools.chain,eachwithspecificadvantages:1)The operatorissimplebutlessefficientforlargelists;2)extendismemory-efficientbutmodifiestheoriginallist;3)listcomprehensionoffersf

In Python 3, two lists can be connected through a variety of methods: 1) Use operator, which is suitable for small lists, but is inefficient for large lists; 2) Use extend method, which is suitable for large lists, with high memory efficiency, but will modify the original list; 3) Use * operator, which is suitable for merging multiple lists, without modifying the original list; 4) Use itertools.chain, which is suitable for large data sets, with high memory efficiency.

Using the join() method is the most efficient way to connect strings from lists in Python. 1) Use the join() method to be efficient and easy to read. 2) The cycle uses operators inefficiently for large lists. 3) The combination of list comprehension and join() is suitable for scenarios that require conversion. 4) The reduce() method is suitable for other types of reductions, but is inefficient for string concatenation. The complete sentence ends.

PythonexecutionistheprocessoftransformingPythoncodeintoexecutableinstructions.1)Theinterpreterreadsthecode,convertingitintobytecode,whichthePythonVirtualMachine(PVM)executes.2)TheGlobalInterpreterLock(GIL)managesthreadexecution,potentiallylimitingmul

Key features of Python include: 1. The syntax is concise and easy to understand, suitable for beginners; 2. Dynamic type system, improving development speed; 3. Rich standard library, supporting multiple tasks; 4. Strong community and ecosystem, providing extensive support; 5. Interpretation, suitable for scripting and rapid prototyping; 6. Multi-paradigm support, suitable for various programming styles.

Python is an interpreted language, but it also includes the compilation process. 1) Python code is first compiled into bytecode. 2) Bytecode is interpreted and executed by Python virtual machine. 3) This hybrid mechanism makes Python both flexible and efficient, but not as fast as a fully compiled language.

Useaforloopwheniteratingoverasequenceorforaspecificnumberoftimes;useawhileloopwhencontinuinguntilaconditionismet.Forloopsareidealforknownsequences,whilewhileloopssuitsituationswithundeterminediterations.

Pythonloopscanleadtoerrorslikeinfiniteloops,modifyinglistsduringiteration,off-by-oneerrors,zero-indexingissues,andnestedloopinefficiencies.Toavoidthese:1)Use'i


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

Notepad++7.3.1
Easy-to-use and free code editor

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

SublimeText3 Mac version
God-level code editing software (SublimeText3)

ZendStudio 13.5.1 Mac
Powerful PHP integrated development environment
