Nabız oksimetresi ile kalp atış hızı izleme için Arduino kütüphanesi
Uyku yönetimi projemde izlenen parametrelerden biri
Bu nabız. ölçmek için Hemoglobin ve oksihemoglobinin farklı dalga boylarındaki ışığa karşı davranışını temel alan bir cihaz geliştirdim. Temel olarak belirli bir türdeki ışığın ne kadarının vücudun iyi sulanan bir bölgesinden geçebildiğini veya yansıtabildiğini ölçmekle ilgilidir. Bu olgunun tam bir döngüsünün meydana gelme sıklığı, ölçümün yapılmasına olanak sağlar. nabız.Projenin tasarım ve test aşamasında nabız ölçüm cihazı Montajın doğru olduğunu doğrulamama yardımcı olacak bazı küçük programlar geliştirdim. Öncelikle zaman zaman (en azından her seferinde) ölçülen değerleri alan aşağıdaki kodu yazdım. ve en fazla her biri ) biri ile bir önceki arasında minimum değişiklik gösterdiğinde (karşılık gelen değer) ) ve Python uygulamasıyla bir bilgisayardan izleniyor bunları daha sonra analiz edebilmek için.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
#define PIN_OXIMETRO 0 // Pin analógico 0
#define MEDIDA_MINIMA 10 // Cambio menor monitorizado
#define TIEMPO_MAXIMO_MEDIDA 200 // Cambio menor entre medidas (determina la resolución vertical)
#define TIEMPO_MINIMO_MEDIDA 100 // Milisegundos entre medidas (determina la resolución horizontal)
int lectura_anterior_oximetro=0;
int lectura_oximetro;
unsigned long cronometro_minimo=0;
unsigned long cronometro_maximo=0;
void setup()
{
Serial.begin(9600);
//pinMode(PIN_OXIMETRO,INPUT); // Ya es entrada por defecto
}
void loop()
{
if(millis()>cronometro_minimo)
{
lectura_oximetro=analogRead(PIN_OXIMETRO);
if(abs(lectura_oximetro–lectura_anterior_oximetro)>MEDIDA_MINIMA||millis()>cronometro_maximo)
{
cronometro_minimo=millis()+TIEMPO_MINIMO_MEDIDA;
cronometro_maximo=millis()+TIEMPO_MAXIMO_MEDIDA;
lectura_anterior_oximetro=lectura_oximetro;
Serial.println(String(millis(),DEC)+“,”+String(lectura_oximetro,DEC));
}
}
}
|
Değerler ayarlandıktan sonra (çok yoğun ölçümlerden başlayarak) nabız oksimetresi zamanla bir e-tablo kullanarak grafik çizebildim, LibreOffice Calc de LibreOffice, özel.
Yukarıdaki resimde temsil edildiği gibi toplanan verilerle, bir sonraki işlem, değer yoğunluğunun, değeri güvenilir ancak "ekonomik" bir şekilde (gerekli verilerden daha fazlasını örneklemeden) hesaplamamıza izin verip vermediğini belirlemekti. nabız; Aşağıdaki grafikte de görüldüğü gibi, alınan önlemler beklenebilecek sonuçların alınmasına hizmet ediyor gibi görünüyordu.
.
Daha sonra veri örneklemesinden elde edilen bilgilerle nabız hızını ölçecek bir algoritmanın geliştirilmesi gerekiyordu. Grafiğe sadık kalarak, basitlik açısından, aşağıdakine benzer bir düzeni temsil ettiği varsayılmaktadır. QRS kompleksi, en basit şey, en belirgin kısımlar arasındaki süreyi daha yüksek değerlerle (ventriküllerin depolarizasyon qRs bölgesine karşılık gelir) ölçmek, daha düz ve "gürültülü" bölgeyi atmak gibi görünüyor, bu nedenle daha zor ölçmek. Aşağıdaki test koduna karşılık gelen benimsenen çözüm, aşağıdaki prosedüre göre çalışır:
-
Yalnızca değer zirvelerine dikkat etmek için her durumda ölçülen alanı tespit edin qR'ler ve vadiyi atın. Bunu yapmak için belirli bir sabitin üzerindeki değerler ölçülebilir, ancak bireyin ve/veya koşulların orantılı da olsa değerleri yükseltmesi veya düşürmesi riski vardır. Bunu önlemek için alandaki bir değer, ortalama değeri belirli bir katsayı kadar aşan değerden büyük kabul edilir. Bu şekilde ölçüm hassas bir şekilde kendi kendine kalibre edilir ve katsayıya ince ayar yapılarak daha da ayarlanabilir; benim durumumda bunu testler sırasında deneysel olarak elde ettim.
Ölçüm için azalan bölgenin değerlerini seçin (Rs) zirvenin qR'lerEğrinin maksimumuna mümkün olduğu kadar yakın. Yükselen bölgenin terk edildiğini bilmek için, yeni bir değerin öncekinden daha küçük olduğunu doğrulamak ve genel olarak azalan bölgede birkaç değer olduğundan aranan değerin henüz bulunamadığını doğrulamak yeterlidir. bölgesi qR'ler örnekleme yoğunluğuna bağlıdır. Darbeyi zamanlamak için, noktanın bulunduğu anın değeri (tarafından döndürülen milisaniye) saklanır. milis ()) ve onu bir sonrakiyle karşılaştırır.
Ölçülen değerin en yüksek eğrinin azalan bölgesindeki en büyük değer olmasını sağlamak için bir değişken kullanılır boolean ( bu örnekte ve Ana eğrinin artan bölgesine girildiğinde etkinleştirilen ve zamanlanmış olan ilk azalan değer bulunduğunda devre dışı bırakılan.
Nabız süresinin dakika başına atım (ppm) olarak temsil edilmesi olağan olduğundan, elde edilen atımlar arasındaki sürenin değeri, temsilin toplam süresinin (bir dakika, 60000 milisaniye) elde edilen aralığa bölünmesiyle hesaplanarak düzeltilir. Geçerli milisaniyeyi (geçerli değerden) önceden zamanlanmış olanlar arasından çıkararak.
Yanlış ölçümlerden kaçınmak için (örneğin vakumda ölçüm yapan cihaz gibi), kesin olarak kabul edilmeden önce sonucun maksimum ve minimum değerler arasında olduğu doğrulanır. İstirahat halindeki sağlıklı bir yetişkin için normal değerin 60 ila 100 ppm arasında olduğu ortalama olarak kabul edilse de aşağıda kabul edilebilir değerler bulunmaktadır, istirahat halindeki bir sporcuda 40 ppm'i, egzersiz sırasında 200 ppm'e kadar bulmak kolaydır. yoğun egzersiz ve heyecan halindeki hareketsiz yetişkinlerde 100 ppm'den fazlası, uyku yönetimi projesi için kesinlikle ilginç bir faktör bu da beni bunu geliştirmeye yönlendiriyor nabız ölçüm cihazı. Bu nedenle ilgili yönleri tam olarak gösterebilecek aşırılıkların kaybolmaması için bu değerlerin çok gevşetilmesi tavsiye edilir.
Yeni ortalama değer, örneklenen değer sayısına göre mevcut ortalamanın alaka düzeyi azaltılarak hesaplanır ve son değer eklenir, ayrıca o ana kadar ölçülen değer sayısı arttıkça onu daha da azaltan bir katsayı ile ağırlıklandırılır. .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#define PIN_OXIMETRO 0 // Pin analógico 0
#define TIEMPO_MINIMO_MEDIDA 20 // Milisegundos entre medidas (determina la resolución horizontal)
#define COEFICIENTE_PULSO 1.25 // Coeficiente que determina la zona de valores en la que medir el pulso
#define PULSO_MENOR 30 // Ignorar valores menores (Es infrecuente un pulso más lento aún en reposo)
#define PULSO_MAYOR 180 // Ignorar valores mayores (Es infrecuente un pulso mayor en reposo)
#define MINUTO 60000.0 // Milisegundos en un minuto
float velocidad_pulso;
float lectura_media_oximetro=511.5;
unsigned long valores_contados=0;
int lectura_anterior_oximetro=0;
int lectura_oximetro;
boolean medir_pulso=false;
unsigned long cronometro_pulso=0;
unsigned long cronometro_oximetro=0;
void setup()
{
Serial.begin(9600);
//pinMode(PIN_OXIMETRO,INPUT); // Ya es entrada por defecto
}
void loop()
{
if(millis()>cronometro_oximetro)
{
cronometro_oximetro=millis()+TIEMPO_MINIMO_MEDIDA;
lectura_oximetro=analogRead(PIN_OXIMETRO);
valores_contados++;
lectura_media_oximetro=lectura_media_oximetro*(float(valores_contados–1)/valores_contados);
lectura_media_oximetro+=lectura_oximetro*(1.0/valores_contados);
if(lectura_oximetro>lectura_media_oximetro*COEFICIENTE_PULSO)
{
if(lectura_anterior_oximetro<lectura_oximetro)
{
medir_pulso=true;
}
else
{
if(medir_pulso)
{
velocidad_pulso=MINUTO/float(millis()–cronometro_pulso);
medir_pulso=false;
if(velocidad_pulso>PULSO_MENOR&&velocidad_pulso<PULSO_MAYOR)
{
Serial.println(“Pulso “+String(velocidad_pulso,DEC));
}
cronometro_pulso=millis();
}
}
}
lectura_anterior_oximetro=lectura_oximetro;
}
}
|
Son olarak, daha önce anlatılan algoritmayı kullanarak, nabzın varlığını tespit ederek nabzı hesaplayacak kütüphaneyi geliştirdim. hemoglobin o oksihemoglobin (kullanılan ışığın dalga boyuna bağlı olarak) aşağıdaki koddan.
Kütüphane örnekleme fonksiyonunun periyodik olarak çağrılmasını beklemektedir. nabız uyku yönetimi projemde
. Her durumda, yaptığım testlere göre buna gerek yok gibi görünüyor; cihazdan veya davranışından dolayı fonksiyonla başvurulabilecek nabzı hesaplamak için veya fonksiyonla ortalama nabız. Sınırlı bir kaynak olmasının yanı sıra, kesintileri kullanmayı reddettim çünkü anlık değerlere değil, daha ziyade zaman içinde sürdürülebilir olanlara ihtiyacım vardı. nabızBelirli bir frekansta örnekleme yeterli bilgi sağlar ve bu bilginin arttırılmasıyla daha fazlası (ilgili) elde edilmez ve hesaplama için ilgili verileri kaybetmeden çok fazla azaltılması da mümkün değildir; kodun ilk sürümlerinde okunuşunu izlemek için nabız oksimetresi Maksimum ölçüm süresine bağlı kalmanın gerekli olmadığını keşfettim çünkü ardışık değerlerin değişimleri doğru bir şekilde dikkate alınırsa minimuma çok yakındı.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
//pulso.h
#if defined(ARDUINO) && ARDUINO>=100
#include “Arduino.h”
#else
#include “WProgram.h”
#endif
#define PULSO_MINIMO 5 // Pulso mínimo. Un pulso menor se considera un error.
#define PULSO_MAXIMO 200 // Pulso máximo. Un pulso mayor se considera un error.
#define COEFICIENTE_PULSO 1.25 // Coeficiente que multiplica el pulso medio para determinar si el valor medido está en la zona que se cronometra. Puede usarse para calibra el dispositivo
#define OXIMETRIA_MEDIA 511.5 // Medida media inicial del pulso (1023/2) Puede usarse para calibrar el dispositivo
#define PULSO_MEDIO 80.0 // Pulso medio de un adulto en reposo (sólo para referencia)
class Pulso
{
private:
byte pin_oximetro; // Pin analógico al que se conecta el sensor de pulso
int lectura_oximetro; // Último valor medido en el sensor de pulso
int lectura_anterior_oximetro; // Penúltimo valor medido en el sensor de pulso para compararlo con el último y establecer la zona de valores en la que se encuentra
unsigned long numero_lecturas_oximetro; // Número de medidas del oxímetro tomadas. Usado para calcular la media
unsigned long numero_lecturas_pulso; // Número de medidas de pulso tomadas. Usado para calcular la media
float lectura_media_oximetro; // Medida media del sensor de pulso. Usado para saber si un valor se encuentra en la zona de medida (que se cronometra) del pulso
boolean medicion_de_pulso_activa; // Verdadero si se ha entrado de la zona del pulso (para no confundir si aún se encuentra en una zona ya medida)
float velocidad_pulso; // Último valor de pulso calculado
float ultima_velocidad_pulso; // Último valor de pulso correcto
float velocidad_media_pulso; // Media de los pulsos calculados durante la última sesión (creación del objeto Pulso)
unsigned long cronometro_pulso; // Tiempo entre medidas de pulso consecutivas
protected:
public:
Pulso(byte pin_oximetro_solicitado);
~Pulso();
void monitorizar_pulso(); // Se llama periódicamente (entre 10 y 50 ms) para calcular el pulso
byte ultimo_pulso(); // Devuelve el último valor correcto de pulso muestreado
byte pulso_medio(); // Devuelve el pulso medio de la sesión
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
//pulso.cpp
#include “pulso.h”
Pulso::Pulso(byte pin_oximetro_solicitado)
{
pin_oximetro=pin_oximetro_solicitado;
//pinMode(pin_oximetro,INPUT); // Ya es entrada por defecto
numero_lecturas_oximetro=0;
numero_lecturas_pulso=0;
lectura_media_oximetro=OXIMETRIA_MEDIA;
velocidad_media_pulso=PULSO_MEDIO;
medicion_de_pulso_activa=false;
lectura_anterior_oximetro=0;
ultima_velocidad_pulso=0; // Para indicar que es un valor incorrecto por el momento
cronometro_pulso=0;
}
Pulso::~Pulso()
{
}
byte Pulso::ultimo_pulso()
{
return round(ultima_velocidad_pulso);
}
byte Pulso::pulso_medio()
{
return round(velocidad_media_pulso);
}
void Pulso::monitorizar_pulso()
{
lectura_oximetro=analogRead(pin_oximetro);
numero_lecturas_oximetro++;
lectura_media_oximetro=lectura_media_oximetro*(float(numero_lecturas_oximetro–1)/numero_lecturas_oximetro); // Cambiar la representatividad de la parte actual de la media de pulso
lectura_media_oximetro+=lectura_oximetro*(1.0/numero_lecturas_oximetro); // Añadir la nueva lectura a la media
if(lectura_oximetro>lectura_media_oximetro*COEFICIENTE_PULSO)
{
if(lectura_anterior_oximetro<lectura_oximetro) // Medida de valores creciente
{
medicion_de_pulso_activa=true;
}
else
{
if(medicion_de_pulso_activa)
{
velocidad_pulso=60000.0/float(millis()–cronometro_pulso); // Cálculo de las pulsaciones por minuto (representación habitual del pulso)
medicion_de_pulso_activa=false; // Ya se ha medido el pulso, no medir hasta entrar en una nueva zona ascendente
if(velocidad_pulso>PULSO_MINIMO&&velocidad_pulso<PULSO_MAXIMO)
{
numero_lecturas_pulso++;
ultima_velocidad_pulso=velocidad_pulso;
velocidad_media_pulso=velocidad_media_pulso*(float(numero_lecturas_pulso–1)/numero_lecturas_pulso); // Calcular la representatividad de la media actual en la nueva media
velocidad_media_pulso+=velocidad_pulso*(1.0/numero_lecturas_pulso); // Añadir la nueva lectura a la media
}
cronometro_pulso=millis();
}
}
}
lectura_anterior_oximetro=lectura_oximetro;
}
|
Aşağıdaki örnek program, önceki kitaplığın ölçüm için nasıl kullanılacağını gösterir. nabız ile nabız oksimetresi. Sınıfı başlatmanın yanı sıra seviyesinin izlenmesi oksihemoglobin/hemoglobin ve daha küçük bir periyodiklikle değeri nabız hesaplanmış ve ortalama.
Ölçümlerin ilgili olduğundan emin olmak için herhangi bir değer görüntülenmeden önce bir bekleme programlanır. Değer yanlış olabileceğinden (örneğin kullanıcının cihazı çıkarması durumunda), değerler yalnızca geçerli olduğu düşünülen aralıktaysa gösterilir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
#define PIN_PULSOMETRO 0
#define TIEMPO_MONITORIZACION_PULSO 20
#define TIEMPO_PRESENTACION_PULSO 5000
#include “pulso.h”
Pulso pulso(PIN_PULSOMETRO);
unsigned long cronometro_monitorizacion_pulso;
unsigned long cronometro_presentacion_pulso;
byte velocidad_pulso;
byte velocidad_media_pulso;
void setup()
{
Serial.begin(9600);
cronometro_monitorizacion_pulso=0;
cronometro_presentacion_pulso=TIEMPO_PRESENTACION_PULSO*2;
}
void loop()
{
if(millis()>cronometro_monitorizacion_pulso)
{
cronometro_monitorizacion_pulso=millis()+TIEMPO_MONITORIZACION_PULSO;
pulso.monitorizar_pulso();
}
if(millis()>cronometro_presentacion_pulso)
{
cronometro_presentacion_pulso=millis()+TIEMPO_PRESENTACION_PULSO;
velocidad_pulso=pulso.ultimo_pulso();
velocidad_media_pulso=pulso.pulso_medio();
if(velocidad_pulso)
{
Serial.print(“Pulso “);
Serial.print(velocidad_pulso,DEC);
Serial.print(” | Pulso medio “);
Serial.println(velocidad_media_pulso,DEC);
}
}
}
|
Yorum Ekle