UNIVERSIDAD AUTONOMAMETROPOLITANA UNIDAD IZTAPALAPA 'DIVISION DE CIENCIAS BASICAS 'LICENCIATURA E INGENIERIA EN INGENIERIA BIOMEDICA INSTRUMENTACION MEDICA ELECTRONICA 'PROCESAMIENTO DE UNA SEÑAL DE FONOCARDIOGRAFIA EN TIEMPO REAL ASESOR : Ing. Miguel Angel Peña Castillo ALUMNO: / Juan Hernández Cervantes México, D.F. , 1996. .. i UNIVERSID AUTONOMA ME ROPOLITANA h - PROCESAMIENTO DE UNA SEÑAL DE FONOCARDIOGRAFIA EN TIEMPO REAL- Vo. Bo. f\ INTRODUCCION Es común en la actualidad observar en los equipos médicos, va sea de diagnóstico o de terapia, lapresencia de dispositivos electrónicos y dispositivos de potencia que permiten ser integrados para lograr métodos de control de procesos, tanto más precisos como más eficientes, los cuales hoy endía,con los avances enla tecnología de dispositivos integrados, logran grandes velocidades de procesamiento de información. Lo anterior permite hacer el control de todo un proceso en diferentes faces, en muchos casos estos procesos se llevan a cabo en los que conocemos como tiempo real. Con la ayuda de estas herramientas el desarrollo del procesamiento digital de sefialese imágenes, hoy en día, existe unamplio campo de aplicación en el área médica e industrial. Como se menciona anteriormente, hoy podemos observar equipos como: imágenes ultrasónicas en tiempo real , detección de frecuencia cardiaca por ultrasonido, medición de parámetros de oximetría y, en general, aquellos equipos que se relacionan con la medición de yarámetros en forma instantánea que son de gran utilidad, ya que se puede determinar el diagnóstico o la terapia adecuada casi en el momento, por lo tanto, el diagnóstico y/o terapia serán más precisos. Dentro de la tecnología médica, la implementación de dispositivos que permitan al usuario un mejor análisis de la información obtenida es de gran importancia. Sin embargo, el diseño yeltipo de tecnología que se utilizará debe ser considerada; puesto que, de esto depende una mejor obtención de resultados en condiciones más confortables para el paciente y que a la vez el dispositivo cuente con todos los medios necesario para su buen desempeiio. La utilidad de las herramientas matemáticas para el procesamiento de señales es importante, ya que permite que la información oculta en las señales fisiológicas, como el electrocardiograma o fonocardiografía, sea posible observarla gráficamente o en forma numérica. Aún existen aplicaciones en las cuales la utilidad de las herramientas matemáticas del procesamiento de señales y surelación con la tecnología de dispositivos electrónicos, son de gran importancia, que, aplicadas al desarrollo de nuevas técnicas de detección de parámetros médicos, siguen en desarrollo o estána prueba. En al algunos casos de estos algoritmos, donde esta involucrado el ciclo cardiaco, utilizan principalmentela detección del complejo QRS. Sin embargo, como es de esperar se requiere la aplicación de electrodos para su detección. En el presente trabajo se muestra un algoritmo de detección del ciclo cardiaco en basealadetección de picos generados por la presencia de ruidos cardiacos. Cuando escuchamos con u n estetoscopio el coratdn que late, se perciben normalmente dos ruidos que podrían describirse con las sílabas "lub,dub; lub,dub; lub,dub". El "Lub" es el primerruido cardiaco, y el "dub" esel segundo ruido cardiaco. El primer ruido cardiaco es producido es producido por el cierre de las válvulas AV (aurículo-ventriculares) cuando se contraen los ventrículos, v el segundo ruido lo causa el cierre de la válvula aórtica y pulmonar alfinal de la contracción. Entonces, la representación gráfica de estos ruidos se conoce como fonocardiograma. La detención súbita del flujo retrógrado desde los ventrículos hacialas auriculas crea vibración de la sangre y de las paredes cardiacas; estas vibraciones se transmiten hacia la pared torácica y se escuchan como primer ruido. Inmediatamente después que los ventrículos han descargado su sangre en el sistema arterial, la relajación ventricular subsecuente permite que empiece a fluir sangre de nuevo desde las arterias hacia los ventrículos, por lo tanto hace que se y pulmonar. Estodesencadena también cierren súbitamente lasválvulasaórtica vibraciones, esta vez en la sangre v en las paredes de las arterias aorta y pulmonar lo mismo que en los ventrículos. Esta vibraciones se transmiten hacialapared torácica y se producen los ruidos que escuchamos. Es importante mencionar que encada evento, relacionado con el ciclo cardiaco, están involucrados otros eventos como: el ruido respiratorio, el movimiento muscular y ruido exterior. Por lo tanto, el procesamiento de estas señales; implica la eliminación de elementos indeseables, de tal forma que se logre lo mejor posible el registro del evento deseado (En este caso el latido del corazón). Entonces como primer paso es la detección de estos ruidos, el método que todos conocemos es mediante un transductor de sonido (micrófono o bocina) y un amplificador de instrumentación. Esto en principio no esta tan complicado y no es la parte importante del trabajo (Esta parte será complementada con los dispositivos existentes en el laboratorio). La tarea principal, es la conversión A/D de la señal de ruido y la necesaria separación de los componentes presentes no deseados enla misma; utilizando las herramientas antes mencionadas. Todo el proceso que más adelante se describe, contiene la información acerca del los dispositivos utilizados, una relación de las consideraciones del laspartes principales configuradas, los procesos matemáticos utilizados y la importancia en la partedel proceso y, además la parte más importante, a juicio propio, la detección de los picos que durante el proceso se manejan con dos criterios importantes: la amplitud del pico y la distancia pico a pico. Todo esto se espera nos de corno resultado el objetivo principal, el ciclo cardiaco. la automatización del método de Con el presente trabajo se busca a registrosde medicióndelciclocardiacofetalentiemporeal,enbase fonocardiografía. Esto presenta una idea que pueda sugerir una implementación del algoritmo más eficiente para esta aplicación. Anteriormente,cuandosedesarrollo el método,fueaplicado a registros presentes en archivos, en base a las referencias se obtuvieron muy buenos los datos resultados. Sin embargo, la forma en como fueron manipulados en ese caso fue utilizando estructuras de listas. Respecto a este punto se menciona la justificación del porque no se utilizó estemismométodode la relaciónqueexisteentre el manejo de datosenestetrabajo.Además y eldispositivo que provee la procesodedetección del ciclocardiac0 información. CONTENIDO Sección I I. 1.- Especificaciones de la tarjeta PC-LAB 812. I. l . 1.- Convertidor A/D. I. 1.2.- Contador/Temporizador Programable. I. 1.3.- Canales de interrupción . I. 1.4.- Especificaciones Generales. I. 1.5.- Diagrama a Bloques de la Tarjeta. I. 1.6.- Selección de la B a s e de direcciones. I. 1.7.- Selección del con tador. I. 1.8.- Selección de línea de interrupción(1RQ). I. 1.9.- Estructura de Registros y Formato. I. 1.9.1.- Mapeo de los puertos de entrada/salida (I/O). 1.1.9.2.-Registro de Datos en el modo A/D. 1.1.9.3.- Registro de selección del Canal de Conversión. 1.1.9.4.- Registro de Control de PCL-812. I. 1.10.-El Intel 8253. I. 1.10.1.- Escritura/Lectura al Contador y Registros de Control. 1- 1 1-1 1-2 1-2 1-2 1-3 1-4 1-4 1-5 1-5 1-5 1-6 1-7 1-7 1-7 1-8 Sección I1 11.1.- Desarrollo de la interface PC-PCLAB. 11. l . 1.- Programación"de los Contadores (timer-S). 11.1.1.1.- Listado del programa que Configura la Frecuencia de Muestreo. 11.1.2.- Habilitación del vector de interrupción. 11.1.3.- Transferencia de datos a la memoria. 2- 1 2-2 2-2 2-4 2-1 1 Sección I11 111.1.- Diagrama a Bloques del Algoritmo. 3- 1 Sección IV IV. 1.- Desarrollo del sofware. IV. l . 1.- Módulos del Algoritmo. IV. l . 1 .-1Búsqueda por Amplitud. IV. l . 1.2- Búsqueda por Distancia entre Picos. 4- 1 4-29 4-29 4-34 Sección V V.1.- Gráficas de Respuesta de los Filtros. 5-1 Sección VI V.1.- Manual de usuario. 6- 1 Sección VI1 OBSERVACIONES. COMENTARIOS. CONCLUSIONES. Anexo Bibliografia 7-1 7-2 7-3 1 - 1 I. 1.- Especificaciones de la Tarjeta PC-LAB 812 La tarjeta PCL-812 es de alto desempeño, alta velocidad y con múltiples las funcionesdeadquisicióndedatosparaIBMPC/XT/AT.Dentrode aplicacionesmáscomunesincluye la adquisicióndedatos,procesos de control, pruebas automáticas y automatización por factores. Especificaciones importantes: I.1.1.- Convertidor A/D Canales : bits. 16 canales. 12 Resolución: RangodeVoltaje: + / - lOV, + / - 5 v , + / - 2 v , + / - 1v. Todos los rangos de entrada son seleccionables por interruptores. Protección contra sobre voltaje: Rango continuo de +/ - 3 0 V máximo. Tipo de conversión: Aproximaciones sucesivas. i Modelo del convertidor: HADC574Z Velocidad de conversión: 30KHz máximo. Precisión: 0.015 Yo de la lectura + / - 1 bit. Linealidad: + / - 1 bit. Modo de disparo: Disparo por software, contador programable incluido en la tarjeta o disparador externo (pulso externo). Transferencia de datos: Controlado por programa (poleo), controlado por interrupción o transferencia por DMA. Disparo externo: Compatible con TTL. 1-2 I. 1.2.- Contador/Temporizador Programable Dispositivo: INTEL 8 2 5 3 - 5 . Contadores: 3 canales, 16 canales bits. 2 permanentemente conectados a u n reloj de 2MHz como contador programable, 1 canal libre para aplicación del usuario. Compuerta de entrada: Compatible con TTL/DTL/CMOS. B a s e de tiempo: 2MHz. Rango de frecuencia programable: 35 minutos/pulso hasta 0.5MHz. I. 1.3.- Canales de interrupción Nivel: IRQ 2 a 7 , seleccionable puentes por % Habilitación: Vía de registro de control (jumper's). SO, S 1 y S 2 . I. 1.4.- Especificaciones Generales Consumodeenergía: + 5V @ 500mA, 1A máximo. + 12V @ 50mA, 1 O O r n A máximo. -12V @ 1 4 d , 20rnA máximo. Conector Entrada/Salida ( W ) : entrada puerto Analógica/Digital. 20pin para de B a s e de Direcciones (I/ 0): Requiere 16 direcciones memoria deconsecutivas. La base de direcciones esta definida por 1-3 interruptores tipo DIP, líneas para direccionamiento son: A8-A4. de Temperatura de Operación: O a +50 “C. Temperatura de Almacenamiento: -20 a +65 “C. Peso: 8.6 oz (242.89 gm). 1.1.5.- Diagrama a Bloques de la tarjeta nnnnn ww 111SSY 2L( ANA “<CH 16 CHANNEL SDIGLB END “<CH O ANALOG INPUT 1-4 I. 1.6- Selección de la Base de Direcciones Nombre del interruptor : sw1. Muchos dispositivos periféricos de PC y tarjetas de interface son Estos puertos utilizan controladas a través de puertos de entrada salida. un espacio de direcciones. Labasededireccionesdelpuertodeentradasalidapara la tarjeta PCL812 esseleccionableconinterruptorestipo DIP. La PCL-812 requiere 16 direcciones consecutivas. Las direcciones validas están en el rango 200 a 3F0, sinembargopuedenserutilizadasestas Hexadecimalde direcciones para otro dispositivo. A continuación se proporciona una tabla de direcciones seleccionables. Direcciones I / O Posiciones de los Interruptores Rango en Hexadecimal A9 1 2 A8 A6 A7 3 4 5 A5 A4 O O O 1 1 O 1 O (fijo) 200-20F 2 10-2 1F 220-22F' 300-30F3 3FO-3FF 1 O 1 O 1 % O 1 220-23FO 1 1 1 1 I. 1.7.- Selección del contador Puente selector( Jumper ) : JP2 I NT El EXT O . CLK Especificada por fabricante. ' Base de direcciones utilizada . O O O O O O O O O 1 1 O 1 1 O 1 1-5 1.1.8.- Selección de Línea de Interrupción (IRQ) Puente selector : JP4 2 3 4 5 6 O O O O O O O O O O 7 O ** X [ * * Determina.da por fabricante. ** Seleccionada por usuario. 1.1.9.- Estructuras de Registros y Formato 1.1.9.1.- Mapeo de los puertos de entrada /salida (I/O) La siguiente tabla muestra la localización de cada registro y el control de la base de direcciones, y el uso de esta. c Localización Lectura Escritura B a s e +O Contador O Contador O B a s e +1 Contador 1 Contador 1 Base +2 Contador 2 Contador 2 B a s e +3 N/U Control de contador B a s e +4 A/D byte bajo CH1 D/A byte bajo B a s e +5 A/D byte alto CH 1 D/A byte alto B a s e +6 D/I byte bajo CH2 D / A byte bajo B a s e +7 D / I byte alto CH2 D/A byte alto 1 - 6 Base +8 N/U B a s e +9 N/U B a s e +10 N/U B a s e +11 N/U B a s e +12 N/U Base +13 N/U B a s e +14 N/U B a s e + 15 N/U deAviso atención de interrupción (Clear interrupt request) N/U MUX (selección del canal de conversión) PCL-8 Control de 12 (habilitación de línea de interrupción) modo Selección de transferencia de transferencia de datos. D/O byte bajo. alto. D / O byte 1.1.9.2.-Registros de Datos en el m o d o A / D Los registro de datos usados por las direcciones Base +4 y Base +5. Formato de datos: l . A/D Byte bajo. Base +4 D7 D6 D5 D4 D3 D2 Dl A AD D7654321 ADO 2. A/D Byte alto. Base +5 D7 D6 D5 D4 O DO D3 O O DRDY AD11 AD10 AD9 D2 Dl DO AD8 AD 11 a ADO - Analógico a dato digital. ADO-AD7 e s el byte menos significativo (LSB) y AD8-AD 11 e s el byte m á s significativo (MSB) de el dato convertido. Como se había mencionado anteriormente la resolución del convertido e s de 12 bits distribuidos en dos registros. DRDY - Señaldedatoconvertido. O: Datoleído, 1 : Datono leído. Al momento de leer el registro (Base +5) este bit debe ser puesto a cero o limpiado. 1 - 7 Al unir el resultado de ambos registros, además de limpiar el bit dato final es el valor de conversión A/D. DRDY, el 1.1.9.3.-Registro de selección de Canal de Conversión Este registro e s solo de escritura usando la base de direcciones Base+lO. El multiplexor (MUX)cambia a un nuevo canal de conversión cuando se escribe sobre este registro. Formato: Base +10 D 7 D2 D3 D4 D5 D6 X x DI x x CL3 - Númerode canal de conversión CLO - CL3 CL2 CL1 DO CLO A/D. 1.1.9.4.-Registro de Control de PCL-812 El registro de control de PCL-812; es un registro de solo escritura y usa la dirección Base “-1l . Este registro provee información del modo de operación de la PCL-8 12. Formato: Base + 1 1 D4 D3 D6 D5 D7 PCL-8 12 CNTL status X x x x X D2 Dl DO S2 S1 so Bajo las siguientes condiciones internas de disparo: S2 S1 so o O O 0 0 0 1 0 1 1 1 1 : Software deshabilitado. : Habilitación de disparo solo por software. : Habilitación de disparo usando transferencia por DMA solamente. : Habilitación de disparo usando transferencia por programa o transferencia por interrupción. Si es transferencia por programa, el puente (jumper) JP4 debe estar en la posición “X”, como se menciona anteriormente. 1 - 8 I. 1.10.- El Intel 8253 La PCL-812 usa el INTEL 8 2 5 3 como un contador de intervalo programable un temporizador/contador muy común, este versión 5. El 8253 es 16 bits.Cada dispositivoconsistedetrescontadoresindependientesde contador tiene un reloj de entrada, la compuerta de control y una salida. Estos pueden ser programados con cuentas desde 2 hasta 65535. La máxima frecuencia del reloj de entrada es de 4MHz para la versión 5 del 8 2 5 3 . La PCL-812 contiene un oscilador de 2MHz de frecuencia a través de un cristal oscilador. Los contadores 1 y 2 estan conectados en cascada y operan como divisores defrecuencia(configuracióndivisor fijo). La entradadelcontador 2 esta conectada al reloj de frecuencia de 2 M H z y la salida de este esta conectada a laentradadelcontador 1 . Lasalidadelcontador 1 estaconfigurada internamente como el pulso de disparo del convertidor A/D.El contador O no esta reservado para la PCL-812 en cualquier uso interno, y su acceso e s a través de conector 5. I. 1.10.1.-Escritura/Lecturaal Contador y Registros de El 8253 usa cuatro registros de control con direcciones Base Base +2 y B a s e +3. La función de cada registro es: Control +O, Base + 1 , Base +O Contador O Lectura/Escritura Base +1 Contador 1 Lectura/Escritura B a s e +2 Contador 2 Lectura/ Escritura Base+3Palabradecontroldelcontador Desde que se empezó el uso de una estructura de 16 bits en el contador 8253, cada lectura/escritura de un dato debe hacerse en dos partes en un byte menos significativo y u n byte m á s significativo. Esto e s importante ya que la operacióndelectura/escrituradependedeun par dedatos y el orden en que estos bytes son utilizados. 1-9 Formato de los Datos y el registro de control: Base +3 D7 D6 D5 D4 D3 D2 D l sc 1 SC 1& SCO SCO RW 1 RWO M2 M1 M.O DO BUD O 1 1 1 Y 1 1 O 1 O 1 1 x 1 1 O - VALORES UTILIZADOS 76H B6H Bits de selección de contador. sc 1 SCO Contador O O O 1 O 1 O 1 2 No existe 1 1 RW1 & RWO - Bits de selección de modo Lectura/Escritura. RW 1 RWO Operación O O 1 1 O 1: O 1 Counter Latch Lectura/Escritura LSB. Lectura/Escritura MSB. Lectura/Escritura primero LSB, después MSB. M2,M 1 y M 0 M1 M2 O O X X 1 1 O O 1 1 O O - Selecciona el modo de operación. M0 Modo O 1 O 1 O 1 O123 4 5- Interrupt terminal on count. Programable one shot. Rate generator . Square wave rate generator. Software triggered strobe. Hardware triggered strobe. I 1 BUD - - 10 Modo deconteo. BUD Tipo O 1 Contador binario de 16 bits. Contador en código decimal (BUD), contador en décadas. 4 2-1 PI. 1.- Desarrollo de la interface PC-PCLAB El hechodehaberimplementadomódulosenensambladoresdebido a que; es más sencillo de controlar la escritura en los registros de control. la interface(ensamblador)una vez implementadosson Losmódulosde ligadosalprogramaprincipaldeC,estosmódulosdeensambladorson al programaprincipal y parahacerusode consideradoscomoexternos ellos se definen con el prefijo EXTERN, lo cual permite que sean importadosestosmódulosdeensambladoralprogramaprincipalenC como se muestra en el siguiente bloque del listado. extern void DIVIDE-FREC(void); extern void ADQUISICION(void); extern void REESTABLECE(void); extern int indicador-coloca-ind; Lasvariablesutilizadasenensambladorquepermitenelcontroldela dependen del valor que se les asigne en el programa tarjeta y que principal, estan definidas como variables globales en C, como se puede ver en el parrafo del listado, int int int int DIVISOR; NUM-CANAL; Muestras-Tot; *BLOQUE-AUX-NULL; a estasvariablesnoes comosepuedeobservarenelpárrafoanterior, necesario agregarles el prefijo EXTERN. Paradefinir las variablesenensambladorcuyosvalorseextraen del programa principal(implementaci6n en C) se definen con el prefijo EXTERN, mientras que las variables y procedimientos que son utilizados en módulos implementados en C se definen con el prefijo PUBLIC. DATASEG EXTRN EXTRN public -BLOQUE-AUX:WORD -Muestras-Tot:WORD -indicador-coloca-ind CODESEG public -ADQUISICION public"REESTABLECE 2-2 el párrafo anterior muestra un ejemplo de transferencia de parámetros C a ensamblador y viceversa. de 11.1.1.- Programación de los Contadores ( timer’s) Es preciso mencionar que la frecuencia de muestreo elegida sea la frecuencia de la señal que se obtenga a la salida de los contadores, esta puedesermedidaenel pin 7 del timer;yaquedeestodependela v a directamenterelacionada precisióndelafrecuenciademuestreo,que con el resultado de los datos capturados y de los cálculos. La base de direcciones donde quedó instalada la tarjeta es la 300h. 11.1.1.1.- Listado del Programa que Configura la Frecuencia de Muestre0 El siguientes segmento de programa define : una dirección hacia el puerto SEL-C 1 SEL-C2 CONTl CONT2 PAL-CONT EQU EQU EQU EQU EQU 076h Ob6h 0301h 0302h 0303h C-GAN MODO-TRANS EQU EQU 0309h EXTRN -DIVISOR: WORD 030Bh a las constantes que contiene ;Selecciona contador 1 ;Selecciona contador 2 ;Dirección del contador 1 ;Dirección del contador 2 ;Dirección de palabra de control de 8 2 5 3 ;Control de ganancia ;Controla el modo de transferencia de datos. ;Variable importada desde C , la cual ;tiene el valor del ;divisor de frecuencia que se utilizara ;para programar el timer. CODESEG public-DIVIDE-FREC ;Nombre de el procedimiento que ;será exportado a C. 2-3 PROC SI push push push push push DS push -DIVIDE-FREC DI SS cx BX sub push push A x , = mov mov AX,@data DS,AX mov ES , A X mov NEAR ;Guarda el ambiente Ax ES AL,SEL-C 1 mov DX,PAL-CONT out mov DX,AL AX,[-DIVISOR] mov DX,CONTl ;Localiza dirección del segmento de datos. ;Carga en DS la dirección del segmento ;de datos. ; Ahora la dirección del segmento de ; datos en ES. ;Recibe la palabra de control para ;contador # 1 en AL. ;Dirección del puerto a donde se envía ;la palabra de control. ;Envia palabra de control al registro. ;Toma el valor de divisor (valor calculado ;en C). ;Recibe dirección del contador ##l. ; Escribiendo en el puerto (programa frecuencia de muestre0 en ; contador # 1). out xchg out DX,AL AL,AH DX,AL mov AL,SEL-C2 mov DX,PAL-CONT' DX,AL out ;Envía palabra puerto. control de al mov mov AX,[-DIVISOR] DX,CONT2 ;Envia byte más bajo de la palabra. ;Envía byte mas alto. ;Selecciona al contador numero#2. ;Toma la palabra de control. ;Toma el valor de divisor. ;Toma la dirección del contador2 2 - 4 out xchg out mov mov out mov mov out mov mov out DX,AL ;Envía el byte más bajopuerto. al AL,AH DX,AL ; Envía el byte más alto DX,MODO-TRANS ; Avisa a la tarjeta cual es el modo de ; transferencia de AL,OGh ; datos vía interrupción . DX,AL DX, C-GAN ; Selecciona el modo de ganancia unitaria. AL,OOh DX,AL DX,CAN-MUX ; Indica el canaldeconversión inicial. ; Canal de cero inicio AL,OOh DX,AL POP POP POP POP POP POP POP POP POP ES Ax DS BP BX ; restaura AMBIENTE cx SS DI SI ; Termina procedimiento RET a ENDP -DIVIDE-FREC ; Fin de procedimiento. END 11.1.2.- Habilitación del vector ;/ /Definición de la constates 0304h EQU BYTE-BAJO BYTE-ALTO C-GAN EQU CAN-MUX MODO-TRANS EQU EQU 0305h EQU 0309h 030Ah 030Bh de interrupción ; Byte menos significativo del dato ; convertido ; Byte mas significativo del dato ; convertido ; Control de ganancia ; Controldelmultiplexor para ; los canales ; Registrodel controldetransferencia 2-5 ; de datos Bandera-Int Limp-Peticion SERV-251 0308h OFFh 250Bh EQU EQU EQU SERV-351 EQU HABILITA-IRQ DESHAB-IRQ FIN-INTERRUP ;Registro para limpiar interrupción ; Aviso de interrupción atendida. ;Servicio de int2 1, para obtener ; vector ; Servicio int2 de 1 , para poner ; vector ; Habilita interrupción para IRQ3 ; Deshabilita IRQ3 ; Para indicar al 8 2 5 9 q u e y a s e ; atendió la interrupción 350Bh EQU EQU EQU OF7h 08h 20h ; / / Inicio del segmento de datos: DATASEG EXTRN -BLOQUE-AUX:WORD ; Apuntador al inicio del bloque ; de direcciones donde ; se guardarán los datos. EXTRN -Muestras-Tot:WORD ; Contiene el numero de muestras ; que se están capturando por bloque public -indicador-coloca-ind -indicador-coloca-ind -indicador-coloca DW DW O O Old-HandSeg DW O Old-HandOfs Dato-Actual DW DW O O Canal-Actual DW O ; Indice para el control de los ; apuntadores que accesan ; al arreglo donde se guardan los ; datos. ; Inicializa índice el ; Contiene la dirección del ; bloque ; Segmento del vector ; original ; Offset del vector antiguo ; Apuntador de numero de ; datos adquiridos ; Apuntador a canales ; Inicia el segmento de código: CODESEG ; Nombres de los procedimientos que serán exportados al modulo de "C". I 2-6 public -ADQUISICION public-REESTABLECE ; Inicia procedimientos: PROC push push push push push push push mov mov mov rnov mov mov mov -ADQUISICION NEAR SI DI SS cx ; Guarda el ambiente BX Ax ES AX,@data DS,AX ; Localiza dirección del segmento de datos ; y carga dicha direccion DS en i y ES ES,AX AX,[-Muestras-Tot] [Dato-Actual],AX AX ,[-BLOQUE-AUX] [indicador-coloca] , AX ; Obtiene el tamañodelbufer y ; lo guarda en la variable ; Obtiene la direcciondememoria ; donde ; seránguardadoslosdatos ; / / Colocación del nuevo vector de interrupción push mov ES AX,SERV_351 in t 21h mov [Old-HandSeg],ES mov [Old-HandOfs],BX POP push mov ES DS AX,SERV-251 ; Salva registro ; Coloca en AH=35 que es el ; servicio de interrupción ; para obtener el vector de ; interrupción del COM2 ; con dirección OBH y cuyo valor ; de dirección se coloca en AL. ; Llamada a la interrupción 2l h del ; bios para obtener el vector. ; Salva el valor del segmento del ; vector antiguo ; Salva el offset del vector antiguo ; Guarda el registro ; Coloca en AH=25 que corresponde ; al servicio de interrupción ; para colocar un nuevo vector y en 2-7 ; AL se coloca OBH que corresponde ; a la dirección de puerto COM2 ; que es donde esta el dispositivo ; que generará la interrupción. push CS POP mov DS DX,offset -1SRQ int 21h POP DS hace ; Se CS=DS que la dirección a ; donde v a a saltar cuando ; El dispositivo interrumpa. ; Obtiene la dirección de la rutina ; de interrupción . ; Llamada a la interrupción 2 1 h ; para colocar al fin el nuevo ; vector de interrupción. ds.; Restaura ; Programación del controlador de interrupciones 8259 y ; habilitación del IRQ3(línea de requerimiento de interrupción). mov in and DX,AL out sti DX,02 1 h AL,DX AL,HABILITA-IRQ mov DX,MODO-TRANS mov DX,AL out AL,OGh ; Habilita la IRQ3 ; Habilita la tarjeta para el modo ; de transferencia de datos ; los (por interrupción ). ; Restaura ambiente RET ENDP -ADQUISICION ;/ / Procedimiento que reestablece el vector de interrupción original. I 2 - 8 PROC -REESTABLECE NEAR cli push push push push push push ES push SI DI SS CX BX AX mov AX,@data mov mov DS , A X ES ,AX ; Guarda el ambiente ; Localiza dirección del segmento ; de datos ; y carga dicha dirección enDS y ES ; / / REGRESAESTADOANTERIORDEL IRQ3 push DS mov AX,SERV-251 mov DX,[Old-HandOfs] mov DS,[Old-HandSeg] 21h int POP DS mov DX,02 1h AL,DX in or AL,DESHAB-IRQ mov DX,02 1h DX,AL out ; salva DS ; Pone el vectorinterrupción de ; Toma el valor del offset guardado ; Obtiene el valor del segmento ;. Deshabilita IRQ3 ; Restaura ambiente sti RET ENDP "REESTABLECE 2-9 ;/ /Inicio de rutina de atención a interrupción (servicio de interrupción) PROC -1SRQ NEAR cLI PUSHAX PUSHBX PUSHCX PUSHDX PUSH SI PUSH DI PUSHDS PUSH ES PUSHBP PUSHF mov AX,@data mov DS,AX mov ES,AX ; Guarda ambiente ; Localiza dirección del segmento dseg ; Carga en D S la dirección del ; segmento ; de datos al igual que en ES. ;Lee el registro donde se encuentrael ;dato convertido, que corresponde al ;byte mas significativo ;Lee el registro donde se encuentra el ;dato convertido, que correspondeal ;byte menos significativo ;Ajuste del valor leído, and A X , O f f f h ;limpia bit DRDY. ;Autoincremento de DI al utilizar cld mov DI, [-indicador-coloca] ;Carga la dirección de apuntador a ; memoria en DI stosw ;Guarda el dato leído en la dirección ;apuntada por DI mov [~indicador~coloca],DI inc [-indicador-coloca-ind] dec [Dato-Actual] ;Actualiza numero datos de jne TERMINA mov DX,BYTE-ALTO AL,DX in xchg AH,AL mov DX,BYTE-BAJO AL,DX in mov ax,[-Muestras-Tot] mov [Dato-Actual],ax 2-11 11.1.3.- Transferencia de datos a la memoria Otra parte importante de la interface e s la transferencia de los datos convertidos para completar el ciclo. Para decidir que arreglo de memoria o el tipo de memoria que se v a a utilizar, se consideran los siguientes puntos: 1 ) Se requiere para la aplicaciónuntipodememoriaquepermitaunaccesomásrápido a los El tamañodememoria datoscontansolomoverundesplazamiento;2) debeservariable; y 3) Debido a que essonutilizadosmódulosen ensamblador,serequiereun tipodememoriaquepermitamanejarun menor numero de variables en ensamblador. De manera que, el periodo en que son almacenados los datos (en el servicio de interrupción) sea lo más pequeñoposible.Estopermitereducireltiempodeacceso a memoria. Comparandocon unaestructuradedatos, el acceso es más lento a los datosenmemoria y al pasar unadireccióndememoria al moduloen ensamblador es más lento; debido al procesodeconexiónenlosnodos, en el caso de listas ligadas. De acuerdo a las consideraciones anteriores, se utiliza u n arreglodememoriasecuencial y de tamañovariable.Este arreglosecuencialpermiteserutilizadocomo un arreglo circular, lo cual da como ventaja el que no es requerido solicitar más memoria cuando se hallallenado el arregloenlaultimaposición, el desplazamientoquees a unadeterminadaposiciónsolose utilizado paramoverelapuntador inicializa para seguir capturando nuevos datos. Este bloque de programa Irnuestra la forma de como es definido el espacio de memoria ó arreglo: void Aparta-Bloque(int MTOTAL) BLOQUE-ASIG=(int *)malloc(2*MTOTAL);/ /Tamaño total de memoria. if(BL0QUE-ASIG==NULL){printf("No hay memoria"); getch();exit(1 ) ; } apuntador-auxiliar=BLOQUE_AUX=BLOQUE_ASIG; 1 I el modulomostradoanteriormentedevuelveunapuntador al inicio del al modulo de ensamblador, y pormediode la bloque, el cual es enviado suma de un índice es desplazado el apuntador a los diferentes espacios de memoria que ha sido reservada previamente, cada vez que es capturado u n nuevo dato. Es precisomencionarqueseutilizandosapuntadores,unopara y otro paraleerlos,entonces;unoesmanipuladoen guardar datos ensambladorcuandosepresentaunainterrupciónyelotrocuandoes leído un dato. Por lo tanto, podemos tratar con dos apuntadores uno de . . ., . . . .. - . . 2 - 12 escritura y uno de lectura, que necesariamente deben ser controlados para evitar que la escritura y lectura sean simultáneas. Para evitar esto podemos mostrar las siguiente líneas de un modulo en C , Real GraficaDatoNoPrc(int VERT-MAX,int cuenta-bufer) Real escalador1 ,nuevoDato; escalador 1 =4095/(Real)VERT-MAX; / /Factor de escalamiento / / Si esta activa la tarjeta espera que el apuntador de escritura sea mayor / / que el apuntador de lectura. if(archiv0Tarjeta) while(indicador-coloca-ind==cuel1ta_bufer); nuevoDato=apuntador~auxiliar[cuenta~bufer]; / /Lee el nuevo valor. return(nuevoDato/escalador1 ) ; / /Retorna valor normalizado \ con las variables “indicador-coloca-ind” y “checa-mem”, que son los desplazamientosenelarreglo,esposibleevitarquelosapuntadoresse traslapen y solo es necesario verificar que la varible “indicador-coloca-ind” sea siempre mayor que “checa-mem” ; esto garantiza que el apuntador de escritura siempre irá adelante del apuntador de lectura. 3-1 111.1 .-Diagrama a Bloques del Algoritmo DERI\'ACION __ PASA BANDA 20 A 30Mz 4 100 A 110Hz B'llSCA -PICOS I - PROhlEDlA -PICOS I ENCC'ENTRA EN E L PROhlEDlO I 4PICOS PROhlEDIA 'PICOS I I Y DESVIACIOS I m INTERVALO ENTRE PICOS I L EXISTE INTERVALO DE REFERENCIA? Ti=r*IIVTERVALO +b ' MIDE E L INTERVALO COK hllNlXlA DIFERENCIA TlEhíPO L EL MEDIDO > Ti? ' PICOS DESTRO DEL RANGO I IKTERVALO ENTRE PICOS 1SELECC;ONA E L MEJOR INTERVALO DE ACUERDO A LA REFERENCIA I I Durante la ejecución del programa, la adquisición de los datos se presenta con cada interrupción de la tarjeta cuando el convertidor tiene un nuevo dato,bloqueandoelprocesoenelqueseencuentreactualmenteenla ejecución del programa principal. 4- 1 IV. 1 .-Desarrollo del software Enunaseñalderuidoobservamosunaseriedepicosaleatorios.En el caso deruidocardiaco,aunquelossonidoscardiacossepresentende maneraregular,esdecircuandosepresentaunlatido;lospicosque conformanelruidonosonregulares.Por lo tanto,esnecesarioaplicar algunos procesos para lograr remarcar los picos importantes del ruido del picoÚnicoporlatido. Enestesentido, la latido y procurarobtenerun primera etapa del algoritmo se busca remarcar los ruidos, con las siguientes consideraciones: filtrar la señal en el rango de frecuencias en el la cualseencuentrancadauno delosruidos,estopermitetambién posibilidadde remarcarmas elprimero o segundoruido,eliminarlas componentes de frecuencia indeseables, en el monitoreo de sefiales , como ruido de línea, fisiológicas se presentan varias interferencias la segunda parte se artefactos de movimiento, ruido respiratorio, etc.; en registranloscambiosdeamplitud,con lo cual sedeseadespreciarlos picosqueesténdebajodeundeterminadoumbral,conundeterminado numerodemuestraspodemoscalcularunrangodeamplitudesqueno solo desprecian los picos por abajo del umbral, sino también los que sobre pasan elnivel superior;una vez detectadoslospicosporun nivelde la deteccióndeposibleslatidos, amplitud,secontinua elprocesocon midiendo la distancia entre picos. Ahora se muestra el listado del programa principal en “C”: Librerías utilizadas, estos archivos contienen el paquete de instrucciones utilizadas en cada parte o modulo del programa principal, por ejemplo: #include<stdio.h> #include<conio.h> #includecctype.h> #include<string.h> #include<dir. h> #include<io.h> #include<bios.h> //Contiene #include<dos.h> #include<math.h> #include<graphics.h> ., .. : bioskeyo / /Contiene : sqrt() / /Contiene : outtextxyo, setcolor(), / / line(), etc.. Toda instrucción que / / utiliza el modo gráfico. 4 - 2 Constantes que no se modifican durante el programa, esta corresponden de principalmente a teclas especiales, las cuales se utilizan como medios ejecucióndetareas,porejemplo:Llamada a filtros,reinicializaciónde variables,ademássedefineunalíneadeun tipode datos.Líneas del programa principal donde se definen como macros(en este caso son constantes): #define PINTA #define F2 #define F3 #defineARRIBA #define ABAJO Ox3B00 Ox3COO Ox3D00 0x4800 0x5000 #define Real #define taps #define memTotal #define NUMPICOS #define MUESTRAS #define TOTCOMPARA float //Define u n tipo de datos. 15 //Número coeficientes de del filtro. 20000 //Total de memoria utilizada para / /guardar los datos adquiridos. 3 / /Número picos de a detectar / /para comparar distancias. 15 / /Número de picos a detectar antes //de obtener promedios. 15 //Total picos depara calcular / /el primer promedio por / /amplitud. i MóduEos implementados en ensamblador: extern void DIVIDE-FREC(void); extern void ADQUISICION(void); extern void REESTABLECE(void); indicador-coloca-ind; int extern (única variable controlada exclusivamente en ensamblador y que cambia con cada interrupción, es utilizada principalmente para evitar que 'losapuntadores de escritura y lecturase traslapen, por lo tanto; en el programa principal solo se utiliza como un indicador). 4-3 VariabZes que importantes para cargar los datos capturados en y quesonutilizadastantoenensambladorcomoenprogramaprincipal la memoria “C”. int DIVISOR,NUM-CANAL,Muestras-Tot,*BLOQUE-AUX=NULL; Variables globales: int checa-mem; int contadorAmplitUno=O,contadorPicos=O, contadorPosiciones=0,posicionesDetec[NUMPICOS], distanciasDetec[MUESTRAS],contadorIntervalos=O; int *BLOQUE-ASIG=NULL,*apuntador-auxiliar=NULL; int frecuenciacanal=1 ,frecuenciaMuestreo= 1 ,canalGraficar= 1 ; Real distanciaMaxima=O,distanciaMinima=O,datoProcesado=O; Real primerRegistro=O,segundoRegistro=O; Real umbralNivel=O,SDamplitud=O,amplitudPromedio 1 =O, PrimAmplitud[TOTCOMPAP~],amplitudesDetec[MUESTRAS], intervaloPromedio= 1 ,frecuenciaAprox=O, variabilidadMuestras,SDintervalo,variabilidadHer~=O; Arreglos donde son guardados los coeficientes de los filtros: [taps]; Real taps1 [taps], taps2 Real arreglo1 [taps],arreglo2[taps],arreglo-fin[taps]; VariabZes quesonutilizadascomobanderasdeestadoqueindicanal programa los proceso que son o no realizables: int archivoTarjeta=O,corrimiento=O,existeReferencia; Definición de los módulos “Prototipos de Procedimientos”, en los cuales se aprecia el tipo de dato que devuelve y los parámetros que recibe: int PresentaMensaje(int cual); void CorregirCadena(char *cadena-a-mandar,int “bad-cad); void ReservaMemoria(int MTOTAL); void LiberaMemoria(v0id); int CargaDatos(void); void CargarBuffer(void); void Canal(void); . . . . . 4 - 4 int CargaTaps(int cualFiltro); int IniciaGraficos(void); void MuestraMensaje(int bandera,int xx1 ,int yyl ,int xx2,int yy2,char *mensaje,Real valor); void AmbienteDeGraficacion(int XXMAX,int YYMAX); void PresentaGrafica(v0id); Real ProcesaDatos(void); Real PrimerFiltro(int verifica-bufer); Real FuncionDerivada(Rea1 *conjunto); Real SegundoFiltro(Rea1 *arreglo-final); Real BuscaPicos(Rea1 muestra-act); Real PromedioPicos 1 (Real valor-pico-act); intCorrimiento(Rea1muestra-anterior); int SeleccionaIntervalo(int posicionActua1); int GuardaDistancia(Rea1 intervActua1); Real BuscaReferencia(int NuevaPosicion); int CompruebaDistancia(int distanciaAnterior,int disTancia); Real PromediaIntervalos(void); Real CalculaFrecuencia(int distanciaEntrePicos); Real VariabilidadDeFrec(Rea1 frecuencia); Implementación de los módulos: Módulo principal: int main(void) / /Inicio de programa.. . c h a r f; PresentaMensaje(0); do( PresentaMensaje( 1 ) ; f=getch(); switch(f){ case 'O': PresentaMensaje(2); LiberaMemoriaO; Muestras-Tot=memTotal; ReservaMemoria(memTotal+ 1 ) ; archivoTarjeta=CargaDatos(); //Opción de adquisición de datos break; case ' 1 ': { ' I 4-5 LimitesDeFrecuenciaO; break; case 2': Canal(); IniciaGraficos(); PresentaGraficaO; if(archivoTarjeta)REESTABLECE(); clrscr(); break; case '3l: LiberaMemoriaO; PresentaMensaje(6); delay( 1000); break; }while(fl='3'); return O; / /Fin programa. de I Módulo de menús y mensajes: int PresentaMensaje(int cual) c clrscr(); textbackground(L1GHTBLUE); textcolor(WH1TE); switch (cual) { case O: gotoxy( 13,2);cprintf("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ~,"); gotoxy( 13,3); cprintf("O "'7; cprintf("" gotoxy( 13,4); O"); gotow( 13 >5); cprintf("UNIVERS1DADAUTONOMA METROPOLITANA"); cprintf("" gotoxy(13,6); gotoxy(13,7);cprintf("O IZTAPALAPA cprintf("" gotoxy(13,8); "'7; gotoxy( 13,9);cprintf("O C. B. I. ""1; gotoxy( 13,1O);cprintf("" "7; gotoxy( 13,ll);cprintf(" SEMINARIODEPROYECTOS I1 "); gotoxy(13,12);cprintf("" ""); go t o w;cprintf("" ( 13,13) Titulo: O"); gotoxy( 13,14);cprintf("PROCESAMIENTODESEYAL DE O " ) ; O"); " ' l b 4 - 6 gotoxy( 13,15);cprintf("" -FCG- TIEMPO EN REAL. "'I; gotoxy( 13,23);cprintf("" ""1; gotoxy( 1 3 , 2 4 ) ; c p r i n t f ( " E : i Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í ~ " ) ; textcolor(L1GHTGREEN); ."); gotoxy(18,25);cprintf("Esperar.. delay(2000); break; case 1: gotoxy(18,5);cprintf("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ))"); cprintf("" gotoxy(18,6); ""1; cprintf("" gotoxy(18,7); "'7; gotoxy(18,8); cprintf("" MENU PRINCIPAL ""1; gotoxy( 18,9);cprintf("" ""1; gotoxy(1 8 , lO);cprintf("" <O> CARGAR DATOS ""1; gotoxy(18,ll);cprintf("" < 1> LIMITESDEFRECUENCIA gotoxy(18,12);cprintf("" <2> MUESTRA GRAFICA O"); gotoxy( 18,13);cprintf("" <3> TERMINAR O"); gotoxy(18,14);cprintf("" O"); gotoxy(18,15);cprintf("" O"); gotoxy(18,16);cprintf("" gotoxy( 18,17);cprintf("EÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ'/4"); gotoxy(23,19);cprintf("Elija opcicn "); break; case 2: gotoxy(18,6);cprintf("0ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ~)"); gotoxy(l8,7); cprintf("" CARGAR LOS DATOS DE: "") ; cprintf("" gotoxy( 18,8); "'7; gotoxy(cprintf("" 18,9); l . ARCHIVO ""1; gotoxy(18,10);cprintf("" O"); gotoxy( l);cprintf("" 18,l2. TARJETA O"); gotoxy( 18,12);cprintf("" ""1; gotoxy(18,13);cprintf("" ""1; gotoxy(1 8 , 1 4 ) ; c p r i n t f ( " E Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í ~ " ) ; textcolor(L1GHTGREEN); gotoxy(23,18);cprintf(" Elija opcicn : "); break; case 3: gotoxy(14, 5);cprintf("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ~~t'); gotoxy(14, 6); cprintf("" "'7; gotoxy(14, 7); cprintf("O O"); gotoxy(14, 8);cprintf("RANGODE FRECUENCIA A DETECTAR"); ( latidos/minuto ) O"); gotoxy(14, 9); cprintf("" lO);cprintf("" gotoxy(14, "'7; gotoxy( 14, 1l);cprintf("" <A> 70 - 90. ""); O"); O"); 4 - 7 gotoxy( 14, 12);cprintf("" <B> 1 2 0 - 1 8 0 "'7; gotoxy( 14, 13);cprintf("" DEFAULT 100-200. "'7; gotoxy( 14, 14);cprintf("" "'7; 15);cprintf("" gotoxy( 14, ""1; g o t o y ( 14, 1 6 ) ; c p r i n t f ( " E Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í ~ ~ " ) ; textcolor(L1GHTGREEN); gotoxy(18,20);cprintf(" << OPCION >> "); break; case 4: . "); gotoxy( 18,1O);printf("Tarjeta Inicializada.. gotoxy( 18,12);printf("Interrupcion habilitada.. . Cargando datos..."); gotoxy( 18,16);printf("Oprima cualquier teclapara continuar."); getche(); break; case 6: textbackground(BLACK); textcolor(WH1TE); cprintf("Termin0..."); delay(800); clrscr(); break; f return O ; 1 J Corregircadena,este módulocompruebacadaelementode verifica si todos son números, en caso de que la cadena contenga elementos alfanuméricos regresa un cero en el apuntador bad-cad uno si la cadena cumple solo con elementos numéricos. la cadena y y un void CorregirCadena(char *cadena-a-mandar,int *bad-cad) { char recibe_caracter[20]; int i=O; do { *badPCad= 1 ; recibe-caracter[i]=cadena_a_mandar[i]; *bad-cad=(isdigit(cadena-a-mandar[i])); if(*bad-cad==O )break; ' i 4-8 i++; 1 1 while(cadena-a-mandar[i]!='\xO');//Verifica hasta el elemento nulo. de es //que final el la cadena. PideFrecuencia, captura el valor de frecuencia de muestre0 deseado en rango predefinido. el int PideFrecuencia(v0id) { char cadena-a-mandar[20],cadena-a-validar[20]; int bad-cad= 1 ; clrscro; do{ do{ gotoxy( 18,14);cprintf("Seleccionela frecuencia en Hz< 1-3000>:"); bad-cad= 1; gotoxy( l8,70); clreol(); gotoxy( 18,70); gets(cadena-a-validar); strcpy(cadena-a-mandar,cadena--a-validar); CorregirCadena(cadena-a-mandar,&bad-cad); }while(bad-cad==O); frecuenciaCanal=(atoi(cadena-a-validar)); )while((frecuenciaCanal<=O,O) I I (frecuenciaCana1>3000)); return(frecuenciaCana1); } RaizFrec,recibecomoparámetro la frecuenciaporcanalseleccionada previamente, y regresa valor eldel divisor que será utilizado posteriormente registros cada los uno del encontador del el fin dedividirlafrecuencia programable(timer)correspondiente,con máxima de 2MHz a la frecuencia seleccionada, tomando en cuenta que se la justificaciónde la raíz tratadedoscontadoresencascada;estaes la función. Cuando se menciona contador cuadrada que se encuentra en programable, se refiere a los contadores de la tarjeta PC-LAB. I . 4 - 9 int KaizFrec(int frecuenciacanal) I 1 double Conversion; int resultado; frecuenciacanal = frecuenciacanal; Conversion = (doub1e)frecuenciaCanal; Conversion = 2000000/Conversion;//Frecuenciamáxima 2MHz / / Raíz cuadrada. Conversion = sqrt(Conversi0n); Conversion = (int)Conversion; / / Conversión de resultado en //entero. resultado = (int)Conversion; return(resu1tado); i El hecho de convertir el resultado en un valor entero, es debido a que no se puede escribir en el registro de ocho bits del contador programable un valor fraccionario, en el caso de que este error se presentara ocasionaría el un problema en la ejecución del programa que bloquearía el proceso, en mejor de los casos. LimitesDeFrecuencia, en relación a el número de muestras existentes en entre cada latido; es necesario relacionar el numero de muestras máxima y numerodemuestrasmínimasparaunrangodefrecuenciadelatidos cardiacos definido; esto v a directamente relacionado, desde luego, con la frecuencia de muestreo. int I.,imitesDeFrecuencia(void) I char c; PresentaMensaje(3); c =toupper(getch()); CalculaLimitesDeFrec(c); return O ; 3 CalculaLimiteDeFrec, hace los cálculos necesario para determinar el número de muestras limite que debe haber entre cada pico detectado. Esto es necesario para determinar si el pico detectado e s o no un latido. int CalculaLimitesDeFrec(charc) { 4 - 10 Real maxima,minima; switch(c)( case 'A':/ /para adulto 70-90 minima=50; maxima= 1 1 O ; break; /para feto 120- 180 case 'B':/ minima= 100; maxima= 190; break; default : minima= 100; maxima=200; break; minima=(Real)minima/60.000; //frecuencia en Hertz / /frecuenciaen Hertz minima= 1 / (Rea1)minima; //En segundos minima=(Real)minima*frecuenciaMuestreo; / / [s]*[MUESTRAS/s]=[MUESTRAS] maxima=(Real)maxima/60.000; maxima= 1 /maxima; segundos //En maxima=maxima*frecuenciaMuestreo; / / [s]*[MUESTRAS]=(MUESTRAS] e distanciaMaxima=minima; distanciaMinima=maxima; 1 / /Guarda los resultados en variables / /globales. return O ; Canal, captura el número de canal por el que van ha ser adquiridos los de 16 canales), datos. Una vez capturado el número de canal (de un total es seleccionado directamente escribiendoal registro que se encuentra en la dirección del puerto Ox030A, donde se encuentra el multiplexor. void Canal(void) if(archiv0Tarjeta) 4 - 11 canalGraficar=PideCanalGraficar(); outportb(0x030A,(unsignedchar)canalGraficar); / /Escribe en el. puerto int PideCanalGraficar(v0id) \ int NUMERO-CANAL,bad-cad=l; char cadena-a-mandar[20],cadena-a-validar[20]; do( do{ clrscr(); gotoy( 1,2);printf("Indique canal a graficaw 1 - 16>:"); bad-cad= 1 ; gotoxy(25,35); clreol(); gotoxy(25,35); gets(cadena-a-validar); strcpy(cadena-a-mandar,cadena-a-validar); CorregirCadena(cadena-a-mandar,&bad-cad); )while(bad-cad==O); NUMERO-CANAL=(atoi(cadena-a-validar)); //Convierte cadena a 1 / / número. )while(NUMERO-CANAL< 1 I I NUMERO-CANAL> 16); return(NUMER0-CANAL- 1 ) ; LiberaMemoria, verifica si existe u n bloque de memoria ocupado previamente, si e s así es liberado el espacio e inicializados los apuntadores a nulo. void LiberaMemoria(v0id) { if(BL0QUE-ASIG!=NULL) free(BL0QUE-ASIG); BLOQUE-AUX=apuntador-auxiliar=BLOQUE-ASIG=NULL; 1 1 4 - 12 ReservaMemoria,devuelveunapuntador al iniciodelbloquedememoria de tamaño MTOTAL, asignado para valores enteros. El valor de la dirección de inicio es asignado void ReservaMemoria(int MTOTAL) BLOQUE-ASIG=(int *)malloc(2*MTOTAL); if(BL0QUE-ASIG==NULL){printf("No hay memoria"); getch();exit(1);) apuntador-auxiliar=BLOQUE-AUX=BLOQUE-ASIG; 1 J CargaDatos,estemódulopermiteque el programatengadosfuentes de y la otra opción es acceso a datos; una es por medio de datos en archivo obtener datos habilitando la interrupción de la tarjeta. int CargaDatos(void) { int entero,cambia=O; char c; PresentaMensaje(2); c=getch(); switch(c){ case ' 1 ': CargarBufferO; break; case '2': entero=PideFrecuencia(); DIVISOR=RaizFrec(entero); DIVID E-FREC () ; ADQUISICION(); PresentaMensaje(4); cambia= 1 ; break; 1 frecuenciaMuestreo=frecuenciaCanal; if(cambia== 1)return 1 ; return O ; 1 ontador. 4 - 13 El módulodevuelvevalor uno si losdatossonadquiridosmediante la tarjetaPC-LAB. E n otrocaso, si losdatossoncargadosmedianteun archivo, la función regresa como resultado un cero. Esta función además de permitir acceso el a los datos, también modifica variable la "archivoTarjeta" , con la cualseejecutan o dejandeejecutarsealgunas instrucciones durante el proceso. CargarBuffer, por medio de este módulo es posible el acceso archivo. a 10s datos en void CargarBuffer(v0id) i int dato=O,auxIliar=O,Num-dat=O,Contador=O; char archivo[70]; FILE *fp; clrscr(); printf("\,n Nombre y ruta de acceso al archivo:\n "); scanf("O/s",&archivo); if(!(fp = fopen(archivo,"rb"))) c printf(" \n\nNo se abrio el archivo..."); delay(800); goto salir; 1 fseek(fp,OL,SEEK-SET);//Coloca el apuntadoralinicio delarchivo. frecuenciaCanal=getw(fp);//Lee la frecuencia de muestreo con que //fueron capturados los datos. Num-dat=getw(fp); / /Leeelnúmerototaldedatosdelarchivo. fseek(fp,S,SEEK-SET);//Coloca el apuntadorenlaposicióndonde //comienza el bloque de datos. Contador=auxIliar=O; / / Inicializa los contadores. while(auxIliar<Num-dat-2)/ /Comienza carga de los datos y verifica //el final del archivo. dato=getw(fp); / /Lecturadato. del apuntador-auxiliar[auxIliar]=dato;/ /Lo guarda en memoria. el //Actualiza ++Contador; 4 - 14 if(Contador=-memTota1)goto termina; //Verifica si esta al final del / /arreglo de memoria. ++-auxiliar; //Actualiza contador. 1 termina: //Etiqueta de final de carga directa de archivo. fseek(fp,OL,SEEK-END); //Coloca el apuntador de archivo al final de //este. fclose(fp); archivo. / /Cierra el //Llenalosespacioslibresdelbloquedememoria, si esqueexisten,es //decir,quedanespacioslibres si el nilmerodedatosesmenorque el / /espacio de memoria asignado. if(Num-dat-2<memTotal- 1) c for(auxIliar=0,Contador=Num~dat-3; Contador<memTotal;Contador++,auxIliar++) I { apuntador~auxiliar[Contador]=apuntador~auxiliar[auxIliar]; if(auxIliar==Num~dat-2)auxIliar=O; i 1 printf("\n\n\nLos datos ya fueron cargados en el bufer ... \I"'); printf("\n\n\n Oprima cuaquier tecla para continuar. \r"); salir: getch(); / /Espera se oprimida cualquier tecla. 1 CargaTaps,estemódulocontieneloscoeficientesdelosfiltros.Cada que es llamado, son cargados los valores en arreglos globales. vez int CargaTaps(int queFiltro) i' int guardaTaps; Real tapsFiltro 1 [taps]= {-2.108063075E-2,-3.9151573873-2,-6.97967747E-2, -7.0825699043-2,7.662132192E-13,1.367956549E-1, 2.7502143323-1,3.3333333E-1,2.7502143323-1, 1.3679565493-1,7.662132 192E-13,"7.0825699043-2, -6.979677473-2,-3.915157387E-2,-2.1080630753-2}, 4 - 15 tapsFiltro2[taps]= C2.315044242E-2,3.167428862E-2,-8.796018663E-13, -1.14598374531 ,-2.003068499E1 ,-8.45443642 1E-2, 1.866614325E1,3.333333331,1.866614325E1, -8.45443642 1E-2,-2.00306849931 ,-l.145983745E-1, -8.796018663E-13,3.167428862E-2,2.315044242E-2), tapsFiltro3(taps]= (-2.4208468663-2,1.209850168E-2,6.97967747E-2, 9.4783274443-2,1.2379644 143-1,-2.499380982E1, -6.602597445E-2,3.3333333E-1,-6.6025974453-2, -2.49938098231 ,-1.2379644 14E1,9.478327444E-2, 6.97967747E-2,-1.209850168E-2,-2.420846866E-2), tapsFiltro4[taps]= (2.4208463663-2,-1.209850168E-2,-6.97967747E-2, 9.478327444E-2,1.237964414E-1 ,-2.499380982E1, -6.602597444E-2,3.3333333E-1,-6.602597444E-2, -2.499380982E1,1.2379644 1431,9.478327444E-2, -6.979677473-2,-1.209850 168E-2,2.420846366E-2}, tapsFiltro5[taps]= (-2.315044242E-2,3.167428862E-2,-1.466003111E-12, - 1.1459837453-1,2.003068499E-1 ,-8.454436422E-2, -1.866614325E-1,3.3333333E-l,-1.866614325E-l, -8.454436422E-2,2.003068499E1,-1.14598374531, - 1.4660031llE-l2,3.167428862E-2,-2.3150442423-2), tapsFiltro6[taps]= (9.3670739573-3,1 .go743 1079E-2,4.635808739E-2, 9.181312086E-2,1.485844147E-1,2.043135351E-1, 2.45060350531,2.6E1,2.45060350531, 2.043135351E-1,1.485844147E-1,9.181312086E-2, 4.635808739E-2,1 switch(queFi1tro) 1079E-2,9.367073957E-3;; .go743 case O: //20-30Hz con Frec. Muestreo de 300Hz for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps 1[guardaTaps]=tapsFiltr1o[guardaTaps]; for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps2[guardaTaps]=tapsFiltro1 [guardaTaps]; break; case 1: / /40-60Hzcon Frec. Muestreo de 300Hz for(gua?daTaps=O;guardaTaps<taps;guardaTaps++) taps1[guardaTaps]=tapsFiltro2[guardaTaps]; break; I 4 - 16 case 2 : / /80-90Hzcon Frec. Muestreo de 300Hz for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps 1 [guardaTaps]=tapsFiltro3[guardaTaps]; break; case 3: / / 100- 1 lOHz con Frec. Muestreo de 300Hz for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps1 [guardaTaps]=tapsFiltro4[guardaTaps]; break; case 4: //20-30Hz con Frec. Muestreo de 300Hz for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps 1 [guardaTaps]=tapsFiltro5[guardaTaps]; for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps2[guardaTaps]=tapsFiltro5[guardaTaps]; break; default: / /20-30Hz con Frec. Muestreo de 1OOOHz for(guardaTaps=O;guardaTaps<taps;guardaTaps++) taps 1 [guardaTaps]=tapsFiltro6[guardaTaps]; for(guardaTaps=O;guardaTaps<taps;guardaTaps++) 1 tapsZ[guardaTaps]=tapsFiltro6[guardaTaps]; break; return O ; Cada filtro fue diseñado para una determinada frecuencia de muestreo, en base a losalgoritmosdeventanasdeHamming. Sus coeficientesfueron calculados con la ayuda del paquete DSPLAY, posteriormente serán mostradas sus curvasderespuestaenfrecuencia y las diferenciascon respecto a la frecuencia de muestreo. MuestraMensaje, el siguiente módulo genera un mensaje en la pantalla de gráficos, con el que se muestran principalmente resultados de los cálculos realizados durante el proceso y cada vez que es detectado un nuevo pico. Recibe como parámetro una variable “bandera”, que indica si el mensaje v a ha ser borrado o restablecido, con tan solo cambiar el color de la fuente, recibe las coordenadas donde v a ha ser colocado el mensaje “ x x l ,yy 1 ,xx2 & yy2”; obtienelacadena que contieneelmensaje“mensaje” y esta definida como un apuntador “mensaje”; y por último el valor o resultado que v a a desplegar. void MuestraMensaje(int bandera,intxxl ,int yy1,int xx2,int yy2,char 4 - 17 *mensaje,Real i char valor) *numero-calculado=NULL; settextjustify(T0P-TEXT,LEFT-TEXT); settextstyle(SMALL~~FONT,HORIZ~DIR,4); gcvt(va~or,5,numero-~alculado); / /Cambia número flotante o Real una //cadena. setcolor(L1GHTGREEN); outtextxy(xx1+15O,yy1+2O,mensaje); if(bandera==,O)setcolor(LIGHTBLUE); if(bandera== l)setcolor(YELLOW); outtextxy(xx2+150,yy2+20,numero~calculado); i J MenuFiltro, void muestra la enpantalla MenuFiltros(int de gráficos la opciones de filtrado. xx,int yy) I int ajustex=xx- 160,ajustey=yy105; setcolor(L1GHTGREEN); outtextxy(ajustex,ajuste$," FILTROS PASA BANDA "); setcolor(YELL0W); outtextxy(ajustex,ajustey+16,"O> 20-30I-Iz"); outtextxy(ajustex,ajustey+30,"1> 40-50 Hz"); outtextxy(ajustex,ajustey+43,"2> 60-70Hz"); outtextxy(ajustex,ajustey+54,"3> 80-90Hz"); outtextxy(ajustex,ajustey+66,"4> 100-110Hz"); CargaTaps(getch0); setcolor(L1GHTBLUE); outtextxy(ajustex,ajustey,"FILTROS PASA BANDA "); outtextxy(ajustex,ajustey+16," O> 20-30Hz"); outtextxy(ajustex,ajustey+30,"1> 40-50Hz"); outtextxy(ajustex,ajustey+43,"2> 60-70Hz"); outtextxy(ajustex,ajustey+54,"3> 80-90Hz"); outtextxy(ajustex,ajustey+66,"4> 100-1 1OHz"); , GraficaDatoNoPrc, esta función realizaun calculo de normalizaciónde datos, ya que los valores leídos de un archivo, asícomo los valores que 4 - 18 entrega la tarjeta,estánenelrangode O a 4095, y para poder ser graficados es necesario normalizarlos a la resolución de la pantalla actual en el plano vertical. En este caso, es módulo es utilizado paragráficarlosdatosqueaúnno son procesados. Real GraficaDatoNoPrc(int VERT-MAX,int cuenta-bufer) i Real escalador1 ,nuevoDato; escalador 1 =4095/(Rea1)VERT”AX; / /Factor de escalamiento / / Si esta activa la tarjeta espera que el apuntador de escritura sea mayor / / que el apuntador de lectura. if(archiv0Tarjeta) while(indicador-coloca-ind==cuenta-bufer); nuevoDato=apuntador~auxiliar[cuenta~bufer]; / / Lee el nuevo valor / /convertido. return(nuevoDato/escaladorl);//Retorna valor normalizado Marcapicos,estafunciónes el mismocasoque la funciónanterior la diferenciaconsisteenquelosdatos a gráficaryahansidoprocesados. Estos datos son registrados en la variable “datoProcesado”. Adem’ás, la función regresa u n valor uno si durante el proceso es detectado un latido o un pico. En caso contrario regresa un cero. Esta función recibe como parámetro el tamaño en altura de la pantalla de graficación actual y apartir de este valor calcular el valor del dato normalizado. Real MarcaPicos(int VERT-MAX) { int nuevaventana; Real nuevoDato; / /Es utilizada como variable auxiliar.. . //Actualiza los datos de los filtros durante un salto de pantalla if(saltoDePantalla== 1 ) {//Conecta las pantallas for(nuevaVentana=O;nuevaVentana<29;nuevaVentana++) datoProcesado=ProcesaDatos(); 4 - 19 saltoDePantalla=O; / /Fin de salto datoProcesado=ProcesaDatos(); nuevoDato=datoProcesado; //Llama a las funcionesde / /procesamiento; filtrado y derivada. //Comprueba si esta en el rango. if(datoProcesado>4096) datoProcesado=4096; if(datoProcesado<O) datoProcesado=O; //Normaliza el dato para el tamaño de pantalla. datoProcesado=datoProcesado/(4095/(Real)VERT_MAX); nuevoDato=BuscaPicos(nuevoDato);//Llama a las funciones de / /detección de picos. / /Empieza la detección de picos en base al criterio de //distancia entre picos... if(nuevoDato== 1 ) nuevoDato = SeleccionaIntervalo(checa-mem); if(nuevoDato== 1 ) return 1 ; return O ; ProcesaDatos, filtra y deriva los datos capturados regresando como resultado el valorprocesado.Considerandoque las características de los filtros y la derivadas dependen de valores anteriores o mejor dicho utilizan valores anteriores, es posible que guardando los datos anteriores y haciendouncorrimiento,paraagregar el datoactual y desechandoun Único dato, lograr mayor velocidad de procesamiento. Para esto es ya fueron necesarioutilizarunbanderaquenospermitasabercuando calculados algunos datos que son reutilizables; esta variable que cambia solo corrimientoses“corrimiento”,escero cuandoesnecesariohacer cuando no hay datos anteriores y uno en el caso contrario. Real ProcesaDatos(void) { int checa-buf,bufer,d,f,g; int tamano=memTotal; bufer=checa-mem; if(corrimiento==O) / /Bandera en el inicio.. . 4 - 20 I for(f=taps- l;f>=O;f--,bufer--) if(bufer<O)bufer=tamano-2;//Si esta en el limite inferior de bufer checa-buf=bufer; / /tomaelvalorsuperior(bufer circular). for(g=3;g>=O;g--) { for(d=3;d>=O;d--,checa-buf--) {if(checa~buf~O)checa~buf=tamano-2; arreglo 1 [d]=PrimerFiltro(checa.-buf);)/ /Llamo 4 veces al filtro arreglo2[g]=FuncionDerivada(arreglo1 ) ; //Derivada 1 arreglo-fin[f)=FuncionDerivada(arreglo2);/ / Derivo por segunda / / ocasión. 1 corrimiento= 1 ; //Cambia la bandera, pues ya existen datos anteriores. 1 ) else { / /Corrimientos. for(f=O;f<taps;f++) arreglo-fin[q=arreglo-fin[f+ 1 I ; for(d=O;d<3;d++) arreglo 1 [d]=arreglo1[d+ 11; for(g=O;d<3;g++) arreglo2[g]=arreglo2[g+l]; //Calcula los nuevos datos.. arreglo 1 [3]=PrimerFiltro(bufer);//Filtra dato actual arreglo2 [3]=FuncionDerivada(arreglo 1 ) ; / /Derivada / Derivo por segunda arreglo-fin[taps- l]=FuncionDerivada(arreglo2);/ / /vez. 1 return(fabs(SegundoFiltro(arreg1o-fin)));/ /Filtro por segundavez 1 PrimerFiltro, la idea de utilizar dos funciones diferentes para el filtrado e s debido a que es posible la utilización de dos filtros distintos en cada una de las etapas del proceso. Real PrimerFiltro(int verifica-bufer) { 4 - 21 mt y; int tamano=memTotal; Real arregloFiltrar[taps); Real datoProcesado=O; for(y=taps- 1 ;y>=O;y--,verifica-bufer--) / /Para lograr la idea de recorrer el búfer de manera circulary en //sentido descendente, enel caso de que el apuntador haya leído la //primera posición es necesario que la siguiente lectura la haga / /en la última posición del arreglo. if(verifica_bufer<O) verifica-bufer=tamano-2; / /Lectura de un nuevo dato. arregloFiltrar[yJ=apuntador~auxiliar[verifica_bufer]; 1 / /Realiza el filtrado . .. for(y=O;y.=taps;y++) datoProcesado=taps 1 [y]*(arregloFiltrar[taps-yl])+datoProcesado; //Regresa el dato procesado. return (datoProcesado); t J < FuncionDerivada, ca1cul.a la tercera derivada por método de aproximación de derivadas. Recibe como para metro un apuntador al arreglo donde se encuentran los datos previamente filtrados. Real FuncionDerivada(Rea1 *conjunto) { int D; D=(- l*conjunto[O] +3*conjunto[1 J -3*conjunto[2] + l*conjunto[3] ); return (4*fabs(D)); //Amplifica el resultado I 4 SegundoFiltro,efectúa elfiltrado parasuavizar la curvaresultante los picos.Recibecomoparámetroun estamaneraremarcaraúnmás arreglo de datos previamente derivados. - 22 y de Real SegundoFiltro(Rea1 "arreglo-final) f I m t y; Real datoFinal=O; //Calcula la sumatoria del filtro. for(y=O;y<taps;y++) datoFinal=taps 1 [y]*(arreglo-final[taps-yl])+datoFinal; //Regresa un datoya procesado. return (datoFinal); IniciaGraficos, activa monitor el en modo el de gráficos. Además inspecciona si es posible utilizar un controlador o si existe una tarjeta que permita la utilización de gráficos. L int IniciaGraficos(void) { int chances=O,modo,Error,controlador=O; c h a r BGIs[GO]="c:\ yuan\ \tc"; //Localiza los controladores en esta / /dirección como primera opción. clrscr(); do{ initgraph(&controlador,&modo,BGIs); Error=graphresult(); / /Si después de la búsqueda genera uno de los siguientes errores //regresa un mensaje de error no reparable o sin solución. switch(Error)( case grNotDetected: case grInvalidDriver: case grNoScanMem: case grInvalidMode: case grIOerror: 4 - 23 case grInvalidVersion: case grNoLoadMem: case grInvalidFont: puts ("Error tragico"); exit( 1 ) ; break; case grOk: //Este caso es en el que ha sido posible break; / /la inicialización de los gráficos. default: / / E n c a s o de que la ruta de acceso a los controla/ /dores de video no sea la correcta... printf("La ruta de acceso de los bgi: "); gets(BG1s); / /espera nueva ruta . .. controlador=O; chances++; / /Oportunidades de inicialización de / /gráficos. if(chances==3) { clrscr(); printf("\n\n\n Se acabaronlos chances. "); LiberaMemoriaO; exit(0); ; 1 break; )while(Error!=grOk); settextstyle(TRIPLEX_FONT,HORIZ_DIR,4); setcolor(L1GHTBLUE); outtextxy( 100,170," Prepara Ambiente grafico... "); delay(800); return O ; 1 AmbienteDeGraficacion,muestraunaventanadondeseaprecianbarras y otras dedatoscomo:frecuenciademuestreo,canaldeadquisición funciones; como la llamada de los filtros y opción de salida. void AmbienteDeGraficacion(int XXMAX,int YYMAX) { char numero[20]; setviewport(O,O,XXMAX,YYMAX,1); //Define una ventana... setbkcolor(BLUE); fondo.. / /Color de . setfillstyle(SOL1D-FILL,LIGHTBLUE); 4 bar(O,O,XXMAX,YYMAX); - 24 //Coloca una barra de color azul claro / / e n la parte superior dela pantalla. settextjustify(LEF3-TEXT,TOP-TEXT); setfillstyle(SOL1D-FILL,BLUE); bar(O7YYMAX-20,XXMAX,YYMAX+25);/ /Coloca una barra decolor azul / / e n la pare inferior de la pantalla. settextstyle(SMALL-FONT,HORIZ_DIR,5); itoa(canalGraficar,numero, 10); / /Convierte un número en cadena settextjustify(LEFT-TEXT,TOP-TEXT); setcolor(WH1TE); outtextxyj50,YYMAX- 15,numero); / /Pinta el valor del canal a graficar settextjustify(LEF3-TEXT,TOP-TEXT); setcolor(YELL0W); outtextxy(8,YYMAX-15,"CANAL "); //Pinta la leyenda "CANAL" itoa(frecuenciaMuestreo,numero,10);/ /Ahora frecuencia de muestreo.. . settextjustify(CENTER-TEXT,TOP-TEXT); setcolor(WH1TE); outtextxy(XXMAX-30,YYMAX1 5,numero);/ /Pinta valor de la frecuencia //de muestreo. settextjustify(CENTER-TEXT,TOP-TEXT); I setcolor(YELL0W); outtextxy(XXMAX-80,YYMAX15,"FM"); //Pinta leyenda "FM" setfillstyle(CL0SE-DOT-FILL,BLUE); bar(O,O,XXMAX,18); //Define área de graficación. setcolor(WH1TE); settextstyle(SMALL~FONT,HORIZ~DIR,5); / /Pinta leyendas de funciones outtextxy(XXMAX-120,4,"CUALQUIERTECLA PARA SALIR"); outtextxy( 110,4,"F2: REINICIA DETECCION"); outtextxy(XXMAX/2,4,"F3: FILTROS"); setfillstyle(SOL1D-FILL,WHITE); bar(81,20,XXMAX- 19,YYMAX1 10); //Marca el área de graficación / / en blanco. setcolor(RED); rectangle(79,18,XXMAX-18,YYMAX-109); rectangle(80,19,XXMAX-l7,YYMAX108); IresentaGrafica, muestra los resultados de los datos obtenidos. I 4 - 25 void PresentaGrafica(v0id) I int j,key,exitenDatos,YYMAX,XMAX,altura-ventana, longitud-ventana,altura-ven-real; int dif,aux,posYant,posYact,checa-bufer,tam-buf, ventana,indicador-frecc=O; int YYant,YYact,aux2; Real borra~ant=O.O,estandar~old=O.O,variabilidad~ant=O.O; YYMAX=getmaxy(); //Captura la resolución del monitor actual en XXMAX=getmaxx(); / /horizontal y vertical. //Ajusta el área de la pantalla donde serán graficados los datos. longitud-ventana=XXMAX- 19; altura-ventana=YYMAX- 130; altura~ven~real=altura~ventana+20; //Inicializa el valor del total de datos presentes en memoria. tam-buf=memTotal; / /Inicializa el índice a la primera poción del arreglo. checa-bufer=O; AmbienteDeGraficacion(XXMAX,YYMAX); key =PINTA; CargaTaps(6); //Carga un valor cualquiera para los filtros ... do{ switch(key)( case PINTA: / /Primera opción... ventana=O; / /Inicializa el número de ventanas graficadas exitenDatos=O; //Bandera que indica si ya existen tienen datos //procesados suficientes para comenzarla / /detección de los picos., . j=aux=O; / /Inicio de la pantalla while(bioskey(1)==0) //Realizala graficación mientras no se oprima / / u n a tecla... { //Verifica si final de arreglo de datos capturados. if((checa_bufer+2)==tam_buf) checa-buf=O; //Verifica si final de ventana ifCj>longitud-ventana I I j==O) / / E n el caso del final de ventana... { //Torna una nuevaposición en la pantalla, en especifico al //inicio de esta para continuar con la gráfica. j=aux=81; i 4 - 26 //Toma unnuevo dato como primera coordenada .... posYant=(int)(altura_ventana+20GraficaDatoNoPrc(a1tura-ventana,checa-bufer)); if(ventana<2)++ventana;/ /Incrementa número de ventanas exitenDatos=O; saltoDePantalla= 1 ;> setcolor(MAGENTA); lineCj ,70,j,altura-ven-real-50); / /Línea indicadora del punto / /actual de graficación. setcolor(WH1TE); ,altura-ven-real); / /Línea de borrado del dato lineu ,20,j //del punto anterior. setcolor(BLUE); / /Calcula la posición del nuevo datoa gráficar(dat0 actual). posYact=(int )(altura_ventana+20GraficaDatoNoPrc(a1tura-ventana,checa-bufer)); line(aux,posYantj,posYact);/ /Pinta curva de datos no procesados. posYant=posYact; / /Actualiza coordenadas.. . aux=j ; //Verifica si ya fueron graficadas al menos dos pantallas / / y entonces cambia la bandera, para que posteriormente //empiece la detección de los picos.. . Además espera a que, //en cada pantalla, sean graficados al menos doce datos. if(ventana> 1 &&j==8 1 + 12) exitenDatos=1 ; / /Comienza graficación de rasultados.. . if(exitenDatos) checa-mem=checa-bufer; //Pone el índice del apuntador en el / /dato actual... if(MarcaPicos(a1tura-ventana)) //Sipico detectado e s latido.. . {setcolor(GREEN); / /pinta líneaverde vertical y cambia la bandera / / “indicador-frecc”. line~-12,20,j-12,altura~ven~real);indicador~frecc=l;} / / S i final de pantalla... if(j==81+12) { / /Actualiza variables... YYant=(int )(altura~ventana+20-datoProcesado); //primera //coordenada en ejeY . . . aux2=j- 12;/ /coordenada en X, al inicio.} 4 - 27 / /Calcula nuevo valor a gráficar para la nueva pantalla. YYact=(int )(altura~ventana+20-datoProcesado); / /Verifica si esta dentro delos límites del área de graficación... if(YYact>=20&&YYact<=altura-ven-real) {setcolor(LIGHTRED); line(aux2,YYantj-12,YYact); //Pinta curva del gráfica / /procesada.. . / /Actualiza coordenadas. aux2=j- 12; YYant=YYact;} / /Si indicador-frecc es uno, muestra los valores actuales / /calculados; tanto de frecuencia como desviaciones estándar. if(indicador-frecc) {MuestraMensaje(0,35,YYMAX100,100,YYMAX-100, "FRECUENCIA <Hz> :",borra-ant);//Borra MuestraMensaje(O,170,YYMAX100,240,YYMAX-100, "SD :",estandar-old); / /Borra MuestraMensaje(0,35,YYMAX-80,100,YYMAX-80, "VARIABILIDAD :",variabilidad-ant);// borra MuestraMensaje(1,35,YYMAX-100,100,YYMAX-100, "FRECUENCIA <Hz> :",frecuenciaAprox);/ /Pinta 100, MuestraMensaje(1,170,YYMAX- 100,240,YYMA.XSD :",SDintervalo); / / Pinta MuestraMensaje(1,35,YYMAX-80,100,YYMAX-80, "VARIABILIDAD :",variabilidadHertz);//Pinta / /Guarda los valores actuales... estandar-old=SDintervalo; //Desviación estándar por ancho / /de intervalo. borra-ant=frecuenciaAprox; variabilidad-ant=variabilidadHertz; / /Variabilidad calculada / /de la frecuencia. indicador-frecc=O; / /Inicializa la bandera.. .> q. 1 " ++theca-bufer; //Incrementa el índice para lectura de unnuevo //dato. ++j; //Incrementa posición en el eje X }/ / fin del ciclo while... key=bioskey(O); //Toma el valor de la tecla presionada. break; 4 - 28 case F2: //La tecla “F2”, permite inicializar todas la variables que se utili//zan durante la detección. ventana=O; corrimiento=O; umbralNivel=O; SDamplitud=O; SDintervalo=O; contadorPicos=O; contadorAmplitUno=O; contadorPosiciones=O; contadorIntervalos=O, existeReferencia=O; key=PINTA; / /Continúa graficando. break; case F3: / /La tecla “F3”,permite la visualización y selección de los filtros. MenuFiltros(XXMAX,YYMAX); key=PINTA; //Continúa graficando. break; } }while(key==F3 I I key==ABAJO I I key==PINTA 1 I key==F2); REGRESA: closegraph(); //Restaura el modo textodel monitor. restorecrtmode(); 1 4 - 29 IV. 1.1.- Módulos del Algoritmo Lasiguientepartedellistadomuestra la implementacióndelalgoritmo para la detección de posibles picos que correspondan a u n latido o sonido cardiaco. IV.l.l . 1 .- Búsqueda por Amplitud BuscaPicos, la primerapartedelalgoritmoesdetectarpicosenbase al criterio de amplitud. Primero es necesario determinar si el dato presente es unmáximo, si estosucedecabelaposibilidaddequeseaunposible sonido cardiaco. Esto es posible entre las variables “primerRegistro”, solo seaceptacomoposible ”segundoRegistro” y “muestra-act”,donde pico el caso en que el valor de la variable “segundoRegistro” e s mayor. Real BuscaPicos(Rea1 muestra-act) Real limite~sup=0,1imite~inf=07Umbral=0; int num.-muestra; / / Verifica si es un máximo el dato inmediato anterior “segundoRegistro”. if(segundoRegistro>primerRegistro&& segundoRegistro>muestra-act) { % //Toma los valores actualesdel segundo promedio y desviación estándar, / /si los valores son cero solo se considera el umbral determinado por / /el primer promedio. La variable “umbralNive1” corresponde al segundo / / promedio. limite-inf=umbralNivel-SDamplitud; limite-sup=umbralNivel+SDamplitud; / /Llamada a la función de primer promedio y actualización del umbral //con el nuevo pico detectado. Umbral=PromedioPicos 1 (segundoRegistro); / /Prueba si los limites dados por el segundo promedio y desviación / /estándar son distintos de cero, si esto no sucede estos limites //toman los valores del primer promedio como el limite inferior / / yel limite superior como el máximo valor que puede tener una //muestra capturada. Además, verifica si el valor de “Umbral”( que //contiene el primer promedio ) e s distinto de cero. if(Umbral>limite-inf I I limite-inf>=limite-sup&&Umbral!=O) 4 - 30 limite-inf=Umbral; limite_sup=4096; / /La variable “contadorAmpli.tuno” lleva la cuenta de un arreglo don( ~ //están guardados los datos de los valores a promediar, con esta //variable comprueba si ya se ca1cul.o el primer promedio, cuando / /es igual al valor“TOTCOMPARA”. if(segundoRegistro>=limite_inf&&segundoRegistro<=limite_sup&& contadorAmplitUno>=TOTCOMPARA) i PromedioPicos2(); / / Calcula el segundo promedio si / /tiene el total de datos en el arreglo... Corrimiento(segundoRegistro);/ /Guarda el nuevo valor del amplitud / /idel pico actual. primerRegistro=segundoRegistro;/ /Actualizo variables segundoRegistro=muestra-act; return 1 ; //Regresa un uno si el máximo detectado pasó el limite I amplitud. //de else ; I else ; primerRegistro=segundoRegistro;/ /Actualiza las variables. segundoRegistro=muestra-act; return O ; //Regresa un cero si el valor de amplitud no es un máximo o 1 //el valor del pico no esta en el rango de amplitud. PromedioPicosl, calcula elprimerpromedioporamplitudde un número “TOTCOMPARA” demuestras, y seactualizaestepromedioconcada nuevo pico detectado. Real PromedioPicos 1 (Real valor-pico-act) i int jj,poblacion=TOTCOMPARA; Real prom; //Verifica si el contador “contadorAmplitudUno” indica si no se ha / /llenado el arreglo con las’muestras necesarias para calcular el / /promedio. Además, comprueba si “valor-pico-act” esta dentro del / /rango de amplitud. if(contadorAmplitUno~poblacion&&valorpic valor-pico_act>=O) . ... . . , 4 - 31 / /Guarda el valor de pico actual.. . { PrimA~nplitud[contadorAmplitUno]=valor~pico~act; ++contadorAmplitUno; //Actualiza el contador.. return O;). //Termina ... . / /Si el arreglo esta lleno... if(contadorAmplitUno~=poblacion&&valor~pico~act~=4096&& valor-pico-act>=amplitudPromedio 1) //Hace un corrimiento... forCjj=O;jj<poblacion- l;jj++)PrimAmplitudIjj]=PrimAmplitudIjj+ 11; PrimAmpli tud[poblacion- l]=valor-pico-act; //Guarda el nuevo valor / /Calcula el promedio... actualiza. forCjj=O,amplitudPromedio1 =O;jj<poblacion;jj++) amplitudPromedio 1 +=PrimAmplitudljj]; amplitudPromedio 1 =amplitudPromedio 1 /poblacion; //Valor relativo del promedio reduciendo a u n 45% el umbral / /del valor original. amplitudPromedio 1 =amplitudPromedio 1 -(0.45*amplitudPromedio 1 ) ; I return amplitudPromedio 1 ; / /Regresa el valor del promedio. los picosporamplitud PromedioPicos2, calcula elsegundopromediode cuando tiene un total de “MUESTRAS” en el arreglo “amplitudesDetec”, y guarda valor el en la variable “umbralNive1”. También calcula la desviación estándar de amplitudes. int PromedioPicos2(void) { int pico,poblacion=MUESTRAS; //El contador “contadorPicos ” indica si el arreglo esta lleno, es decir, / /si e s igual a “MUESTRAS”. if(contadorPicos>=poblacion) { / /Calcula el promedio for(pico=O,umbralNivel=O;pico<poblacion;pico++) umbralNivel+=amplitudesDetec[pico];/ / Sumatoria.. . umbralNivel=umbralNivel/poblacion;/ /Calcula promedio.. . 4 DesviacionEstandar 1 (); / /Calcula - 32 desviación estándar. \ J else ; return O ; / /Termina calculo. Corrimiento, guarda el valor del pico actual ... int Corrimiento(Rea1 muestra-anterior) I int recorre,poblacion=MUESTRAS; //Verifica si “contadorPicos‘‘ indica que esta lleno el arreglo if(contadorPicos>=poblacion) {amplitudesDetec[O]=O; //Libera la primera posición for(recorre=O;recorre<poblacion1 ;recorre++) / /Hace el corrimiento.. . amplitudesDetec[recorre]=amplitudesDetec[recorre+11; / /Guarda el nuevo dato. amplitudesDetec[poblacion-l]=muestra-anterior; return O ; //Termina. 1 / /Si no esta llenoel arreglo.. . amplitudesDetec[contadorPicos]=muestra~anterior; / /Guarda elnuevo i / /dato. ++contadorPicos;//Actualizacontador. return O ; / /Termina. I DesviacionEstandarl,calculaladesviaciónestándardeamplitudde muestras presentes en el arreglo “amplitudesDetec”, con número total de muestras igual a “MUESTRAS”. las int DesviacionEstandarl(void) { int standar,poblacion=MUESTRAS; / /Suma del cuadrado de la diferencia del promedio y la muestra. for(standar=O,SDamplitud=O;standar<poblacion;standar++) SDamplitud+=pow((double)(umbralNivel-amplitudesDetec[standar]),2.0); //División entre el número de muestras. I 4 - 33 SDanlplitud=SDamplitud/poblacion; if(SDamplitud<O)SDamplitud=O; SDamplitud=sqrt(SDamplitud);/ /Raíz cuadrada... SDamplitud=3*SDamplitud;//Esto nos provee el 99 YOde probabilidad return O ; //Termina. t 4 - 34 IV. 1.1.2.- Búsqueda por Distancia entre Picos Lasegundapartedelalgoritmoes l a búsquedadeposibleslatidopor el criteriodedistanciaentrepicos.Enestapartesemenciona la palabra “posición” y se refiere a la posición (valor en el índice del apuntador) en el arreglodememoria,querelacionandocon la frecuenciademuestreo;se refiere al número de muestras que debe haber entre cada pico, esto para que se puedan seleccionar los picos que si cumplen con este criterio. GuardaPosicion, guarda el valor del índice (posición en el arreglo). int GuardaPosicion(int posicion) I int contador; / /El contador que lleva el control de el arreglo “posicionesDetec” e s / /”contadorPosiciones”, este determina en que lugar del arreglova //aser guardado un nuevo dato o una nueva posición. if(contadorPosiciones<NUMPICOS) //Verifica si no esta lleno el arreglo. { / /Guarda la nueva posición.. . posicionesDetec[contadorPosiciones]=posicion; ++contadorPosiciones; / /Actualiza el contador. return O;> //Siesta lleno el arreglo... posicionesDetec[0]=0; / /limpia la primera posición.. . / /hace un corrimiento... for(contador=O;contador<NUMPICOSl;contador++) posicionesDetec[contador]=posicionesDetec[contador+ 11; / /guarda la nueva posicion... posicionesDetec[NUMPICOS- l]=posicion; return O ; //Termina. 1 I MideDistancia, calcula la distancia que existe entre dos picos. Considerando que se trata de u n arreglo que se maneja como circular, es necesarioverificardoscasosparalograrlamedicióncorrecta de la distancia. El primero, el más sencillo, donde la posición actual (hablando de indices) es mayor que la posición anterior, donde con una simple resta 4 - 35 e s posiblecalcular la distancia. El segundocaso,cuando la posición actualesmenorque la posiciónanterior, esnecesariohacerunajuste para obtener la posición real ... int MideDistancia(int posicion-actua1,int posicion-anterior) int tamano=memTotal; //Comprueba si es necesario el ajuste ... if(posicion-actual<posicion-anterior) //Regresa un valor real dela distancia entre los picos actuales, //donde “tamano” es el tamañodel arreglo. return (tamano-posicion-anterior+posicion-actual); else return (posicion-actual-posicion-anterior); 1 El ajuste se realiza, primero calculando la distancia que hay de la posición la distanciaque anterior al finaldelarreglo;posteriormentesesuma existe del inicio del arreglo a la posición actual. promedio de distanciaentrepicos,los PromediaIntervalos, calcula el valoresdeestasdistanciassonguardadospreviamenteen el arreglo del “distanciasDetec” y el “contadorhtervalos ” lleva el control del llenado arreglo. También calcula la desviación estándar. int PromediaIntervalos(void) { int cuenta,poblacion=MUESTRAS; ! //Comprueba si esta lleno el arreglo ... if(contadorIntervalos>=poblacion) c for(cuenta=O,intervaloPromedio=O;cuenta<poblacion;cuenta++) intervaloPromedio+=distanciasDetec[cuenta];/ /Sumatoria de los datos. / /Calcula el promedio. IntervaloPromedio = intervaloPromedio/ poblacion; / /Calcual desviación estándar de intervalos. DesviacionEstandara(); else ; return O ; //Termina. 1 4 - 36 DesviacionEstandar2, desviación estándar de la distancia entre picos con un número total de “MUESTRAS”... int DesviacionEstandar2(void) int standar,poblacion=MUESTRAS; / /Sumatoria del cuadrado de la diferencias entre el “intervaloPromedio” y / /la muestra . for(standar=O,SDintervalo=O;standar<poblacion;standar++) SDintenralo+=pow((double)(intervaloPromediodistanciasDetec[standar]),2.0); //División entre el numero total de muestras... SDintervalo=SDintervalo/poblacion; if(SDintervalo<O)SDintervalo=O; SDintervalo=sqrt(SDintervalo); //raíz cuadrada.. . SDintervalo=3*SDintervalo; //el 99 YOde probabilidad.. . return O ; //termina. 1 SeleccionaIntervalo,determina si la distanciaentrepicosdetectadacae dentrodelrangodefrecuenciacardiacacorrespondiente,comparando entre los picos encontrados sus respectivas distancias. int SeleccionaIntervalo(int posicionActua1) i Real distanciaActual=O; distanciaActual=BuscaReferencia(posicionActual); if(distanciaActual!=O&&existeReferencia== 1) { //Sicumple es un posible pico y guarda la distancia actual y //hace los calculos correspondientesa pico detectado actualmente. GuardaDistancia(distanciaActua1); //Variabilidad en base a promedio de intervalos VariabilidadDeFrec(CalculaFrecuencia(PromediaIntervalos())); / /frecuencia actual I 4 frecuencidprox = - 37 CalculaFrecuencia(distanciaActua1); / / T o m a el mejor intervalo. if(CompruebaDistancia(distanciaActua1,variabilidadMuestras)) I return 1 ; return 1; return O ; 1 1 BuscaReferencia,detecta si existenreferencias; si estasnoexisten las busca y guarda en un arreglo las posiciones de los picos detectados, en otro caso compara estas distancias con la actual y verifica si corresponden o no a u n posiblepico. Estafunción devuelve uncerosinoexisten referencias o si el pico detectado no corresponde a un posible pico, en otro caso devuelve un uno. Real BuscaReferencia(int NuevaPosicion) { Real disTancia1=O,disTancia2=O,distanciaActual=0, limiteInf=O,limiteSup=O; //Toma los limites calculados para el rango de distancias entre picos //para un rango determinado de muestras entre picos que equivale / /al rango de ciclo cardiac0 seleccionado. 1imiteInf = distanciaMinima; limiteSup = distanciaMaxima; //Pregunta si existen datos para comparar... if(contadorPosiciones<NUMPICOS) GuardaPosicion(NuevaPosicion);//guarda nuevos datos. return O ; ) //Mide las distancias entre dos intervalos subsecuentes y el actual disTancia1 = MideDistancia(posicionesDetec[l],posicionesDetec[O]); disTancia2 = MideDistancia(posicionesDetec[2],posicionesDetec[ 11); distanciaActua1 = MideDistancia(NuevaPosicion,posicionesDetec[2]); //Comprueba si se ha perdido un latido con respecto al limite superior if(disTancia1 >limiteSupI I disTancia=!>limiteSupI I distanciaActual>limiteSup) 4 f existeReferencia = O ; / / reinicia busqueda de referencia, contadorPosiciones = O ; return O ; 1 //Compara contra el limite inferior. if(disTancia1 <limiteInfI I disTancia2<limiteInfI distanciaActual<limiteInQreturn O ; I //Buscamínima diferencia de distancia entre picos //anteriores. if(CompruebaDistancia(disTancia1,disTancia2)==0) return O ; //termina si no cumple ... //busca mínima diferencia con la referencia actual. if(CompruebaDistancia(disTancia2,distancidctual)== 1) { 1 GuardaPosicion(NuevaPosicion); existeReferencia = 1 ; return distanciaActua1; I return O ; t int CompruebaDistancia(int distanciat\nterior,int distancidctual) Real diferencia,limiteInf,limiteSup; / /Calcula la diferencia entre distancias... diferencia = 0.03*frecuenciaMuestreo+20; //obtiene un rango de diferencia ... limitelnf = distancidnterior-diferencia; IimiteSup = distanciaAnterior+diferencia; / /compara. if(distancidctual>=limiteInf&& - 38 4 - 39 distanciaActual<=limiteSup)return 1 ; return O ; \ J CalculaFrecuencia,una vez que el programahadetectadointervalos de referencia es posible calcular una aproximación dela frecuencia cardiaca. Real CalculaFrecuencia(int distanciaEntrePicos) { Real frecuencia,Periodo-muestreo; Periodo-muestreo= 1 /(Real )frecuenciaMuestreo;/ / [sJMUESTRAS] frecuencia= 1 / (distanciaEntrePicos*?eriodo-muestreo); / / [s/MUESTRAS]"[MUESTRAS]= 1/ [ S ] return (frecuencia); VariabilidadDeFrec, calcula la variabilidad de la frecuencia tanto en unidades de Hertz como por número de muestras. <. Real VariabilidadDeFrec(Rea1 frecuencia) { Real intervalo,a=O,b=O,Ti; if(frecuencia<=O)frecuencia=1 ; intervalo= 1 / (Rea1ffrecuencia;j/ [ 1 / 1/ s ] = [ s ] if(intervalo<0.023&&intervalo~O.O1) {a=0.9;b=0.002 l;} / /Criteriospara elindice de else(a-1 . O 0 0 l;b=0.0001;}/ /variabilidad(pendiente y cons/ /tante de la recta Ti=a*intervalo+b; / / [SI if(Ti<=O)Ti=1 ; variabilidadHertz= 1 /Ti; / /Hz variabilidadMuestras=frecuenciaMuestreo*Ti; / / [MUESTRAS/s]*[s]=[MUESTRAS] return (VariabilidadMuestras); } 5-1 V.l.- Gráficas de Respuesta de los Filtros Las siguiente gráficas de respuesta corresponden a filtros cuya frecuencia de muestre0 es de 330 Hz. Filtro pasa banda con rango de frecuencias 2 0 a 30 Hz. l.ook Y 5.00 o. o 1 , Frecuencia Central :24.609Hz : 4. Filtro pasa banda con rango de frecuencias entre 40 a 50 Hz. Frecuencia Central : 44. 531 Hz. 0.0 - 1 o .o I 1 I I I I I I , 1 I I I I I 1 18.750 H z / D i v 5 - 2 Filtro pasa banda con rango de frecuencias entre 60-70 H z 1 I I I o .o Frecuencia Central : 64.453 Hz. I I I I , I 18.750 Hz/Div. I Filtro pasa banda con rango de frecuencias entre 80 a 90 HZ. 1.000 4 5.000 1 o .o I I I I 1.8.750 Hz/Div. 1 I I I 5-3 Filtro pasa banda con rango de frecuencias entre 100 a 1 10 Hz. 1.000 - Frecuencia Central : 104.SS3 Hz. 0.0 1 5 .O00 I I 1 0.0 I I 0 r I I 13.750 Hx/Div. Filtro con rango de frecuencia entre 20 a 30 Hz,con frecuencia de muestre0 de 1000 Hz.!. l*Oool I 0.0 I I I 62.500 Hz/Div. , I I 5 - 4 Los filtros fueron diseñados en base a las ventanas de Hamming, es decir, se tratadefiltrostipos FIR. Existendiferenciasrespecto a la selectividadde los filtros, esta diferencia es notoria modificando la frecuencia de muestreo. Respecto a la selectividad, esta sería aún mayor si fueran disenados los filtros con un mayor número de coeficientes. Sin embargo, esto influiría en gran parte en la velocidad de procesamiento. La respuesta en fase, en el caso de los filtros digitales, siempre tendremos una respuesta lineal al menos en la banda de paso. En la frecuencia de muestreo seleccionada para el diseño según el teorema Nyquist, estafrecuenciaesaproximada ya quetenemosunampliorango frecuencias en las que va ha estar oscilando el ciclo cardiaco. de de Como esdeobservarseen elúltimocaso, elfiltro diseñadocon 1000 Hz de frecuencia de muestreo, la selectividad disminuye considerablemente. En base a lo anterior es necesario considerar para la captura de los datos; una frecuencia de muestreo lo suficientemente grande, para que de esta manera se obtengaunarespuestaoptima delfiltro y ademásseaposibledistinguirlos picos que resultan de los ruidos cardiacos, cuando estos se presenten. c 6-1 VI. 1 .-Manual de Usuario El ordendecomosemuestran alguno de los pasos se omite procesamiento. las opcionesesindispensable, el programa generará errores en ya que si el 1 .- La primer pantalla muestra una presentación del programa; no se debe oprimir tecla alguna, debe esperar unos segundos(siguiente ventana). UNIVERSIDAD AUTONOMA METROPOLITANA IZTAPALAPA C. B . I . SEMINARIO DE PROYECTOS I 1 PROCESAMIENTO DE S E Ñ A L DE -FCG- EN TIEMPO REAL. 2.- Unasegundapantallamuestralasopcionesquetiene elprograma (menú principal). Debe seleccionar con número la opción, cualquier error tecleado solo genera la espera del número correcto. MENU PRINCIPAL < O > CARGAR DATOS < 1 > LIMITES DE FRECUENCIA <2> MUESTRA GRAFICA <3> TERMINAR 6-2 3.- E n la opcióndecargardatos,muestraunsubmenúquemuestra el origen deseado de los datos, debe ser seleccionado oprimiendo un número. Los casos se muestran en la siguiente ventana, C A R G A R LOS D A T O SD E : l . ARCHIVO 2 . TARJETA El origen de los datos incluye la frecuencia de muestreo. Si existe un error en la lectura del archivo muestra un mensaje “no se abrió el archivo”, y regresa al menú principal; este error se puede presentar debido a que este mal la ruta de acceso del archivo o por un error de tecleo de la ruta de acceso. Si el acceso fue correcto el programa regresa el mensaje “ya fueron cargados los datos”. E n el caso de unarchivo,lafrecuenciademuestreonotienequeser seleccionada; este dato encuentra se al principio archivo, del Posteriormente lee el número de datos. Para el caso de la habilitación de la tarjeta, la frecuencia de muestreo se selecciona, muestra un mensaje al teclear la opción “2”; pide la frecuencia de muestreodeseada y envía el datonecesarioalcontadorprogramable (8253-5). Después de ejecutarse cualquiera de las opciones regresa al menú principal. 6-3 4.- Para seleccionar el rango de detección del ciclo cardiaco, debe oprimir con letra la opción mostrada en el submenú. la opción el programa toma por default valores distintos primeras; como se muestra a continuación. Si ocurre un error al teclear a las dos RANGO DE FRECUENCIA A DETECTAR ( latidowminuto 1 70 - 90. 120-180 DEFAULT 100-200. A. B. E s importante, que antes de iniciar el procesamiento, debe seleccionar el los que seguramente estará la señal rango de ciclos cardiacos en capturada. De ahíelhechodetenerprimerolosdatos o seleccionar la frecuencia de muestreo, ya que el rango depende de este parámetro para calcular elnúmerodemuestras máximo y mínimoentrecadaciclo cardiaco. 6 - 4 5.- Al hacer la llamada a la opcióndemostrargráfica,cambiaal modo gráfico el monitor y muestra un mensaje de espera. Si existe un error al inicializar los gráficos muestra el mensaje correspondiente. En otro caso, muestra el mensaje “preparando gráficos”, y muestra la siguiente pantalla de gráficos. E s muycomúnque, si no se encuentrauncontrolador de gráficos (archivos *.BGI) el programa pedirá la dirección correcta de dicho controladorhastaqueobtengalarutacorrecta, solotienetresopciones para lograr esto o el programa terminará. En la pantalla de gráficos .muestra dos funciones de teclas. Para la tecla “F2” su función inicializar es las variables que se utilizan en procesamiento.Latecla “F3” muestraunmenú defiltros, los cualesse pueden seleccionar oprimiendo el filtro requerido, al ancho de banda que se desee filtrar (ver la siguiente gráfica). 6-5 I I I I I /, .” ”. E n las pantallas mostradas anteriormente se puede apreciar las funciones en la barra superior, así como el modo de salida del programa; desde luego que para salir delprograma,debeseroprimida una tecla diferente de la función “F2”y ”F3”.E n la barra inferior, se muestra el valor del número de canal que se observa en la pantalla (Solo cuando esta activa la tarjeta, en la opción de datos de archivo puede tomar cualquier valor; puesto que no se incluyó como parámetro al guardar los registros). Además se aprecia en la esquina inferior derecha el valor de la frecuencia de muestreo. Lafrecuenciaqueseindicacomoresultado“FRECUENCIA <HZ>”, e s el valor aproximado de la frecuencia instantánea. La “VARIABILIDAD” es un para ser calculada. datos no real, puesto que, no tiene los datos correctos El valor “SD”e s la desviaciónestándar del númerodemuestrasentre intervalos. Al momento de oprimir cualquier tecla, distinta de las funciones, regresa al menú principal cambiando del modo gráfico al modo texto de la pantalla. 6-6 6.- E n el momento de que en la pantalla se muestra la curva procesada o la (parte inferior en el área de gráficas); se muestra un desplazamiento forma de los picos de la curva no son los adecuados, es necesario oprimir la tecla ‘‘€72’para ’ reinicializarelprocesohastaobtenerlaformade los picos más adecuada para la detección; ejemplo: (ver las siguientes gráficas). dos curvas. La curva superior En todas las gráficas se aprecian corresponde a la señal original. Mientras que la curva inferior corresponde a la señal procesada. Gráfica 1 : 6 - 7 Gráfica 2 : 7 - 1 OBSERVACIONEStf electrocardiografiaera unaseñalde Estealgoritmoalserprobadocon bastante eficiente, de tal forma que (la la posibilidaci de medir la frecuencia instantánea. Esto se debe a que la presencia del complejo QRS está más definido, es el caso contrario que se presenta en la fonocardiografia. El criteriodeamplitudsiemprefue dificilde definiradecuadamente,ya que al presentarse un pico de amplitud muy grande, el umbral (promedio) se disparaba a valoresmuyporarriba delpromediodeamplituddelos picos correspondientes a un latido, lo que originaba que los picos la presencia subsiguientesnofuerandetectados.Estogeneralmentepor de un artefacto. Considerando que en aplicación normal (detección directa defonocardiograma)siempreexistenartefactosdemovimiento o ruido respiratorio. Es necesarioconsiderarque en elmonitoreode la señalderuido,los cambios de la distancia del micrófono(transductor de sonido) por movimientosrespiratorios,provocanque la amplituddelruidocambie debidoalalejamiento o acercamiento del transductor.Estoscambios de y amplitud provocan que el pico que se presenta sea de menor amplitud, ocasiona que el pico no rebase el umbral, por lo tanto no es detectado y se pierde la referencia. se pudoverque al presentarse ruidos En elmismosentido,también respiratorios o artefactos elfiltradono logró eliminarestasfrecuencias, después haber de procesado señal, observaron la se picos correspondientes a la presencia delruido en cuestión. En algunos casos, los artefactosquesepresentabanestabantraslapadosuocultabanun ruidocardiaco, lo queocasionabaque elpico obtenidoeramuygrande, por lo tanto, al pasar por la etapa de discriminación por amplitud el pico resultante no eradesuficienteamplitudparaserdetectado. Es sucede m á s a menudo cuando se muestrea la señal a m á s de 500Hz. Sin embargo, al muestrear a 300 o 330Hz, la señal se observó limpia de ruido, aunque se seguía presentando el problema de el filtrado antes mencionado. tt En el caso de observaciones y comentarios, para mayor referencia se muestran gráficos en anexo. 7-2 COMENTARIOS Para hacer uso de este programa, debido al alto número de operaciones, es indispensable una PC que cuente con coprocesador matemático, sin este la velocidad de proceso es extremadamente lenta. Es importante mencionar la frecuencia de muestreo que se esta utilizando, al programar el 8253 con frecuencias de muestreo mayores a lOOOHz se debe verificar que sea la indicada, ya que el calculo de divisor es por medio de raíz cuadrada y un redondeo, que produce un cierto margen de error. El rangodeprecisióndelafrecuenciademuestreo,esposiblemedirlo observando la salidadelaseñal del 8253 en elpin 7 , medianteun osciloscopio y hacer los ajustes necesarios. El objetivo principal de tener teclas especiales durante el proceso es el de poder observar los cambios instantaneos que ocurren en el mismo. E n el caso de “FY,en ocasiones sucede que el umbral de amplitud este muy alto debido a la señal actual; pero al presentarse un cambio de amplitud o al mover la amplitudde la señal a u n a demenor,esnecesariocomenzar nuevamente el registro, inicializando la variables. De igual manera la tecla “F3”,permite visualizar los cambios de la curva o señal procesada al mover el tipo de filtro. Al momento de iniciar el proceso, el filtro debe ser inicializado, ya que en la curva de la señal procesada en forma aleatoria se presenta un offset en la curva, se debe oprimir la tecla F2, para reinicializar el proceso o h a s t a ver que este offset halla desaparecido. La frecuencia de muestreo a 300 o 330Hz,se observó suficiente para lograr apreciar los picos debidos al ruido producido por un latido. E n el caso de que no se llegaran a apreciar los picos; después del procesamiento, basta conquesemultiplique por, unaconstantedichoresultadodespués de haber derivado, para lograr la amplificación de la señal procesada . 7 - 3 CONCLUSIONES La solución dada a este algoritmo es un preliminar, los resultados obtenidosdanideadelospuntosimportantesdelmismo.Unasolución la utilización del modelo alternativa para un mejor control del proceso es deobjetos.Conestoseobtendráunmejorcontroldelasvariables y procedimientos. Es de observar que en muchos equipos el monitoreo de señales fisiológicas este acompañado de otras curvas monitoreo. de Haciendo las modificacionesnecesarias a la interfacedecapturadedatos,esposible rastrear canales simultáneos. Además, es necesario incrementar la frecuencia de muestreo en forma proporcional a número de canales; dada por FM*N(FM: frecuencia de muestreo por canal, y N: número de canales). Relacionando lo anterior, existe un tipo de algoritmos de filtrado que son mucho más eficientes que el que se utiliza en este trabajo, dichos filtros sonconocidoscomo“filtrosadaptivos”.Estaaplicaciónrequieredelas diferentesserialesinvolucradas,lascualesson:ruidocardiaco,ruido la ayuda muscular, ruido respiratorio, artefactos de movimiento, etc.. Con de este método se correlacionan las señales y se filtra la señal deseada. Se ha observado que esta herramienta de procesamiento es bastante eficiente. En general, durante el desarrollo del trabajo se puede observar los puntos clavesenlosqueelprogramadebediseñarseparalograrunamayor eficiencia. Los resultados obtenidos muestran un buen avance y proporcionan ideas importantes, para un posterior mejoramiento del mismo. La utilidad de este algoritmo es interesante y de amplia aplicación, sobre todo lo que se refiere a la medición de la frecuencia instantánea, en especifico, la medición de la variabilidad de la frecuencia cardiaca latido a latido, lo cual, nos da la posibilidad de obtener la curvadevariabilidad, como objetivo al cual deberá ser enfocado el mejoramiento del algoritmo. El algoritmodedetección e s eficiente,lapruebahechaconunECG (Electrocardiograma) lo muestra. La precisión con que realiza la detección es bastante buena. Sin embargo, la etapa de filtrado no e s la adecuada. El tipo de filtros utilizados; solo obtiene el área bajo la curva de las muestras presentes, lo que provoca es que no sean eliminados los artefactos, por lo tanto, ocasiona los errores antes mencionados. Fue posible medir el ciclo cardiaco, sin embargo, no instantánea. fue posible de manera ANEXO G r h f i c a No. 1 A- 1 ANEXO G r a f i c a No. 2 A-2 ANEXO Grafica No.3 A-3 ANEXO G r a f i c a No. 4 A - 4 ANEXO A - 5 G r a f i c a No. 5 P 'I, 1,". ANEXO A - 6 G r h f i c a No. 6 111 ANEXO Grafica No. 7 A-7 BIBLIOGRAFIA Peña, M., 1994, Método Automatizado para la Medición del Ciclo Cardiac0 Fetal por FCG, Ing. Biomedica, vol. XV, NO.2, pigs. 64-74. Peña, M, 1994, Comparation of Abdominal ECG and phonocardiography for instantaneus fetal heart rate detection, World Congress on Medical Physics and Bionledical Enginering, Brasil. Guyton, A., Fisiología Humana, Edit. Interamericana, 6” Edición, pag‘s [268-2711. Kamas, A., Digital Signal Processing Experiments (User’s Manual). la Edición, Edit. Prentice-Hall, pag’s 57 -6 1. Brey, B., The Intel Microprocessors. 8086/8088, 80186, 80286. 80386, and 80486 (Architecture, Programing, and Interfacing). 1” Edición, Edit. Macmillan Publishing Company. Goofrey, J., LenguajeEnsamblador para Microcornputadoras, 1” Edicion, Edit. Prentice-Hall, Cap’s. 2, 5. PCL-812 ENHACED MULTILAB-CARD,USER‘S MANUAL. Aljama , T.,1992, Procesamiento Digital de Señales. 1”Edicion, Edit. UAM. Schildt, H., 1994, Turbo C/C++ 3.1 (Manual de Referencia), 1” Edicion, Edit. Osborne McGraw-Hill. 7