"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > شاشة HR بسيطة يمكنك صنعها بنفسك + شاشة تخطيط القلب

شاشة HR بسيطة يمكنك صنعها بنفسك + شاشة تخطيط القلب

تم النشر بتاريخ 2024-11-09
تصفح:202

هدف
الهدف من هذا المشروع الصغير/البرنامج التعليمي هو إنشاء شاشة مراقبة للموارد البشرية وشاشة تخطيط القلب قابلة للتمرير باستخدام الحد الأدنى من المكونات.

متطلبات:

  • بايثون
  • واجهة الصوت
  • كابل 1/4 بوصة/كابل جيتار/كابل أداة (يحتاج فقط إلى الدخول إلى الكمبيوتر عبر واجهة الصوت)

خلفية سريعة

تقوم عضلات القلب بإنشاء إشارات كهربائية. بعض هذه الإشارات يمكن اكتشافها على سطح الجلد.

يمكننا التقاط تلك الإشارات باستخدام الأقطاب الكهربائية السطحية. المشكلة هي أن هذه ليست الإشارات الكهربائية الوحيدة على الجلد. ولحسن الحظ، فإن معظم الإشارات التي نرغب في رؤيتها تقتصر على حوالي 1-40 هرتز.

عملية

سنأخذ كابلنا مقاس 1/4 بوصة، والذي سيكون بمثابة قطب كهربائي لدينا وندخله في بشرتنا بالقرب من القلب. ثم نستخدم واجهة الصوت USB لتضخيم الإشارة التناظرية وتحويلها إلى رقمية أخيرًا نقوم بالتصفية والعرض في لغة بايثون.

خطوات

الخطوة 1: يتكون الكابل مقاس 1/4 بوصة من جزأين، الغلاف والطرف. يحتاج كلا الجزأين إلى ملامسة بشرتك - فقط أمسك الغلاف بيدك واهرسه على الجانب الأيسر من صدرك/القفص الصدري العلوي (قد تحتوي بعض الكابلات على قنوات أكثر، فقط تأكد من اتصالها جميعًا للبدء).

Simple DIY HR Monitor ECG Display

الخطوة 2:

قم بتشغيل الكود أدناه. تأكد من أن سطر input_device_index يشير إلى واجهة الصوت الخاصة بك. ما نقوم به هو أخذ أجزاء من الصوت الوارد، والتحويل إلى مجال التردد باستخدام fft، وضبط جميع الترددات غير الضرورية على 0، ثم التحويل مرة أخرى إلى المجال الزمني. بعد ذلك نجد القمم لحساب الموارد البشرية ثم رسم بياني بطريقة التمرير.
استيراد numpy كـ np استيراد pyaudio كـ pa هيكل الاستيراد استيراد matplotlib.pyplot كـ plt من scipy.signal استيراد عشري، find_peaks القطعة = 4410 #.1 ثانية التنسيق = pa.paInt16 القنوات = 1 المعدل = 44100 # بالهرتز fstep = معدل/قطعة ع = pa.PyAudio() القيم = [] dsf=44 #عامل العينة السفلي rds=RATE/dsf #down معدل العينات تيار = ص.فتح ( تنسيق = تنسيق، القنوات = القنوات، معدل = معدل، input_device_index=3، #ضبط بناءً على الإدخال الإدخال = صحيح، frames_per_buffer=CHUNK ) # إعداد الرسم البياني الشكل، الفأس = plt.subplots(1) س = np.arange(0,2*CHUNK,2) الخط، = 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), تحويل=ax.transAxes, حجم الخط=14, المحاذاة العمودية = "الأعلى") الشكل.إظهار() def getFiltered(x,hp=1,lp=41): #this يضبط التكرارات غير الضرورية على 0 ففت=np.fft.fft(x) hptrim=len(fft)/RATE*hp lptrim=len(fft)/RATE*lp fft[int(lptrim):-int(lptrim)]=0 ft[0:int(hptrim)]=0 إرجاع np.real(np.fft.ifft(fft)) مواطن getHR(x): pdis = int(0.6 * rds) #المسافة الدنيا بين القمم. توقف عن التحفيز السريع. أيضًا الحد الأقصى للساعة، لذا اضبطه القمم، _ = find_peaks(x، المسافة = pdis، الارتفاع = 0.1) الفواصل الزمنية = np.diff(القمم)/rds # بالثواني ساعة = 60 / فواصل زمنية # في BPM قمم العودة، round(np.mean(hr),0) #peaks,avg hr بينما 1: البيانات = تيار.قراءة (CHUNK) dataInt = struct.unpack(str(CHUNK) 'h'، بيانات) filtered=getFiltered(dataInt) #filter (العمل مع القطعة الكاملة) dsed=decimate(filtered, 44) عينة #down (تحويل القطعة إلى قطعة ds) value=np.concatenate((values,dsed)) # يضع القطع في مصفوفة Peaks,hr = getHR(values*-1) # يحصل على القمم ويحدد متوسط ​​HR. text.set_text(str(hr)) line.set_xdata(np.arange(len(values))) line.set_ydata(values*-10) #السلبية هي أنها تأتي مقلوبة مع الإعداد الخاص بي. *10 للمتعة فقط ax.set_xlim(max(0,len(values)-2500),len(values)) # استمر في تمرير الرسم البياني vlines = ax.vlines(peaks,ymin=-100,ymax=100,colors='red', linestyles='dashed') # انبثاق بعض الخطوط عند القمم شكل.قماش.رسم() الشكل.canvas.flush_events() vlines.remove() إذا len(values)>10000: #يحافظ على حجم المصفوفة بشكل يمكن التحكم فيه، ويتم تمرير الرسم البياني بشكل جميل value=values[5000:] #5 ثواني @ ~1000 ريال.

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 الخاصة بي، وكانت تظهر دائمًا قيمًا مماثلة.

