You are on page 1of 29

Diseño Electrónico de un ECG"

¡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.

Bien ... manos a la obra.

Para la parte electrónica he usado un amplificador de instrumentación, concretamente el


INA128. ¿Por que este y no otro? Este tiene unas características que lo hacen idóneo para
sistemas de electromedicina y captura de señales biomédicas. Existen muchos más
modelos de amplificadores de instrumentación, pero este concretamente tiene un margen
de alimentación que va desde los 2,25V a los 18V simetricos, lo que lo hace perfecto para
aplicaciones donde la alimentación sea solo de 5V. Este también presenta la posibilidad de
regular la ganancia de amplificación por medio de una resistencia que permite obtener un
margen de ganancia desde 1 hasta 10.000, lo cual es necesario cuando se trabaja con
señales biomédicas. Tiene un encapsulado de 8DIP, lo que también le hace ser mucho
más manejable. Respecto al resto de características, no se diferencia mucho de otros
modelos de amplificadores de instrumentación de la familia INA. Te aconsejo que te metas
en la WEB de Burr-Brown, bueno ya es propiedad de Texas Instrument,

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

A continuación paso a mostraros el circuito electrónico inicial que he diseñado para


construir el sistema ECG. Mas abajo encontrareis el esquema realizado con un software
de diseño de esquemas electrónicos

Como podéis observar lo he dividido en varios bloques:

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.

 Filtro Paso alto:

La frecuencia de paso es de 0,1Hz en adelante. Para ello he calculado los componentes


necesarios por medio de las siguientes fórmulas. La ecuación característica de un filtro
normalizado paso bajo de Butterworth de 2º orden es la siguiente.

Particularizando para f=0,1Hz, se tiene finalmente la función de transferencia buscada:

Para implementar físicamente esta función de transferencia se va a usar


la siguiente red activa.
La cual tiene la función de transferencia:

Comparando esta función de transferencia con la función de transferencia


deseada, se tiene:

Para calcular el valor teórico de los componentes R y C se fija el valor de


C y se obtiene el valor de la resistencia R, es decir:

2 * 0,1 * pi * R * C = 1 fijando C = 1uF se despeja R

R = 1 / ( 2 * 0,1 * pi * 1uF ) = 1,6MΩ

A continuación se muestra el esquema definitivo con los


correspondientes valores ajustados y finalmente montados.
 Filtro Paso bajo:
Siguiendo la misma metodología que en el punto anterior y fijando una frecuencia
de corte superior de 40 Hz para eliminar la componente de 50 Hz de la red, el filtro
usado es uno normalizado de 2º orden de Butterworth el cual queda definido por
la siguiente función de transferencia:

Que tras hacer el cambio a la variable de la frecuencia se obtiene la


función de transferencia siguiente:

Y particularizando para una determinada frecuencia, (en el caso de la


formula se fija la frecuencia a 100Hz)
Luego finalmente la función de transferencia del circuito total es:

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.

R = 1 / (2 * 100Hz * pi * 100nF) = 15,9KΩ cuyo valor comercial existente seria


15KΩ

Para el caso de una frecuencia de 40 Hz el valor de R hubiera sido:

R = 1 / (2 * 40Hz * pi * 100nF) = 39,8KΩ cuyo valor comercial existente seria 39KΩ

A continuación se muestra el esquema montado con el ajuste de los


valores de los componentes para el ejemplo de frecuencia de corte de
100Hz.
 Ajuste de Offset e indicación sonora:
El circuito de ajuste de offset lo que permite es quitar la componente negativa de señal
continua que exista a la salida de la etapa de filtrado. Es importante hacer esto porque el
siguiente paso sería digitalizar la señal por medio de un conversor A/D y estos no admiten
señales con componente negativa.

Además es una forma de amplificar la señal ademas de eliminar su componente negativa.

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.

Para ello el circuito a montar sería el siguiente:

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:

F = 1 / (Tc + Td) donde:

Tc = 0,69 * (R1 + R2) * C


Td = 0,69 * R2 * C

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.

