Professional Documents
Culture Documents
¡Quién no ha pensado alguna vez como poder capturar a sí mismo la señal eléctrica del
corazón! Pues bien, en esta entrada os voy a mostrar como podéis construiros un circuito
electrónico para haceros un sistema capaz de medir vuestra señal de ECG, es decir
obtener vuestro electrocardiograma.
http://www.ti.com/lsds/ti/amplifiers-linear/instrumentation-amplifier-products.page
y eches un vistazo a todos los modelos por si en tu caso te interesa usar otro diferente.
Por si te interesa también he probado el modelo INA110K y funciona perfectamente como
este otro.
Para más datos al respecto sobre este amplificador de instrumentación, os dejo el
datasheet del mismo para que podáis consultar cualquier de las características que tiene.
https://drive.google.com/file/d/0By2_W81NKkeAU2hMSTFrWGtYS3c/view?usp=sharing
1. Amplificador de Instrumentación
2. Guarda Activa.
3. Filtrado (Etapa de Filtro Paso Alto y Filtro Paso Bajo)
4. Ajuste de Offset e indicación sonora.
Guarda Activa
Para la Guarda Activa, he seguido exactamente los consejos de diseño del fabricante en el
datasheet, como a continuación os indico:
Además aquí os dejo un documento teórico explicativo de la Realimentación Activa:
https://drive.google.com/file/d/1ZSv_KuYfOMocd6MoZUDJbiUuKgF2kknv/view?usp=sharin
g
Para el diseño del filtrado he montado una etapa con un filtro paso alto y luego
seguidamente otro filtro paso bajo, para quedarme con las frecuencias por debajo de los
40Hz y así despreciar la frecuencia de red.
Que ajustando los valores de uno de los componentes, por ejemplo el valor
de C =100nF se determina el circuito de la figura, con la frecuencia de
corte deseada de 100Hz según las formulas mostradas.
Para que quede mucho más real nuestro electrocardiograma, se puede hacer uso del
famoso NE555 para generar un circuito oscilador o aestable y obtener una señal sonara
idéntica a la del ritmo cardíaco. Para controlar que la emisión del pitido del altavoz vaya
acorde al ritmo cardíaco se conecta la salida del circuito de ajuste de offset al pin 4 (RST)
del NE555, para que cuando se tenga la señal del ECG en el punto más elevado el oscilador
se active y por tanto genere el correspondiente tono en el altavoz.
El NE555, por ejemplo, lo fijamos para que oscile a una frecuencia de 3000Hz. Los cálculos
para obtener el valor de las resistencias y el condensador son los siguientes:
Fijamos el valor del condensador del pin 2 a un valor de 10nF. El motivo es porque se tienen
comercialmente menos margen de valores en condensadores, si lo comparamos con los
valores comerciales de una resistencia (pues se tienen series como la E192 para encontrar
casi cualquier valor o incluso llegado el caso usar una resistencia variable).
Tc + Td = 1/ 3000 = 3,3e-4
Dado que con una configuración estándar no es posible obtener que Tc sea igual a Td, lo
que hacemos es que por ejemplo: el Tc = 75% del tiempo total y el Td = 25% del tiempo
total.
R2 = (3.3e-4 * 0,25) / 0,69 * 10nF = 12077 cuyo valor comercial existente seria 12KΩ
R1 = [ (0,75 * 3.3e-4 ) / (0,69 * 10nF) ] -12KΩ = 35869 - 12077 = 23792Ω cuyo valor
comercial existente sería 22KΩ
"POVRay PCB"
A continuación os muestro como ha quedado el modelado en 3D con POV Ray del PCB
del ECG:
"Electrodos ECG"
En esta imagen os muestro como son los electrodos que son necesarios usar para poder
adherirlos a nuestro cuerpo.
Es importante que los cables no sean excesivamente largos y crucen de una lado a otro de
la placa board, para así evitar ruidos e interferencias. El rango de alimentación del
amplificador de instrumentación y del resto de circuitos intregrados permite que se pueda
usar una pila de 9V para hacer portable el sistema ECG.
A continuación os muestro una prueba del funcionamiento del circuito ECG, visualizando la
señal en un osciloscopio.
Vídeo de funcionamiento del Circuito ECG
En la parte II, os mostraré la forma de como digitalizar la señal que obtenemos a la salida
del circuito de ajuste de offset por medio de un microcontrolador (el cual tenga un
subsistema conversor A/D) y llevarla a un software de alto nivel para representarla
gráficamente en un PC.
Espero que os haya gustado ..... y ya sabéis, ahora no hay excusa para no poder analizar
en que estado se encuentra vuestro pulso cardíaco!!
Un saludo.
-------------------------------------------------------------------------------------------------------------------------
---------------------------------------
Por favor, si te ha gustado el blog, te ha ayudado o
has visto algún proyecto interesante del que te has
podido descargar alguna documentación por favor
deja algún comentario. Gracias.
-------------------------------------------------------------------------------------------------------------------------
---------------------------------------
Tras ser arrancado el programa lo primero que debe hacer, es elegir el puerto que
se va usar para comunicarse con el microcontrolador. Eso se elige con la opción que existe
denominada “Puerto de Entrada”. Una vez seleccionado el puerto, el programa ya esta listo
para poder capturar los datos que le envíe el microcontrolador. Para ello se debe seleccionar
la opción “Iniciar Captura”. En ese momento el programa comienza a capturar datos y los
representa en pantalla. A continuación se muestra un ejemplo de la señal de ECG captura
en tiempo real.
Respecto al resto de opciones como son “Salvar Datos a Disco”, lo que hace es
grabar en un fichero nuevo o bien añadir en otro que ya exista, los valores de la señal que
se esté visualizando en ese momento en la pantalla del visualizador. De este modo tenemos
un fichero el cual tiene registrados todos los valores de la señal en formato ASCII, la fecha
y hora en la que han sido capturados, el directorio donde han sido almacenados y el puerto
por el que se han capturado. Al seleccionar esta opción nos aparece el formulario siguiente:
Si se quisiera ver el contenido de alguno de estos fichero guardados, se debe elegir
la opción de “Visualizar Fichero”. Al ejecutar la opción nos pide que seleccionemos que
fichero queremos ver y muestra el contenido del mismo. Se muestra un ejemplo:
Las opciones de “Salva señal a Fichero” es parecida a anterior. En este caso solo se
guardan los valores de la señal en otro fichero con extensión distinta.
Para poder visualizar un fichero que hayamos guardado basta con dar a la opción
de “Cargar Señal”.
En ese instante aparece un menú como el que muestra la figura anterior y tras
seleccionar la señal deseada, esta es dibujada en la pantalla del visualizador. A continuación
se muestra un ejemplo de carga de señal a pantalla.
Finalmente la opción de “Medida de Tiempos” muestra otro formulario en el que
aparece la medida de tiempos del HRV. En la caja de información de “Tiempo medido” indica
el tiempo medido entre pico y pico de la señal de ECG, es decir el HRV, el resto de
indicadores son a nivel informativos para saber como se va comparando la señal con el
umbral seleccionado. En el grafico que aparece se van representado lo valores de tiempos
que vamos midiendo en función también del tiempo para obtener un evolución del HRV. A
continuación se muestra el formulario que aparece al seleccionar dicha opción:
Código de todo el programa
#include <analysis.h>
#include "FB2.h"
#include <formatio.h>
#include <rs232.h>
#include <utility.h>
//#include "amp_bio.h"
#include <easyio.h>
#include <ansi_c.h>
//#include <dataacq.h>
#include <userint.h>
#include "fb2.h"
DisplayPanel (panelHandle);
RunUserInterface ();
return 0;
}
QuitUserInterface (0);
break;
}
return 0;
}
iniciar = 1;
ResumeTimerCallbacks ();
break;
}
return 0;
}
iniciar = 0;
SuspendTimerCallbacks ();
SetCtrlAttribute (panelHandle, PANEL_LED, ATTR_LABEL_TEXT, "OFF");
SetCtrlAttribute (panelHandle, PANEL_LED, ATTR_OFF_COLOR, VAL_RED);
SetCtrlAttribute (panelHandle, PANEL_INICIAR, ATTR_DIMMED, 0);
SetCtrlAttribute (panelHandle, PANEL_PARAR, ATTR_DIMMED, 1);
SetCtrlVal(panelHandle, PANEL_MAXIMO, 0);
// AIClearAcquisition (0);
break;
}
return 0;
}
if ( iniciar == 1)
{
i=0;
//byte = ComRdByte (2);
ComRd (port, valores, 1);
PlotStripChartPoint (panelHandle, PANEL_VISUALIZADOR, valores[i]);
SetCtrlVal (panelHandle, PANEL_DATOS, valores[i]);
if (ini==1)
{
if (valores[i]>umbral_g)
{
if (dos ==0)
{
auxi1=auxi1 + 1.0;
uno=1;
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO, auxi1);
}
}
if (uno==1)
{
if (valores[i]<umbral_g)
{
auxi2=auxi2 + 1.0;
dos=1;
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO2, auxi2);
}
}
if (dos==1)
{
if (valores[i]>umbral_g)
{
edia = media+1;
parcial = (auxi1 + auxi2);
setCtrlVal (panelHandle2,
PANEL2_CAJATIEMPO3,parcial); GetCtrlVal (panelHandle,
PANEL_VELOCIDAD,&vel);
total = total+parcial;
tempo = total * vel;
duracion = tempo + duracion;
dos=0.0;
auxi1=0.0;
auxi2=0.0;
uno=0.0;
}
}
GetCtrlVal (panelHandle2,
PANEL2_NUMMEDIAS,&c_medias); if (media ==c_medias)
{
SetCtrlVal (panelHandle2,
PANEL2_CAJATIEMPO4,duracion/c_medias); PlotStripChartPoint (panelHandle2,
PANEL2_HISTOGRAM, duracion/c_medias);
parcial=0.0;
duracion=0.0;
total=0.0;
media = 0;
c_medias=0;
}
else
{
}
/// ******* fin de la función que cálcula el tiempo *******
maximo = aux1;
SetCtrlVal (panelHandle, PANEL_MAXIMO,
maximo);
if (umbral_g < valores[0])
{
SetCtrlAttribute (panelHandle, PANEL_LED_2, ATTR_LABEL_TEXT, "Alarma de Umbral:
ON"); SetCtrlAttribute (panelHandle, PANEL_LED_2, ATTR_OFF_COLOR,
VAL_RED); SetCtrlAttribute (panelHandle, PANEL_LED_2, ATTR_LABEL_COLOR,
VAL_RED);
}
else
{
SetCtrlAttribute (panelHandle, PANEL_LED_2, ATTR_LABEL_TEXT, "Alarma de Umbral:
OFF"); SetCtrlAttribute (panelHandle, PANEL_LED_2, ATTR_OFF_COLOR,
VAL_YELLOW); SetCtrlAttribute (panelHandle, PANEL_LED_2, ATTR_LABEL_COLOR,
VAL_BLACK);
}
inc_mues = inc_mues + 1;
GetCtrlVal (PANEL, PANEL_PUNTOS, &numero_puntos);
muestras[inc_mues]= valores[0];
if (inc_mues == numero_puntos)
{
inc_mues=0;
}
}
else{}
break;
}
return 0;
}
aux1=0;
maximo = 0;
SetCtrlAttribute (panelHandle, PANEL_MAXIMO, ATTR_CTRL_VAL, 0);
SetCtrlAttribute (panelHandle, PANEL_DATOS, ATTR_CTRL_VAL, 0);
ClearStripChart (panelHandle, PANEL_VISUALIZADOR);
inc_mues=0;
for(i=0;i<numero_puntos;i++)
{
muestras[i]=0;
}
break;
}
return 0;
}
break;
}
return 0;
}
int SaveToDisk(int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
char directory[300];
FILE *filehandle;
int i;
if (event == EVENT_COMMIT) {
SuspendTimerCallbacks ();
SetCtrlAttribute (panelHandle, PANEL_INICIAR, ATTR_DIMMED, 0);
SetCtrlAttribute (panelHandle, PANEL_PARAR, ATTR_DIMMED, 1);
GetProjectDir (directory);
if (FileSelectPopup (directory, "*.rub", "RUB Files",
"Salvar Señal a Disco", VAL_SAVE_BUTTON, 0,
0, 1, 0, pathname) > 0) {
//ResumeTimerCallbacks ();
return (0);
}
int ViewDataPoints(int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
char filestring[300];
if (event == EVENT_COMMIT) {
char directory[300];
GetProjectDir (directory);
if(FileSelectPopup (directory, "*.rub", "RUB Files", "Cargar Fichero de Disco", VAL_LOAD_BUTTON,
0,
0, 1, 0, pathname2) > 0) {
sprintf (filestring, "notepad.exe %s", pathname2);
LaunchExecutable (filestring);
}
CloseFile (file_handle);
}
return (0);
}
break;
}
return 0;
}
HidePanel (panelHandle2);
tiempo =0;
ini=0;
SetCtrlAttribute (panelHandle2, PANEL2_TIMER2, ATTR_ENABLED,0);
break;
}
return 0;
}
//tiempo = tiempo+1;
//SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO, tiempo);
break;
}
return 0;
}
ini=1;
auxi1=0.0;
auxi2=0.0;
break;
}
return 0;
}
int CVICALLBACK botonparar (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
ini =0;
break;
}
return 0;
}
char directory[300];
FILE *filehandle;
int i;
switch (event) {
case EVENT_COMMIT:
GetProjectDir (directory);
SuspendTimerCallbacks ();
SetCtrlAttribute (panelHandle, PANEL_INICIAR, ATTR_DIMMED, 0);
SetCtrlAttribute (panelHandle, PANEL_PARAR, ATTR_DIMMED, 1);
break;
}
return 0;
}
char filestring[300];
if (event == EVENT_COMMIT) {
char directory[300];
GetProjectDir (directory);
GetCtrlVal (panelHandle, PANEL_PUNTOS, &numero_puntos);
SuspendTimerCallbacks ();
if (FileSelectPopup (directory, "*.sen", "SEN Files", "Cargar señal de disco",VAL_LOAD_BUTTON, 0, 1, 1, 0, pathname2)
> 0)
{
file_handle = OpenFile (pathname2, 1, 2, 0);
for (i=0;i<numero_puntos;i++)
{
PlotStripChartPoint (panelHandle, PANEL_VISUALIZADOR, muestras[i]);
}
CloseFile (file_handle);
}
return 0;
}
break;
}
return 0;
}