الإخراج


Simple DIY HR Monitor ECG Display

تنصل

ضع في اعتبارك أنك من الناحية الفنية تجعل جسمك
جزءًا من الدائرة. يتم توصيل الكابل بالواجهة المتصلة بالكمبيوتر والتي متصلة بمأخذ الطاقة بالحائط... جرب هذا على مسؤوليتك الخاصة. أنا لست خبيرًا، أنا فقط أستمتع باللعب بالأشياء، وأردت مشاركتها.

الخطوات التالية

لا تعمل هذه الطريقة بشكل جيد جدًا لرؤية جميع الأجزاء المختلفة لإشارة تخطيط القلب بشكل واضح. القطب الكهربائي مخدوش للغاية وقمت بالحد الأدنى من التصفية.
كما أنه لا يعمل بشكل جيد في اكتشاف الإشارات الأصغر مثل EMG.

من هنا يمكنك التعمق أكثر في جانب البرنامج والتلاعب بمرشحات إضافية، أو إنشاء دائرة فعلية واستخدام أقطاب كهربائية حقيقية. تعتبر حقيبة الأقطاب الكهربائية لهذا النوع من الأشياء رخيصة جدًا على أمازون (انتبه، المادة اللاصقة مزعجة). بالنسبة للدائرة، جربت بعض التكوينات المختلفة - ما وجدته أبسط/أفضل بالنسبة لي هو دائرة مكبر صوت بسيطة للأجهزة باستخدام JFET opamp (يتم وضعها معًا على لوحة التجارب). 3 أقطاب كهربائية، ما عليك سوى البحث عن رسم تخطيطي لمعرفة مكان وضعها. إذا كنت تستخدم واجهة الصوت لـ ADC، فيجب أن يعمل الكود هنا مع إعداد لوحة التجارب ثلاثية الأقطاب الكهربائية (قد يلزم ضبط الكسب)

لماذا

جاء الإلهام لهذا المشروع الصغير أثناء اللعب باستخدام مكون EQ الإضافي في DAW أثناء الإمساك بكابل الجيتار.

بيان الافراج يتم استنساخ هذه المقالة على: https://dev.to/benwwq/simple-diy-hr-monitorecg-display-4ol5؟1 إذا كان هناك أي انتهاك ، فيرجى الاتصال بـ [email protected] لحذفه.
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3