Luego los cálculos quedan de la siguiente forma:

3.3e-4 * 0,25 = 0,69 * R2 * 10nF despejando queda

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Ω

En el circuito finalmente montado las resistencias usadas fueron R1 = 33K y R2 = 10K,


porque eran de los valores que disponía en ese momento. La diferencia se aprecia en la
parte audible y por tanto en la frecuencia del pitido, por lo que estaría bien que como
prueba, que varieis esos valores y observar el efecto que produce en la salida de la señal
generada hacia el altavoz.
"Esquema Electrónico del ECG"

Finalmente el esquema electrónico de como quedaría todo el sistema os lo muestro a


continuación, el cual es idéntico al realizado a mano y que os he mostrado al principio de la
entrada:

"Diseño del PCB del ECG"

Esto otro es como quedaría el diseño de su correspondiente PCB.

"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.

He usado tres. Uno se coloca en el pecho izquierdo, otro en el derecho y el último a la


altura del ombligo. Concretamente el que se coloca en el ombligo es la guarda activa. Con
esa disposición y con unos cables como los que os muestro en la figura no debéis tener
mayor problema para poder captar la señal. Eso sí, es importante que los electródos
hagan contacto sobre la piel, por lo que es aconsejable depilarse un poco la zona si se
tuviese mucho pelo, ...je,je...
Como se observa en la foto, el extremo que se coloca en los electrodos no son ni mas ni
menos que unos cocodrilos, los cuales son fáciles de quitar y poner y perfectos para este
primer prototipo.

Montaje sobre placa board del ECG

A continuación os muestro la imagen de como ha quedado el circuito en las pruebas


realizadas sobre la placa board.

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

Señales reales capturadas del Circuito ECG


Os muestro la comparación de las señales obtenidas de la salida directa del amplificador de
instrumentación, sin pasarla por la etapa de filtrado y la señal a la salida del circuito de
filtrado, abajo y arriba respectivamente.
Como se puede apreciar a la salida del circuito de filtrado la señal queda mucho más
limpia de ruido y un poco más amplificada (Canal 1). La siguiente etapa, la de ajuste de
offset es la encargada ya, de amplificar esta señal limpia de ruido y bien filtrada para poder
ser digitalizada. Esta otra fase la dejo para una futura y nueva entrada en la que estoy
trabajando.

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.
-------------------------------------------------------------------------------------------------------------------------
---------------------------------------

APORTO PARTE DEL DISEÑO ANTIGUO DE LA PARTE DE ALTO NIVEL SOLICITADO


POR UNA DE LAS PERSONAS QUE HA DEJADO UN COMENTARIO EN EL BLOG EN
EL QUE COMENTA INTERÉS POR EL MISMO.
 CAPTURA POR EL PUERTO SERIE LOS DATOS RECIBIDOS CON UN
PROGRAMA DE ALTO NIVEL
Esta parte del sistema, es el programa de alto nivel, el cual se encarga de capturar
los datos que le envía el microcontrolador por el puerto serie y a partir de ahí los representa,
obtiene información de los datos capturados, etc. Para hacer este programa se ha utilizado
el entorno de programación LabCVI. Entre las funcionalidades del programa las que se
destacan desde un punto de vista práctico son principalmente dos:

1.Captura de la señal del ECG y dibujarla en pantalla en tiempo real.

2.Medida del tiempo HRV y obtención de una evolución en el tiempo.

A continuación se va a describir un poco la funcionalidad del programa y de todas


sus opciones para ver se puede hacer con él. El aspecto del programa al ejecutarlo es el
que se muestra en la siguiente figura.

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.

Mientras el programa esta capturando la señal se puede variar el número de puntos


de la pantalla con la opción “Puntos del Visualizador” para ver más o menos puntos en la
pantalla según nos convenga, variar el umbral de detección que no es más que una alarma
que no indica cuando la señal que capturamos sobrepasa el valor que fijamos. La opción
es “Umbral de Detección”. También se puede variar el tiempo de adquisición con la
opción “Velocidad de Adquisición”, bien puede ser con el ratón o bien número en la caja de
texto y se puede borrar la pantalla de adquisición con la opción “Inicializar”.

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"

const int CANAL_ANALOG = 0;


const int NUM_PUNTOS = 1;
double n_puntos = 200.0;

static int panelHandle,panelHandle2;


int i,iniciar=0,inc_mues=0,modo=0, tiempo =0,histogra[1000];
unsigned int numero_puntos,canal,color;
double dato, puntos[100],array[1000],muestras[7000],histo[1000],ejex[10],histo_x[1000];
double valor,velocidad,canal_d;
unsigned long longi;
char conver,pathname[300],pathname2[300];
char puerto[30];
double byte;
unsigned char maximo,aux1,valores[1000],port=2,port_d,umbral,umbral_g=100;

//Definición variables del código que hace la medida de tiempos


double total=0.0,parcial=0.0,auxi1=0.0,auxi2=0.0,auxi3=0.0,duracion=0.0,tempo=0.0,final_t=0.0,vel,utli=0;
int p=0,dos=0,uno=0,media=0,ini=0, c_medias, h=0;

//Variables para leer del fichero


static int file_handle;
static int handle;
static int status;

int main (int argc, char *argv[])


{
if (InitCVIRTE (0, argv, 0) == 0) /* Needed if linking in external compiler; harmless otherwise */
return -1; /* out of memory */
if ((panelHandle = LoadPanel (0, "fb2.uir", PANEL)) < 0)
return -1;
if ((panelHandle2 = LoadPanel (0, "fb2.uir", PANEL2)) < 0)
return -1;

DisplayPanel (panelHandle);
RunUserInterface ();
return 0;
}

int CVICALLBACK _salir (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

QuitUserInterface (0);
break;
}
return 0;
}

int CVICALLBACK _iniciar (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

iniciar = 1;

ResumeTimerCallbacks ();

OpenComConfig (port, "COM2", 9600, 0, 8, 1, 10, 10);

SetCtrlAttribute (panelHandle, PANEL_LED, ATTR_LABEL_TEXT, "ON");


SetCtrlAttribute (panelHandle, PANEL_LED, ATTR_OFF_COLOR,
VAL_GREEN);
SetCtrlAttribute (panelHandle, PANEL_INICIAR, ATTR_DIMMED, 1);
SetCtrlAttribute (panelHandle, PANEL_PARAR, ATTR_DIMMED, 0);

break;
}
return 0;
}

int CVICALLBACK _parar (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

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;
}

int CVICALLBACK ontimer (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_TIMER_TICK:

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(aux1 < valores[i])


{
aux1 = valores[i];
}

// Inicio de la función que cálcula el tiempo ************

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);
}

//SALVAR PANTALLA A FICHERO

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;
}

int CVICALLBACK _borrado (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

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;
}

int CVICALLBACK _velocidad (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
GetCtrlVal (PANEL, PANEL_VELOCIDAD, &velocidad);
SetCtrlAttribute (panelHandle, PANEL_TIMER, ATTR_INTERVAL, velocidad);
break;
}
return 0;
}

int CVICALLBACK _puntos (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

GetCtrlVal (PANEL, PANEL_PUNTOS, &numero_puntos);


if (numero_puntos > 7002)
{
numero_puntos = 7000;
SetCtrlAttribute (panelHandle, PANEL_PUNTOS, ATTR_MAX_VALUE,numero_puntos);
}
SetCtrlAttribute (panelHandle, PANEL_VISUALIZADOR, ATTR_POINTS_PER_SCREEN,
numero_puntos+2);

break;
}
return 0;
}

int CVICALLBACK _canal (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

GetCtrlVal (panelHandle, PANEL_CANAL, &port);


port_d = port;
break;
}
return 0;
}

int CVICALLBACK _color (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

GetCtrlVal (panelHandle, PANEL_COLOR, &color);


SetCtrlAttribute (panelHandle, PANEL_VISUALIZADOR, ATTR_PLOT_BGCOLOR, color);
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) {

GetCtrlVal (PANEL, PANEL_BINARYSWITCH, &modo);


if (modo==1)
{
filehandle = fopen (pathname, "a+");
}
if (modo ==0)
{
filehandle = fopen (pathname, "w+");
}
fprintf (filehandle, "SEÑAL ADQUIRIDA DEL ELECTROCARDIOGRAMA \n\n");
fprintf(filehandle, "Puerto de Adquisición: PUERTO COM%d\n", port);

fprintf(filehandle, "Fecha %s Hora: %s \n", DateStr(), TimeStr());


fprintf (filehandle, "----------------------------------\n");
for (i=0;i<numero_puntos;i++)
{
fprintf (filehandle, "%f\n", muestras[i]);
}
fprintf(filehandle,"\nNúmero de puntos de la pantalla: %d\n",i);
fprintf(filehandle,"\nLocalización: %s\n\n\n",directory);
fclose (filehandle);
SetCtrlAttribute (panelHandle, PANEL_VIEWDATA, ATTR_DIMMED, 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);
}

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++)
{
status = ScanFile (file_handle, "%s>%f[x]", &muestras[i]);
}
ClearStripChart (panelHandle, PANEL_VISUALIZADOR);
for (i=0;i<numero_puntos;i++)
{
PlotStripChartPoint (panelHandle, PANEL_VISUALIZADOR, muestras[i]);
}

CloseFile (file_handle);

}
return (0);
}

int CVICALLBACK _umbral (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:
GetCtrlVal (panelHandle, PANEL_UMBRAL, &umbral);
umbral_g = umbral;

break;
}
return 0;
}

int CVICALLBACK medidatiempos (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

//cosas medida de tiempos


SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO, 0.0);
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO2, 0.0);
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO3, 0.0);
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO4, 0.0000);
auxi1=0.0;
auxi2=0.0;
DisplayPanel (panelHandle2);
SetCtrlAttribute (panelHandle2, PANEL2_TIMER2, ATTR_ENABLED,0);
break;
}
return 0;
}

int CVICALLBACK regreso (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

HidePanel (panelHandle2);
tiempo =0;
ini=0;
SetCtrlAttribute (panelHandle2, PANEL2_TIMER2, ATTR_ENABLED,0);
break;
}
return 0;
}

int CVICALLBACK timer (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_TIMER_TICK:

//tiempo = tiempo+1;
//SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO, tiempo);

break;
}
return 0;
}

int CVICALLBACK botoninicio (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

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;
}

int CVICALLBACK borrado (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event) {
case EVENT_COMMIT:

//cosas medida de tiempos


SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO, 0.0000);
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO2, 0.0000);
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO3, 0.0000);
SetCtrlVal (panelHandle2, PANEL2_CAJATIEMPO4, 0.0000);
break;
}
return 0;
}

int CVICALLBACK salvarsenal (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{

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);

if (FileSelectPopup (directory, "*.sen", "SEN Files", "Salvar señal a disco",


VAL_SAVE_BUTTON, 0, 1, 1, 0, pathname) > 0)
{
file_handle = OpenFile (pathname, 2, 0, 1);
for (i = 0; i<numero_puntos; i++)
{
FmtFile (file_handle, "%s<%f\n", muestras[i]);
}
CloseFile (file_handle);
}

break;
}
return 0;
}

int CVICALLBACK cargarsenal (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{

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++)


{
status = ScanFile (file_handle, "%s>%f[x]", &muestras[i]);
}
ClearStripChart (panelHandle, PANEL_VISUALIZADOR);

for (i=0;i<numero_puntos;i++)
{
PlotStripChartPoint (panelHandle, PANEL_VISUALIZADOR, muestras[i]);
}

CloseFile (file_handle);

}
return 0;
}

int CVICALLBACK borra_evolu (int panel, int control, int event,


void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:

ClearStripChart (panelHandle2, PANEL2_HISTOGRAM);

break;
}
return 0;
}

You might also like