Desarrollo e implementación electrónica de un EMG para monitorización de la actividad deportiva
Full text
ESCUELA DE INGENIERÍA DE TELECOMUNICACIÓN Y ELECTRÓNICA TRABAJO FIN DE GRADO “Desarrollo e implementación electrónica de un EMG para monitorización de la actividad deportiva” Titulación: Grado en Ingeniería en Tecnología de la Telecomunicación Mención: Sistemas Electrónicos Autor: Dailos Fernando Ramírez Guski Tutor: Dr. D. Alfonso Medina Escuela Fecha: Diciembre de 2015
ESCUELA DE INGENIERÍA DE TELECOMUNICACIÓN Y ELECTRÓNICA TRABAJO FIN DE GRADO “Desarrollo e implementación electrónica de un EMG para monitorización de la actividad deportiva” HOJA DE FIRMAS Tutor Alumno Fdo.: Dr. D. Alfonso Medina Escuela Fdo.: Dailos F. Ramírez Guski Fecha: Diciembre de 2015
ESCUELA DE INGENIERÍA DE TELECOMUNICACIÓN Y ELECTRÓNICA TRABAJO FIN DE GRADO “Desarrollo e implementación electrónica de un EMG para monitorización de la actividad deportiva” HOJA DE EVALUACIÓN Calificación: ___________________________ Presidente Fdo.: Vocal Secretario/a Fdo.: Fdo.: Fecha: Junio 2015
Agradecimientos En primer lugar quisiera agradecer a D. Alfonso Medina Escuela la oportunidad que me ha brindado para realizar este proyecto y aprender de él, y a la División COM del Instituto Universitario de Microelectrónica Aplicada y sus laboratorios por prestarme las herramientas esenciales para la realización del Trabajo Final de Grado. A mis padres, porque son mi inspiración y siempre me han regalado su tiempo para darme consejos y ánimos. Y por supuesto el resto de mi familia, ojalá pudieras leer esto abuelo. A todos y cada uno de mis profesores, desde el colegio hasta la Universidad, ya que de todos he aprendido cosas valiosas. A todos mis amigos de siempre, Samir, Sergio, Luke, Jean Paul, Nelson y Pamela. Son los mejores amigos que uno puede desear, muchas gracias por ser como son. A todas las amistades que he establecido en mi vida universitaria, porque me han ayudado a despejar la cabeza y han sido capaces de sacarme sonrisas hasta en los peores momentos, en especial a Jiménez, Horacio, Alex, Sebas y alguno que se me escape. A la Residencia Universitaria de Tafira y cada unos de sus trabajadores por esos cuatro maravillosos años de alojamiento. GRACIAS, de corazón.
Tabla de contenido Introducción ........................................................................................................................ 1 I. Antecedentes ........................................................................................................... 1 II. Objetivos .................................................................................................................. 2 III. Contenido de la memoria ...................................................................................... 3 1. El sistema muscular ...................................................................................................... 4 1.1 Introducción ......................................................................................................... 4 1.2 Músculo esquelético ............................................................................................. 5 1.3 Propiedades musculares ....................................................................................... 6 1.4 EMG (Electromiografía) ......................................................................................... 7 1.4.1 Introducción .................................................................................................. 7 1.4.2 Propiedades bioeléctricas del tejido muscular esquelético .............................. 8 1.4.3 Características de las señales EMG ............................................................... 10 1.4.4 Procesos para la adquisición de una señal EMG ............................................ 11 1.4.5 Campos de aplicación .................................................................................. 13 1.5 Solución propuesta ............................................................................................. 13 2. Hardware del sistema ................................................................................................. 15 2.1 Introducción ....................................................................................................... 15 2.2 Muscle Sensor v3 ................................................................................................ 15 2.2.1 Introducción ................................................................................................ 15 2.2.2 Características ............................................................................................. 16 2.2.3 Especificaciones eléctricas ........................................................................... 17 2.2.4 Esquemático ................................................................................................ 17 2.3 Microprocesador ................................................................................................ 23 2.3.1 Introducción ................................................................................................ 23 2.3.2 ARM Cortex-M3 ........................................................................................... 23 2.3.3 Características del STM32F103VCT6 ............................................................. 27 2.4 Placa de desarrollo HY-MiniSTM32V .................................................................... 29 2.4.1 Introducción ................................................................................................ 29 2.4.2 Características ............................................................................................. 29 2.5 Prestaciones del STM32F103VCT6 ....................................................................... 32 2.5.1 GPIO (General Purpose Input/Output).......................................................... 32
INTRODUCCIÓN 3 6. Desarrollar una aplicación Android sobre la cual monitorizar datos. 7. Comunicar dicha plataforma Android con el microprocesador ARM CortexM3. 8. Desarrollar interfaz gráfica de visualización de datos en la plataforma Android. III. Contenido de la memoria A continuación se describe brevemente los temas a desarrollar a lo largo de esta memoria del TFG. Se ha dividido la memoria en los siguientes capítulos: Capítulo I: El músculo: En este capítulo se describe tanto el músculo como sus propiedades. Además se detalla el análisis de las señales bioléctricas conocida como EMG. Capítulo II: Hardware del sistema: En este capítulo se detalla los criterios de selección de los distintos componentes hardware empleados a lo largo del desarrollo y una descripción de los mismos. Capítulo III: Desarrollo del sistema: En este capítulo se describirá la integración electrónica adoptada entre los distintos componentes del sistema para la adquisición de la señal bioeléctrica de interés y los distintos procesos que se han tomado para la correcta representación de la misma. También se describe el firmware desarrollado para alcanzar todas las etapas. Capítulo IV: Resultados: En este capítulo se mostrarán los resultados obtenidos del sistema desarrollado mediante imágenes que faciliten su lectura y análisis. Capítulo V: Conclusiones: En este capítulo se discutirán las distintas aplicaciones que podría tener el sistema desarrollado además de las posibles líneas futuras que podría presentar. Capítulo VI: Presupuesto: En este capítulo se detallará el presupuesto correspondiente a la ejecución de este proyecto.
INTRODUCCIÓN 4 1. El sistema muscular 1.1 Introducción Una de las características de los animales es su capacidad de realizar movimientos. Este movimiento es posible a la existencia de los músculos, formados por células que pueden modificar su longitud [5]. El cuerpo humano cuenta con un sistema muscular, que es el conjunto de más de 600 músculos [6]. La función mayoritaria de estos músculos es la de producir movimientos en las distintas partes del cuerpo. Figura 1. Sistema muscular humano
INTRODUCCIÓN 5 Existen tres tipos de tejidos musculares, que a su vez conforman tres tipos de músculos: 1. Tejido muscular esquelético: También puede denominarse músculo voluntario o estriado. Se denomina voluntario debido a que se contrae por voluntad propia. 2. Tejido muscular liso: También puede denominarse visceral o involuntario. La localización de estos músculos se encuentra en las paredes de los vasos sanguíneos y linfáticos, el tubo digestivo, las vías respiratorias, la vejiga, las vías biliares y el útero. 3. Tejido muscular cardiaco: Es el músculo que se encuentra en las paredes del corazón. No está bajo el control voluntario [7]. En este proyecto, el músculo de estudio es el denominado músculo esquelético o voluntario, ya que son los músculos que se utilizan cuando realizamos actividades deportivas. 1.2 Músculo esquelético Son los músculos unidos a los huesos, y son los encargados de hacer que estos se muevan. El músculo es el elemento activo del movimiento, mientras que el hueso es el elemento pasivo del movimiento. Este tejido muscular es también conocido como estriado voluntario debido a las estrías transversales que este presenta a niveles microscópicos. Es el músculo más abundante del cuerpo humano, con una proporción del 40 % del peso corporal total aproximadamente [8].
INTRODUCCIÓN 6 Figura 2. Estructura básica del músculo (adaptado de Wilmore y Costill, 1994) Los músculos esqueléticos permiten caminar, correr, saltar y otra multitud de acciones voluntarias. Estos músculos responden a impulsos nerviosos, que viajan a través de los nervios motores que terminan en los músculos. Las respuestas del músculo a estos impulsos nerviosos pueden adaptar una u otra forma y además generan señales bioeléctricas. 1.3 Propiedades musculares A continuación se detallarán unas definiciones de interés asociada a la propiedad de los músculos: - Excitabilidad: Es la facultad de percibir un estímulo y responder al mismo. La respuesta de la fibra muscular es la producción a lo largo de membrana de una corriente eléctrica que origina la contracción muscular. - Contractibilidad: Es la capacidad de contraerse con fuerza ante el estímulo apropiado. - Elasticidad: Es la capacidad que tienen las fibras musculares para acortarse y recuperar su longitud de descanso, después del estiramiento. - Extensibilidad: Es la facultad del estiramiento. Si cuando las fibras musculares se contraen, se acortan, cuando se relajan, pueden estirarse más allá de la longitud de descanso.
INTRODUCCIÓN 7 - Plasticidad: Es la capacidad que tiene el músculo a modificar su estructura en función del trabajo que desempeñe. Así puede ser que un músculo se puede hacer más resistente o más fuerte [8]. 1.4 EMG (Electromiografía) 1.4.1 Introducción La EMG [9] es una técnica experimental que abarca el desarrollo, el registro y el análisis de señales bioeléctricas. Es un estudio sobre la actividad eléctrica de los músculos esqueléticos. Proporciona información muy útil sobre su estado fisiológico y los nervios que lo activan. Actualmente la EMG es una técnica de investigación y diagnóstico médico que permite detectar y evaluar enfermedades neurológica-musculares, y también se utiliza cada vez más para la investigación en la ciencia del deporte [10]. Si los nervios involucrados en la generación y transmisión de los comandos de activación muscular están afectados, pueden variar las características de generación de los potenciales de acción (frecuencia, amplitud, entre otras), mientras que si son los músculos los que están afectados, varían las características de transmisión de los impulsos (amplitud, velocidad de conducción, entre otras) [11]. Las señales bioeléctricas se miden mediante dispositivos llamados electrodos, los cuales se encargan de convertir las corrientes de tipo iónico producidas por la distribución de potencial generada en el interior del tejido vivo en corrientes de tipo eléctrico que pueden ser medidas y acondicionadas para su posterior análisis y tratamiento. Este estudio se realiza con electrodos superficiales, que son pequeños electrodos o discos que se adhieren a la piel. Esta técnica se conoce como SEMG [12], Surface EMG, EMG superficial. La EMG superficial es el método más común de medida, puesto que es no invasiva y puede ser realizada con un mínimo de riesgo sobre el paciente.
INTRODUCCIÓN 8 1.4.2 Propiedades bioeléctricas del tejido muscular esquelético Cuando la membrana de los músculos es excitada mediante la corriente iónica generada por los axonas (prolongación de neuronas especializadas en conducir el impulso nervioso desde el cuerpo celular hacia otra célula) de las neuronas motoras, cambia la permeabilidad selectiva permitiendo la entrada de iones a las células, de manera que se genera una avalancha de dichos iones al interior de la célula para intentar reestablecer el equilibrio, con lo que el potencial de la transmembrana resulta ligeramente positivo. Este potencial de acción es el que se conoce como potencial de acción (PA) de la unidad motora (UM), (PAUM), y se dice que en ese momento, las fibras musculares se encuentran despolarizadas. El proceso por el cual las mismas cambian de estado de reposo a estado de acción se denomina despolarización y es seguido de un evento de repolarización que retorna a las fibras al estado de reposo [13]. Esta actividad se puede observar en la Figura 3. Figura 3. Transición entre el potencial de reposo y el potencial de acción Las fibras musculares (FMs) son células alternantes debido a las proteínas contráctiles presentes en su interior. La contracción se verifica mediante el desplazamiento de estas proteínas entre sí. Es el sistema nervioso quien codifica el grado de contracción de las fibras musculares (FMs) según la frecuencia de los impulsos nerviosos de las motoneuronas alfa (neurona del sistema nervioso central que proyecta
INTRODUCCIÓN 9 su axón hacia un músculo o glándula). Los impulsos nerviosos son potenciales de acción (PAs) que se transmiten a las células musculares. El conjunto que forma una motoneurona alfa y las FMs inervadas por ella se conoce como unidad motora (UM) y constituye la unidad anatómica y funcional del músculo. El registro de las descargas de las fibras musculares (FMs) de una unidad motora (UM) se conoce como potenciales de acción (PA) de unidad motora (PAUM). En condiciones normales, la amplitud media de los PAUMs es de unos 0,5 mV y la duración varía entre 8 y 14 ms según el tamaño de las UMs. La amplitud, y las propiedades de las señales EMG tanto en el dominio del tiempo como en la frecuencia dependen de factores tales como: El tiempo y la intensidad de la contracción muscular. La distancia entre el electrodo y la zona de actividad muscular. Las propiedades de la piel (por ejemplo el espesor de la piel y tejido adiposo). Las propiedades del electrodo y el amplificador. La calidad del contacto entre la piel y el electrodo. La exploración EMG comprende el registro de la señal bioeléctrica en tres estados funcionales. - En reposo: No se encuentra actividad debida a la relajación del músculo. - Durante una contracción débil: Se activan un número escaso de UMs y se pueden captar las PAUMs correspondientes. Para lograr esto el paciente debe realizar una contracción débil y mantenida. Si el grado de contracción es excesivo se activan demasiadas UMs y las descargas se superponen, con lo que sus formas de onda (FOs) se distorsionan. - Durante una contracción voluntaria máxima: En este estado se genera información sobre la población de UMs funcionantes.
INTRODUCCIÓN 10 1.4.3 Características de las señales EMG Una de las características básicas para lograr los objetivos de este proyecto es saber el rango espectral de las señales EMG. La frecuencia de las señales EMG generales comprende un rango aproximado de entre 0 y 500 Hz, pero como en este trabajo se van a adquirir las señales a través de electrodos superficiales, reduce este rango espectral a una banda entre 10 y 400 Hz. Dicho ancho de banda se ve afectado principalmente por la forma de onda (FO) de los PAUMs de las UMs activas, aunque también depende de la frecuencia de generación de los PAUMs. No obstante, tanto por el método de adquisición con electrodos superficiales o electrodos de inserción, la energía espectral se concentra en los rangos de 50 a 150 Hz. Obsérvese dicho fenómeno en la Figura 4. Figura 4. Rango espectral de las señales EMG Otra característica importante es la amplitud, que depende del número de UM reclutadas, su profundidad y un número de fibras que componen cada una de ellas. Al igual que también depende de la frecuencia con la que son activadas [14]. La característica común para la clasificación de la señal EMG, es la distancia euclidiana (norma característica de la geometría euclidiana que indica cuán lejos está un punto de otro en el plano o el espacio) entre la forma de onda de los PAUM. Las
INTRODUCCIÓN 11 principales características de la señal EMG son el número de unidades motoras activas, la forma de onda de PAUM y el tiempo de inervación. En el estudio de Wellig y Moschytz, se determinó que la forma de onda de un PAUM y el número de unidades motoras activas en una contracción muscular conforman un problema cuando se desea clasificar las EMGs [15]. 1.4.4 Procesos para la adquisición de una señal EMG Hay una serie de pasos a seguir para conseguir una señal EMG [16] de forma que los expertos puedan interpretar lo que dicha señal significa. Para ello, el primer paso a ejecutar es el de la colocación de los electrodos superficiales. Los electrodos superficiales constan, normalmente de tres electrodos. Dos electrodos activos y un electrodo de referencia (mayormente negro). Se presentan a continuación las técnicas básicas de procesamiento de la señal electromiográfica: Colocación electrodos: Lo primero es identificar el músculo a medir. Se recomienda que la piel sobre la cual se van a habituar dichos electrodos esté limpia y seca. En algunos casos es incluso favorable afeitarse. A continuación se procede a la colocación de los electrodos. Los electrodos activos se colocan sobre el músculo de tal manera que estén alineados con las fibras musculares. Debe haber un electrodo, en medida de lo posible, lo más céntrico posible (en referencia al músculo) y el otro con una pequeña separación tirando hacia el final del músculo. El electrodo de referencia se coloca preferentemente un poco más alejado de ambos electrodos activos, y si es posible en algún hueso. Amplificación: Toda la instrumentación va dirigida a obtener una representación inteligible de los PAs musculares. Para ello los sistemas deben ser altamente sensibles porque las magnitudes bioeléctricas son muy pequeñas. De ahí que sea necesario amplificar la señal entre 34 y 108 dB [11].
INTRODUCCIÓN 12 Eliminación de ruido: El ruido, ya sea origen técnico o biológico, es un parámetro indeseado que acompaña a la señal que se pretende registrar y generalmente supera la magnitud de la misma. Los amplificadores diferenciales son capaces de eliminar el ruido debido a otros músculos (por ejemplo, el corazón), ya que son capaces de medir la diferencia de potencial entre los electrodos activos y de referencia, como se puede observar en la Figura 5 [11]. Figura 5. Esquemático de la configuración del amplificador diferencial. La señal EMG representada como `m´y ruido como `n´ Filtrado: Se recomienda eliminar frecuencias inferiores a 2-5 Hz (fluctuaciones lentas por movimiento de aguja si estamos en medidas invasivas) y superiores a 10 kHz (oscilaciones de la señal de origen técnico). Además se recomienda eliminar la señal a 50 Hz, siempre y cuando se está conectado a la corriente alterna de la red eléctrica, en “wearables” no hace falta [11]. Digitalización: Este proceso, ejecutado en convertidores analógicosdigitales, consiste en la obtención de medidas (muestras) a intervalos regulares de tiempo. La frecuencia de muestreo de tal conversor debe ser lo suficientemente alta como para no perder cambios significativos del voltaje [11]. La tasa de muestreo en la práctica puede ser de 1000 Hz con el fin de registrar componentes de frecuencia en la señal hasta los 500
HARDWARE DEL SISTEMA 19 instrumentación de ganancia programable y un alto rendimiento que ofrece uno de los mayores CMRR (Razón de Rechazo al Modo Común) para frecuencias altas. El CMRR de amplificadores de instrumentación que se encuentran en mercados actualmente decaen sobre los 200 Hz. Sin embargo, el AD8221 mantiene un mínimo de 80 dB de CMRR para una frecuencia de 10 kHz. En la Figura 13 se observa el esquemático simplificado del AD8221. Figura 13. Diagrama interno del AD8221 El AD8221 es un amplificador de instrumentación basado en la topología típica de 3 amplificadores operacionales. Los transistores de entrada Q1 y Q2 asociadas a corrientes fijas, de manera que cualquier señal diferencial a la entrada forzará que los voltajes de salida de A1 y A2 cambien como corresponde. Una señal aplicada a la entrada crea una corriente que pasa a través de RG, R1 y R2, por lo que las salidas de A1 y A2 proporcionan el voltaje correspondiente. Las señales diferenciales y la de modo común son aplicadas a un amplificador diferencial que rechaza voltaje a modo común pero amplifica el voltaje diferencial. La función de transferencia del AD8221 es: Las especificaciones máximas capaces de soportar este amplificador operacional son las que se detallan a continuación.
HARDWARE DEL SISTEMA 20 Figura 14. Especificaciones máximas El AD8221 es idóneo para aplicaciones que requieren una precisa adquisición de datos, para aplicaciones de análisis biomédico o para aplicaciones de instrumentación aeroespacial. La segunda etapa que atraviesa la señal, por lo que sigue al amplificador, es el circuito rectificador de la señal, cuyo propósito es conseguir que todos los valores a su salida tengan carácter positivo (por encima de 0). Figura 15. Etapa de rectificación de señal del Muscle Sensor v3 Los rectificadores de precisión convencionales tienen el problema al rectificar tensiones pequeñas (por ejemplo, 0.1 V). La caída de tensión introduce un error muy significativo en el proceso. El uso de rectificadores basados en amplificadores operacionales permite solventar este problema, pudiendo rectificar señales de muy baja amplitud sin problema [21]. El circuito de la Figura 15 es un rectificador precisión de onda completa con resistencias iguales basado en amplificadores operacionales [22]. Todas las resistencias de este circuito son iguales y su impedancia de entrada es igual al valor de la resistencia. En la Figura 16 se muestran las direcciones de corriente (flechas negras) para señales de entrada positivas. El diodo D3 conduce, de manera que
HARDWARE DEL SISTEMA 21 los amplificadores operacionales funcionan como inversores y la señal de salida de esta etapa es igual al de la entrada. Figura 16. Sentido de corriente para señales positivas Cuando las señales de entrada son negativas, el diodo que conduce es el D4, por lo que el amplificador operacional TL084 IC2B funciona como inversor. Entonces, el voltaje de salida es positivo e igual al valor absoluto de la señal de entrada. Figura 17. Sentido de corriente para señales negativas
HARDWARE DEL SISTEMA 22 El circuito siguiente a este, es el de filtrado paso bajo de señal. El circuito que se encarga de esto es el siguiente. Figura 18. Etapa de “suavizado” de señal el Muscle Sensor v3 De la Figura 18 se puede asumir que se trata de un filtro RC paso bajo. Para calcular la frecuencia de corte del filtro se usa la siguiente expresión: Esta etapa de filtrado tiene como fin reducir la cantidad de variaciones de amplitud que hay en la señal. Elimina aquellos valores cuyos son muy distintos al de sus vecinos. El efecto que tiene sobre una señal este tipo de filtrado es el que se muestra en la Figura 19, donde se toma como ejemplo una señal sinusoidal rectificada. Figura 19. Efecto etapa de filtrado sobre una señal sinusoidal
HARDWARE DEL SISTEMA 23 La configuración del PIN LAYOUT se muestra en la Figura 20. Figura 20. Pin Layout del Muscle Sensor v3 Se ha optado por esta tarjeta de acondicionamiento, además de su precio económico, porque ofrece las prestaciones necesarias para el desarrollo del TFG. 2.3 Microprocesador 2.3.1 Introducción Para el desarrollo de este trabajo es importante seleccionar el componente sobre el que recae la mayor parte de carga computacional del sistema, y que permite integrar los distintos periféricos para que realicen una función conjunta. Para este TFG se ha optado por un microprocesador de ST Microelectronics de la familia STM32, su modelo es STM32F103VCT6 [23], basado en ARM Cortex-M3. 2.3.2 ARM Cortex-M3 La familia ARM Cortex es una nueva generación de procesadores que proporcionan una arquitectura estándar para un amplio rango de demandas tecnológicas. Existen tres perfiles de Cortex: Un perfil A para aplicaciones de alto rendimiento, un perfil R para aplicaciones de tiempo real y un perfil M para aplicaciones con relación de bajo costo y buenas prestaciones del microprocesador. El ARM Cortex-M3 [24] es el procesador líder en la industria de los procesadores de 32 bit para aplicaciones altamente deterministas y de tiempo real,
HARDWARE DEL SISTEMA 24 desarrollado para permitir a las empresas desarrollar plataformas de alto rendimiento a bajo costo. El procesador ofrece un excelente rendimiento computacional y una sobresaliente respuesta a eventos. Además es altamente configurable permitiendo un amplio rango de implementaciones que requieran protección de memoria y tecnología potente para dispositivos que requieren un área mínimo. Como en el ARM9 y ARM7, el Cortex-M3 [25] tiene un pipeline de 3 estados (Fetch, Decode y Execute). El modelo de programación del Cortex-M3 trata de una arquitectura load/store, donde los datos primero han de moverse sobre un registro para luego ejercer una acción sobre ellos. Figura 21. Ejemplo modelo de programación ARM Cortex-M3 El Cortex-M3 dispone de 16 registros. Los registros del R0-R12 son de propósito general, por ejemplo, guardar variables y estados. Además posee unos registros “especiales”. Éstos son el R13, el cual hace referencia al Stack Pointer. El R14 es el Link Register, que indica la dirección de retorno, muy útil cuando se producen llamadas a subrutinas. Y por último el R15, que es el Program Counter, el que indica en cada momento a la CPU la siguiente línea de código a ejecutar. Figura 22. Registros ARM Cortex-M3
HARDWARE DEL SISTEMA 25 El xPSR es un registro conocido como Program Status Register. Este registro contiene algunos campos de bits que influyen en la ejecución de instrucciones de la CPU. Por ejemplo, uno de estos campos son los flags de condiciones como ‘N’ (Negative, ‘Z’ (Zero), ‘C’ (Carry) y ‘V’ (Overflow) que se activaran dependiendo del resultado de cada instrucción. Figura 23. Registro xPSR ARM Cortex-M3 En cuanto al modo de operación, el Cortex-M3 puede ser usado en dos tipos de modos. Estos dos modos son: - Handler (Supervisor): Donde se tiene un acceso privilegiado a la memoria y recursos de la CPU. - Thread (Usuario): Se puede estar en modo privilegiado o no. El modo privilegiado funciona muy parecido al modo Handler, y el modo no privilegiado hay zonas restringidas a donde no se puede acceder. Figura 24. Modos de operación del ARM Cortex-M3 Cabe destacar que la CPU del Cortex está diseñada para ejecutar instrucciones de tipo Thumb-2, que son instrucciones de 16 y 32 bits. El Thumb-2 mejora en un 26% la densidad del código y en un 25% el rendimiento frente a instrucciones Thumb de 16 bits.
HARDWARE DEL SISTEMA 26 Y por último comentar que el procesador ARM Cortex-M3 integra un controlador de interrupciones anidado (Nested Vector Interrupt Controller) para obtener un alto rendimiento en situaciones que puedan depender de la importancia de la respuesta ante interrupciones. El NVIC incluye una interrupción no enmascarable (NMI), y ofrece hasta 256 canales de prioridad para interrupciones. La integración ajustada entre el procesador y el NVIC permite una ejecución rápida de la rutina de servicio de la interrupción (ISR), reduciendo de manera drástica la latencia ante interrupciones. En nuestro caso se tiene un STM32, que está basado en un Cortex-M3, especialmente diseñado para aplicaciones de buen rendimiento combinado con un bajo consumo de potencia. El STM32 tiene un direccionamiento posible de 4Gbyte de direcciones bien particionadas para memoria, periféricos y propios periféricos del sistema. Consiste en arquitectura Harvard que además tiene múltiples buses que permitirán operaciones en paralelo incrementando el rendimiento general. La familia Cortex permite además el acceso a datos desalineados, asegurando un uso más eficiente de la memoria SRAM. La familia STM32 tiene 4 distintos grupos. Éstos son el “Performance Line”, “Access Line” y el “USB Access Line”. Además ha anunciado un cuarto grupo llamado “Connectivity Line”. El “Access Line” es la entrada para la familia STM32 con operaciones y simples periféricos a 36 MHz. El “Performance Line” trabaja a 72 MHz y proporciona más periféricos. Y el “USB Access Line” añade dispositivos USB para aplicaciones USB relacionadas con costo y prestaciones. El cuarto grupo llamado “Connectivity Line” trae consigo la posibilidad de comunicaciones avanzadas incluyendo un controlador USB de doble rol y un Ethernet MAC [9]. En este caso en concreto se tiene un STM32 de 100 pines, con una memoria Flash de 256 Kbyte de tamaño, es por ello que se concluye que el microprocesador concreto utilizado en el desarrollo del trabajo es el siguiente.
HARDWARE DEL SISTEMA 27 Figura 25. Microprocesador con el que se trabaja 2.3.3 Características del STM32F103VCT6 El STMF32F103VCT6 [26] incorpora un ARM Cortex-M3 de 32 bit tipo RISC de alto rendimiento que opera a una frecuencia de 72 MHz. Este microprocesador pertenece a la familia de microprocesadores STM32F103xC. La diferencia entre unos y otros se basa en el tamaño de memoria, el número de canales del convertidor Analógico/Digital, el número de puertos de entrada/salida, el número de timers y el número de interfaces de comunicación. Este procesador trabaja en un rango de tensión de alimentación de 2.0 a 3.6 V. Dispone además de un modo de ahorro de energía que permite diseñar aplicaciones de bajo consumo. Estas características convierten al STMF32F103VCT6 en un microprocesador ajustable a un amplio rango de aplicaciones tales como de control, médicas, industriales, automoción, videojuegos, entre otros.
HARDWARE DEL SISTEMA 28 Figura 26. Configuración de pines del STM32F103VCT6 A continuación se exponen algunos de los componentes más relevantes del STM32F103VCT6: - Frecuencia CPU: 72 MHz. - Memoria Flash: 256 Kbytes. - SRAM: 48 Kbytes. - 8 Timers: 4 de propósito general, 2 de control avanzado y 2 básicos. - Interfaces de comunicación: o 3 SPI, dos de ellos se pueden utilizar como I2S. o 2 I2C. o 5 USART. o 1 USB. o 1 CAN. o 1 SDIO. - 80 GPIOs. - 3 ADC de 16 canales. - 2 DAC (Digital to Analog Converter – Conversor Digital a Analógico) de 2 canales.
HARDWARE DEL SISTEMA 35 - SPI Esclavo soportando modos 0, 1, 2 y 3 y con opción de elección MSB (Most Significant Bit) o LSB (Less Significant Bit) - SPI Maestro soportando modos 0, 1, 2 y 3 y con opción de elección MSB (Most Significant Bit) o LSB (Less Significant Bit) A continuación se mostrará en la Figura 29 el FTDI Chip DS-UMFT311EV. En la figura se puede observar los distintos componentes y conectores que lo forman. Figura 29. FTDI Chip DS-UMFT311EV y sus componentes El conector CON1, según la configuración seleccionada, se utiliza como puerto de comunicación. Los conectores J3, J4, J5 y J6, que como el CON1, según la configuración seleccionada, se utilizan como puertos de comunicación de un tipo u otro. Los jumpers son para seleccionar la interfaz de comunicación deseada. A continuación se describen las funciones de los componentes del diagrama de bloques del módulo FT311D. Módulos que se pueden apreciar en la Figura 30.
HARDWARE DEL SISTEMA 36 Figura 30. Diagrama de bloques del módulo FT311D Modo de interfaz de selección (Interface Mode Selection): esto permite seleccionar manualmente el tipo de interfaz de comunicación que deseemos a través de los jumpers JP1, JP2 y JP3. Las configuraciones posibles haciendo uso de los jumpers son las siguientes: Tabla 2. Configuración para selección modo de interfaz Modo Interfaz Selección interfaz JP1 JP2 JP3 GPIO 0 0 0 UART 0 0 1 PWM 0 1 0 I2C Maestro 0 1 1 SPI Esclavo 1 0 0 SPI Maestro 1 0 1
HARDWARE DEL SISTEMA 37 USB Host: puerto USB Host en el conector CON1 que se utiliza para conectar el dispositivo Android que soporte el modo Android Open Accesory. Señales de interfaz (Interface Signals): las señales en el CON1 dependerán del modo de interfaz seleccionado previamente. Puerto de programación (Programming Port): el puerto de programación J7 se utiliza para reprogramar el dispositivo FT311D con un nuevo archivo ROM. El dispositivo no se suele reprogramar ya que viene listo para usar. En la realización del proyecto, se ha seleccionado el modo de interfaz de la UART, ya que es por este medio por el que transmitimos los datos muestreados y almacenados en la tarjeta HY-MiniSTM32V hacia el soporte Android, pasando previamente por el DS-UMFT311EV. Esto quiere decir que hemos tenido que realizar la combinación de los jumpers (JP1, JP2, JP3) según descrito en la Tabla 2. La interfaz UART en el módulo FT311D ofrece velocidades de transmisión desde los 300 hasta los 921600 bps. Los datos transmitidos por UART son en formato NRZ (Non Return to Zero). Las señales que se han usado en este módulo están disponibles en el CON1 y el J3, como se muestra en la Tabla 3. Tabla 3. Señales UART módulo FT311D Nombre señal Conector CON1 Conector J3 Número pin Tipo entrada/salida Descripción UART_TXD CON1-10 J3-3 23 Salida Transmisión datos UART_RXD CON1-9 J3-4 24 Entrada Recepción datos
DESARROLLO DEL SISTEMA 38 3. Desarrollo del sistema 3.1 Integración del sistema 3.1.1 Introducción En este apartado se describen como se han realizado las distintas conexiones entre los equipos hardware utilizados para formar el sistema electrónico del trabajo. A continuación se describe la integración de la etapa de la adquisición de la señal. 3.1.2 Etapa de adquisición de señal Los elementos usados son el Muscle Sensor v3, la placa HY-MiniSTM32V y el ADC del STM32F103VCT6. A parte se hace uso de cables conductores para las distintas conexiones, una protoboard y componentes eléctricos (resistencia y diodos) para la realización de un circuito analógico. Figura 31. Integración del sistema final
DESARROLLO DEL SISTEMA 39 La etapa de adquisición de señal es aquella en la que a través de la tarjeta de acondicionamiento de señal, y sus respectivos componentes, electrodos y cables con conector Jack, se obtiene la señal bioeléctrica. Una vez llega la señal a la tarjeta de acondicionamiento, pasa por sus distintos circuitos analógicos, explicados con detalle en el capítulo 2 dedicado al Muscle Sensor v3, produciendo así a la salida una señal legible. La salida del Muscle Sensor v3, serigrafiada en la placa como “SIG” (Véase Figura 20), se conecta a través de un cable conductor a la entrada del ADC del microprocesador a través de la placa HY-MiniSTM32V, concretamente en el pin 16 serigrafiado como “PC1”. Figura 32. Pin ADC en placa HY-MiniSTM32V Como se ha comentado, la señal del ADC fluctúa entre los valores 0 y 3.3 V, es decir en caso de recibir más voltaje por esa entrada se puede estropear el microprocesador. Ahora bien, también se ha detallado que la señal de salida del Muscle
DESARROLLO DEL SISTEMA 40 Sensor v3 puede variar desde los 0 hasta la tensión de alimentación positiva (+Vs). En nuestro caso, se alimenta el sensor con ±5 V con la fuente de alimentación Tektronix CPS250, pudiendo alcanzar la señal de salida entonces dicho voltaje. Para evitar que a la entrada del ADC del microprocesador se alcancen estos valores se ha montado un circuito de protección (diodos clamping) en una protoboard por el cual pasa la señal antes de llegar a la placa de desarrollo. El circuito montado es el que se puede observar en la Figura 33. Figura 33. Montaje circuito de protección Los 3.3 V que alimentan este circuito se aprovechan del HY-MiniSTM32V a través de su pin 48, que proporciona una tensión de 3.3 V. Figura 34. Pin 48 en placa HY-MINISTM32V
DESARROLLO DEL SISTEMA 41 La etiqueta “OUT” va conectada a través de un cable conductor a la tarjeta de desarrollo al pin PC1, que es la entrada al ADC del microprocesador. El pin 46 “GND”, es el que se utiliza como referencia para conectar el resto de las tierras. El conexionado de las tierras comunes se realiza en la protoboard. 3.1.3 Comunicación con plataforma Android En este apartado se describe la integración entre los componentes necesarios para conseguir monitorizar la señal bioeléctrica en un dispositivo Android. Los dispositivos necesarios para esta conexión son la placa HY-MiniSTM32V, el FTDI Chip DS-UMFT311EV y la propia plataforma Android. Esta etapa se realiza para mostrar en la pantalla de un dispositivo Android la señal bioeléctrica. Es decir, previo a esta comunicación, la señal ya ha sido procesada. Para enviar los datos de la señal hacia el DS-UMFT311EV se ha optado para la comunicación serial USART. En concreto se ha utilizado la USART1 del STM32F103VCT6. Como únicamente se van a enviar datos, es decir, solo se va a utilizar la función de transmisión de la USART, únicamente hace falta configurar el pin de transmisión de la USART1. El pin correspondiente a la transmisión de la USART1 es el pin 68, serigrafiado como “PA9”. Figura 35. Pin USART1 TX en placa HY-MiniSTM32V Una vez conectados los dispositivos anteriores, se ha de comunicar el DSUMFT311EV con la plataforma Android. Para conseguir esta comunicación se requiere un cable USB/Micro-USB, ya que a través del puerto USB se transmiten las señales hacia el dispositivo Android. El USB irá al conector USB del DS-UMFT311EV y el Micro-USB irá conectado al puerto Micro-USB del soporte Android.
DESARROLLO DEL SISTEMA 42 Figura 36. Cable USB/Micro-USB En la Figura 37 la conexión de estos equipos a modo de diagrama de bloques. Figura 37. Diagrama de bloques de integración para comunicación con dispositivo Android
DESARROLLO DEL SISTEMA 43 3.1.4 Prototipo de laboratorio En la Figura 38 se podrá observar el montaje físico real de los dispositivos para su correcto funcionamiento. Figura 38. Montaje físico de la integración de equipos
DESARROLLO DEL SISTEMA 44 3.2 Desarrollo Firmware 3.2.1 Introducción En este apartado se va a explicar el código que ha sido desarrollado. El lenguaje de programación por el que se ha optado para el desarrollo del mismo ha sido el lenguaje de programación C. 3.2.2 Entorno de programación Se ha estado diferenciado dos partes fundamentales en este proyecto. La adquisición de la señal y la representación de la misma por la pantalla LCD que provee la placa HY-MiniSTM32V, y la otra parte es la de la comunicación con un dispositivo Android para visualizar en el mismo la misma señal en base a una aplicación creada. Los entornos de programación utilizados han sido el Keil µVision 4.73 y el Android Studio. - Keil µVision 4.73: es una plataforma de desarrollo, basada en Windows, que combina un editor y un gestor de proyecto. Incluye todo tipo de facilidades para desarrollar aplicaciones empotradas incluyendo un compilador C/C++ o assembler, un linker, un gestor de librerías y un conversor HEX. µVision compila, ensambla y enlaza la aplicación automáticamente y proporciona un único punto para focalizar los esfuerzos de desarrollo [31]. En la Figura 39 se puede apreciar un ejemplo de cómo es el entorno de programación.
DESARROLLO DEL SISTEMA 51 /* TIM2 channel1 configuration in Compare mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); } En el capítulo 1 se describió que el rango de frecuencias para señales bioeléctricas adquiridas mediante electrodos superficiales (SEMG) se reducía de 10 a 400 Hz, entonces: El reloj del sistema (CLK) es de 72 MHz. Escogemos un valor para el Prescaler de 7200. Dividiendo el reloj del sistema entre el valor del Prescaler se consigue una frecuencia de 10 kHz. Entonces: Introduciendo entonces el valor calculado en la variable del periodo, se obtiene una frecuencia de muestreo tal que: Ahora bien, para la señal bioeléctrica que proporciona el Muscle Sensor v3 a su salida Figura 47) no es necesaria una frecuencia de muestreo de estas magnitudes. Sin embargo, se ha optado por esta frecuencia para posibilitar el muestreo de la señal bioeléctrica antes de la etapa del filtrado (Figura 48) de la tarjeta de acondicionamiento. Figura 47. Señal EMG a la salida del Muscle Sensor v3
DESARROLLO DEL SISTEMA 52 Figura 48. Señal EMG tras la etapa de rectificación - ADC_Configuration(): en esta función se configura el ADC1 de tal manera que escogemos el canal 11 para depositar los resultados del muestreo. Además se configura que el modo de muestreo sea a través de disparo único. Esto quiere decir que cada vez que se vaya a muestrear, se guarda en el canal 11 del ADC1 el valor exacto del momento de muestreo. void ADC_Configuration(void){ ADC_InitTypeDef ADC_InitStructure; /* ADC1 configuration -----------------------------------*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; /* ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; MODIFICADO */ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //MODIFICADO ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channel11 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5); /* Enable ADC1 external trigger */ ADC_ExternalTrigConvCmd(ADC1, DISABLE); //MODIFICADO /* Enable EOC interrupt */ ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); }
DESARROLLO DEL SISTEMA 53 - USART_Configuration(): la USART2 ha sido configurada para enviar los datos a través del puerto serie. Los datos que se envían son los que se muestrean, y son enviados hacia el DS-UMFT311EV para que éste los envíe vía USB hacia el soporte Android. La transimisión se realiza a una velocidad de transmisión de 9600 bps, la longitud de las tramas es de 8 bits, con un bit de STOP y ningún bit de PARIDAD. También se realiza dentro de esta función la configuración GPIO necesaria para la transmisión de datos. void USART_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE); /* USART1_TX -> PA9 , USART1_RX -> PA10 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; /* Velocidad de transmisión de 9600 bps */ USART_InitStructure.USART_WordLength = USART_WordLength_8b; /* Longitud de trama = 8 bits */ USART_InitStructure.USART_StopBits = USART_StopBits_1; /* Un bit de STOP */ USART_InitStructure.USART_Parity = USART_Parity_No; /* Sin bit de PARIDAD */ USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); USART_Cmd(USART1, ENABLE); } - TouchPanel_Calibrate(): esta función es la rutina de calibración del Touch Panel (Pantalla LCD Resistiva). Con esta función se consigue calibrar la pantalla mediante la colocación de tres cruces, sobre los que hay que presionar, en la pantalla resistiva. Las dos primeras cruces se colocan en las
DESARROLLO DEL SISTEMA 54 esquinas superiores del display, y la última cruz se coloca centrada en parte inferior del LCD. La primera de las cruces se puede observar en la Figura 49 Esta función ha sido creada para poder identificar el espacio temporal seleccionado en el menú programado en la función config_visual(). Figura 49. Calibración de la pantalla resisitiva - config_visual(): con esta función lo que se consigue es dar al usuario una serie de opciones de tiempo en las que quiera que se represente la señal. Estos espacios temporales son 6, 3, 2 o 1 segundo. El tiempo elegido tiene repercusión sobre la función que se encargue de dibujar la señal sobre la pantalla LCD. Se muestra en la Figura 50 el menú d selección de tiempo. Figura 50. Menú de selección de tiempo para la representación de la señal bioeléctrica
DESARROLLO DEL SISTEMA 55 3.2.4.2 Adquisición de la muestra y representación de la misma Las variables que se han creado en el programa principal son las que se encuentran a continuación. int main(void){ static int i = 0; static int j = 0; static float cociente = 0; static float result; static uint16_t valor_pixel; static uint16_t dato; static uint16_t promedio = 0; static uint16_t aux = 0; uint8_t vuelta = 0; uint16_t x = 0; uint16_t datoAlto, datoBajo; uint8_t contador= 0; static uint8_t datoTx1, datoTx0; Con la frecuencia de muestreo de trabajo, se realiza un disparo cada 0.0012 segundos (aproximadamente). Esto quiere decir que cada 0.0012 segundos la muestra que está almacenada será sobrescrita por una nueva muestra. Es por ello que se tienen que almacenar los valores de la muestra. La opción por la que se ha optado es la de crear una cola circular de valor 100. Esta cola circular será alimentada por las muestras que se vayan adquiriendo, y a la vez es la que proporciona los valores para dibujar la muestra en la pantalla. Para eliminar ruido de cuantificación, lo que se hace es colocar el comando que indica al ADC1 que realice un disparo en un bucle for, en el que se dispare cuatro veces. Estos cuatro disparos tienen una diferencia ínfima de tiempo entre sí, por lo que los valores serán muy similares. Entonces, cada vez que se dispara, el valor muestreado nuevo se suma al anterior. Una vez realizados estos cuatros disparos, se divide el valor sumado de los disparos entre cuatro, obteniendo así un valor promedio de los valores muestreados. Y este valor promedio es el que proporcionamos la cola circular. El ADC del STM32F103VCT6 tiene una resolución de 12 bits, por lo que el ADC puede dar hasta 212 = 4096 valores distintos. Desde el valor 0 para 0 V hasta el
DESARROLLO DEL SISTEMA 56 valor 4095 para el valor 3.3 V. Esto implica que hay que encontrar una relación entre los 233 píxeles en vertical y los 4096 valores que nos puede proporcionar el ADC. Para conseguir esta relación lo que se hace es multiplicar el valor muestreado por el valor de un coeficiente obtenido del cociente. Multiplicando el cociente por el valor proporcionado por el ADC, conseguimos como resultado el valor del píxel correspondiente. Sin embargo, habrá aproximadamente unos 17 valores del ADC que se representarán en el mismo píxel. Esto quiere decir, que los primeros 17 valores del ADC (0-16) serán representados en el píxel 0. Los siguientes 17 valores (17-33) serán representados en el píxel 1, y así sucesivamente. Este efecto se ve minimizado en Android, ya que cualquier dispositivo tiene mayor resolución. Para la representación de la señal en la pantalla LCD, se utilizan los valores del píxel correspondiente al último valor muestreado y justo el anterior, es por ello que no se puede reutilizar la cola circular y se debe crear un vector donde se puedan almacenar los valores. El vector que se crea es de tamaño 100. La técnica que se utiliza para dibujar es la de trazar una línea desde el valor anterior hacia el último. Con los detalles explicados se consigue una representación aceptable en cuanto a la señal real. Existe un espacio temporal para la representación de la señal, por lo que una vez completado el tiempo, la pantalla completa se encuentra con la señal dibujada. Es por ello que se hace uso de una ventana deslizante blanca que va barriendo la señal antigua para dejar sobre la pantalla la señal a tiempo real.
DESARROLLO DEL SISTEMA 57 Figura 51. Proceso de limpieza de señal anterior A continuación se muestra el segmento de código detallado anteriormente, y que representa la señal bioeléctrica sobre el TFT. While (1){ while(convertir == 0); /*Esta es la variable que cambia de valor una vez se entre en la ISR del timer1*/ for (j = 0; j< 4; j++){ ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*Habilitamos el disparo por Software del ADC*/ while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET); aux = ADC_GetConversionValue(ADC1) /*Se coge el valor proporcionado por el ADC*/ promedio = aux + promedio; /*Se va sumando a la variable promedio el valor que se va adquiriendo en cada momento del ADC*/ } ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); promedio = (promedio/j); /*Se calcula el promedio del total de unas 4 muestras que se adquieren casi simultáneamente*/ Ejes(); push (&buffer2, promedio);//Se mete en la cola circular el dato promediado en la parte superior de este código*/ resultado = popFast(&buffer2); dato = *resultado; result = (((float)dato)*(cociente)); /*Se calcula el pixel a pintar*/ valor_pixel = (uint16_t) result; /*en esta variable se guarda el pixel a pintar*/ if(valor_pixel>=233){ valor_pixel = 233; /*Forzamos a que el valor máximo de esta variable sea 233 para que en la resta no de menos de 2 en ningún momento */ } valor_pixel = 235 - valor_pixel; almacen_Datos[i] = valor_pixel; actual = almacen_Datos[i]; i++;
DESARROLLO DEL SISTEMA 58 if (i > 1){ if (vuelta > 0){ x = eje_x; for (j = 0; j< 30; j++){ LCD_DrawLine(x, 2, x, 235, White); x++; } } anterior = almacen_Datos[i-2]; if(i == 100){ almacen_Datos[0] = almacen_Datos[i-1]; i = 1; } dibujar_Linea2(eje_x,actual, (eje_x-incremento_x), anterior, Blue); contador = 0; } eje_x = eje_x + incremento_x; if (eje_x >= 310){ eje_x = 10; vuelta = 1; } 3.2.4.3 Transmisión de datos por USART En este punto se presenta el código desarrollado para transmitir los datos, proporcionados por la cola circular, a través de la USART1 hacia el receptor de la USART en el DS-UMFT311EV. Para conseguir una exacta transmisión de los datos se ha tenido que crear un protocolo de comunicación incluyendo cabeceras en las tramas. Esto ha sido necesario porque la longitud de las tramas para enviar por la USART1 son de 8 bits, mientras que los valores del ADC se guardan en variables de 16 bits, aunque solo sean relevantes los primeros 12 bits. Entonces lo que se ha establecido es dividir los 12 bits relevantes en dos tramas de 8 bits, donde los primeros 2 bits son una cabecera, y los restantes 6 son los que corresponden al valor del ADC. Tenemos una variable de 16 bits que se llama dato y las dos tramas a enviar por la USART son datoAlto datoAlto y datoBajo respectivamente. Para la primera trama (datoAlto) se realiza una AND lógica con el valor en hexadecimal FC0 (111111000000 en binario) y el valor del ADC para conservar los 6 primero bits del resultado. A continuación se desplazan estos 6 bits a la parte menos significativa de la trama, para conservar los 2 bits más significativos para la cabecera.
DESARROLLO DEL SISTEMA 59 La cabecera se introduce realizando una OR lógica con el valor hexadecimal 40 (01000000 en binario) quedando de esta manera la trama resultante con el valor binario de 01XXXXXX (X puede representar 1 y 0). A continuación se puede observar el resultado de las tramas de datoAlto, además del segmento de código dedicado a este protocolo. Figura 52. Trama correspondiente a los 6 bits más significativos del valor muestreado (datoAlto) /* Se realizan las operaciones necesarias para coger los primeros 6 bits de datos del ADC*/ datoAlto = ((dato & 0xFC0) >> 6); datoAlto = (datoAlto | 0x40); datoTx1 = datoAlto; Para la segunda trama se hace básicamente lo mismo atendiendo a que los bits que nos interesan ahora no son los 6 primeros bits, si no los siguientes 6, es por ello que el valor con el que se realiza la AND lógica varía. Para la cabecera de la segunda trama se ha establecido que se realice una OR lógica con el valor en hexadecimal 80 (10000000 en decimal), quedando una trama resultante con el valor binario 10XXXXXX. A continuación se muestra la trama y el código. Figura 53. Trama correspondiente a los 6 bits menos significativos del valor muestreado (datoBajo) /* Se realizan las operaciones necesarias para coger los ultimos 6 bits de datos del ADC*/ datoBajo = ((dato & 0x3F) | 0x80); datoTx0 = datoBajo; Por último no queda si no enviar estas dos tramas por la USART1 hacia el destino. Aquí el código empleado.
DESARROLLO DEL SISTEMA 60 /* Enviamos por la USART1 los primeros 6 bits con cabecera 0x40*/ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, datoTx1); /* Enviamos por la USART1 los ultimos 6 bits con cabecera de 0x80*/ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, datoTx0); 3.3 Aplicación Android Para desarrollar la aplicación Android han sido necesarios integrar los equipos HY-MiniSTM32V y el DS-UMFT311EV, que actúa como puente hacia el soporte Android. La explicación debida a la elección de este componente se encuentra en el capítulo 2 dedicada al FTDI Chip DS-UMFT311EV. El entorno de programación utilizado para desarrollar esta aplicación es la de Android Studio, por lo que el lenguaje de programación utilizado ha sido Java. Para configurar el DS-UMFT311EV en modo UART hay que hacerlo tanto por software como por hardware. La configuración hardware de este dispositivo es según una combinación de jumpers en los pines configuración para elección de comunicación. Los jumpers han tenido que ser colocados como se aprecia en la Figura 54. Figura 54. Colocación jumpers para seleccionar comunicación por UART La otra parte de la configuración se realiza por software, en donde se utiliza la librería del fabricante para indicar las configuraciones básicas de una UART, como puede ser la velocidad de transmisión, el número de bits, etc. A continuación se muestra el código de la configuración por Software.
RESULTADOS 67 Las señales bioeléctricas representadas por el display del HY-MiniSTM32V han sido comparadas con la señal real a la salida del Muscle Sensor v3, que ha sido medida a través de las sondas y el osciloscopio. Para las pruebas realizadas, la selección temporal escogida en el programa del HY-MiniSTM32 fue de 6 segundos para facilitar la realización de fotos. En la primera medición se realizaron varias contracciones voluntarias, cuya señal representada en el osciloscopio se aprecia en la Figura 63. Esta señal es la que se compara con la de la Figura 64 y se puede apreciar como efectivamente, las señales son prácticamente iguales, pudiendo diferenciar y relacionar las contracciones realizadas. Figura 63. Señal de varias contracciones mostrada en el PicoScope 3224 Figura 64. Señal de varias contracciones en la pantalla del HY-MiniSTM32V
RESULTADOS 68 También se presentan a continuación la monitorización de las señales musculares en el soporte Android gracias a la aplicación creada. Se contrastará la señal con su equivalente en la pantalla LCD del HY-MiniSTM32V Figura 65. Representación señal muscular en soporte Android Figura 66. Representación misma señal Figura 59 por pantalla LCD Una vez conseguido representar la señal muscular tanto por la pantalla LCD del HY-MiniSTM32V y por el soporte Android se recibe la señal en un principio por el ADC del STM32F103VCT6 (Figura 63) se determeina que los objetivos marcados en un principio han sido alcanzados.
CONCLUSIONES Y LÍNEAS FUTURAS 69 5. Conclusiones y líneas futuras El objetivo principal de este proyecto era el de monitorizar las señales biológicas musculares a tiempo real sobre un soporte Android como si de una EMG (Electromiografía) se tratase. Para ellos se ha hecho uso de recursos materiales electrónicos como recursos software. Todos los recursos software y muchos de los recursos materiales han sido aportados por la división de Equipos y Sistemas de Comunicación del IUMA. Para lograr esta representación se ha hecho uso de la tarjeta de acondicionamiento de señal Muscle Sensor v3, que conectada a la tarjeta de desarrollo HY-MiniSTM32V cumplía la función de adquisición y representación de la señal muscular sobre la pantalla LCD de la tarjeta de desarrollo. Se ha desarrollado para ello un código en el lenguaje de programación C en el entorno de programación Keil µVision4. Para conectar la placa HY-MiniSTM32V con el soporte Android se ha tenido que utilizar como puente el chip DS-UMFT311EV, debido a que la placa de desarrollo no puede enviar datos a través de ningún puerto USB. Una vez lograda la comunicación entre el soporte Android y la placa HYMiniSTM32V. Se ha creado una aplicación para representar la señal muscular en la pantalla del soporte Android utilizado. El lenguaje de programación utilizado para esta aplicación fue Java y el entorno de programación Android Studio. Como línea futura existe la posibilidad de migrar el código desarrollado para una placa con dimensiones menores como es el Maple Mini r2, con exactamente el mismo microprocesador (STM32F103VCT6). La idea al migrarlo a esta placa sería la de crear un prototipo “wearable”, aunque esto implicaría desarrollar un protocolo de comunicación inalámbrica y la inclusión de baterías para el mantenimiento de la placa. Otra posibilidad que ofrece la el proyecto desarrollado es el de controlar a deportistas profesionales para intentar crear un patrón de fatiga muscular y de esta manera evitar lesiones.
PRESUPUESTO 70 6. Presupuesto El presupuesto de este Trabajo de Fin de Grado que se va a detallar a continuación es orientativo siguiendo las recomendaciones del Colegio oficial de Ingenieros Técnicos de Telecomunicación (COITT) que ofrece una herramienta orientativa para trabajos profesionales, el presupuesto se ha desglosado en varias secciones indicando los distintos costes orientativos asociados al desarrollo del proyecto. Estos costes se dividen en: - Recursos materiales. - Trabajo tarifado por tiempo empleado. - Costes de redacción del Trabajo Fin de Grado. - Material fungible. - Derechos de visado del COITT. - Costes de tramitación y envío. - Aplicación de impuestos. 6.1 Recursos materiales Para la realización de este proyecto han sido necesarios tanto recursos hardware como recursos software. 6.1.1 Recursos hardware Los recursos materiales utilizados a lo largo del desarrollo del TFG son los siguientes: - Tarjeta de acondicionamiento de señal Muscle Sensor v3 - Placa de desarrollo HY-MiniSTM32V Dev. Board + 3.2" TFT LCD Module - FTDI Chip UMFT311EV - Fuente de alimentación Tektronix CPS250 - Osciloscopio PicoScope 3224
PRESUPUESTO 71 - 2 sondas CP-260 60 MHz - Ordenador de sobremesa Sun Microsystems Intel Core 2 - Monitor Sun Microsystems 22" LCD El periodo de amortización de un equipo electrónico está estipulado en 24 meses. Sin embargo la duración de este TFG ha sido de 4 meses, por lo que el coste del material será correspondiente a la sexta parte del precio de mercado de cada equipo. Los dispositivos comprados durante la ejecución del TFG no presentan periodo de amortización. Tabla 4. Costes recursos hardware Hardware Precio Periodo amortización Periodo de uso Importe Muscle Sensor v3 34,15 € - 4 meses 34.15 € HYMiniSTM32V 28,69 € - - 28,69 € UMFT311EV 28,65 € - - 28,65 € Tektronix CPS250 459 € 24 meses 4 meses 76,5 € PicoScope 3224 590,66 € 24 meses 4 meses 98,44 € Sondas CP-269 60 MHz 38,99 € 24 meses 4 meses 6,50 € Ordenador sobremesa 854,85 € 24 meses 4 meses 142,48 € Monitor 284,25 € 24 meses 4 meses 47,38 € TOTAL 462,79 €
PRESUPUESTO 72 6.1.2 Recursos Software Los recursos software utilizados a lo largo del desarrollo del TFG son los siguientes: - Keil µVision 4.73 - Android Studio - Microsoft Office 2013 Al igual que con el material hardware, el material software también presenta un periodo de amortización de 24 meses, por lo que el importe será calculado como la sexta parte del precio de mercado. Tabla 5. Costes recursos software Hardware Precio Periodo amortización Periodo de uso Importe Keil µVision 4.73 8.538,10 € 24 meses 4 meses 1423,02 € Android Studio 0 € - - 0 € Microsoft Office 2013 269 € 24 meses 4 meses 44,83 € TOTAL 1.467,85 € 6.2 Trabajo tarifado por tiempo empleado En este Trabajo Fin de Grado se han invertido 300 horas en las tareas de preparación, desarrollo y documentación necesarias para la elaboración del mismo. El importe de las horas de trabajo utilizadas para la realización del proyecto se haya utilizando las recomendaciones del COIT, a diferencia de que el sueldo por hora normal de trabajo de 50 € y 65 € por hora especial. Entonces utilizando la fórmula que facilita el COIT, queda que: Donde:
PRESUPUESTO 73 - son los honorarios totales por el tiempo dedicado. - son las horas normales trabajadas (dentro de la jornada laboral). - son las horas especiales. - es un factor de corrección función del número de horas trabajadas. Las horas trabajadas han sido 300 (5h · 60 días) y todas ellas en horario normal. Entonces, según el COIT el coeficiente tiene un valor variable en función del número de horas empleadas de acuerdo con la siguiente tabla: Tabla 6. Factor de corrección en función del número de horas invertidas Horas empleadas Factor de corrección Hasta 36 horas 1,00 Desde 36 horas a 72 horas 0,90 Desde 72 horas a 108 horas 0,80 Desde 108 horas a 144 horas 0,70 Desde 144 horas a 180 horas 0,65 Desde 180 horas a 360 horas 0,60 Desde 360 horas a 540 horas 0.55 Atendiendo entonces a la Tabla 6 el factor de corrección es de 0,60 debido a que las horas trabajadas se comprenden entre las 180 y 360 horas. De esta manera se queda la ecuación siguiente: Los honorarios totales por tiempo dedicado libres de impuestos ascienden a nueve mil euros (9.000 €).
PRESUPUESTO 74 6.3 Costes de redacción del Trabajo Fin de Grado El importe de la redacción del proyecto se calcula de acuerdo a la siguiente expresión: Donde: - es el presupuesto. - es el coeficiente de ponderación según el presupuesto. Para este cálculo es necesario saber el presupuesto hasta el momento del TFG, que se muestra en la Tabla 7. Tabla 7. Presupuesto Recursos Costes Recursos materiales 462,79 € Recursos Software 1.467,85 € Trabajo tarifado por tiempo empleado 9.000 € TOTAL 10.930,64 € El presupuesto calculado hasta el momento asciende a 10.930,64 €. Como el coeficiente de ponderación para presupuestos inferiores a 30.050 € viene definido por el COIT, con un valor de 1.00, el coste derivado de la redacción del Trabajo Fin de Grado es de:
PRESUPUESTO 75 6.4 Material fungible Además de los recursos hardware y software, en este proyecto, se han utilizado otros materiales como son los folios, impresión y encuadernación. Tabla 8. Costes material fungible Materiales Costes Folios 12 € Impresión 40 € Encuadernación 9 € TOTAL 65 € 6.5 Derechos de visado del COIT Los gastos de visado del COIT, precios orientativos, se tarifan mediante la siguiente expresión: Donde: - es el presupuesto del proyecto - es el coeficiente reductor en función del presupuesto del proyecto. El presupuesto P, calculado hasta el momento corresponde a la suma de los costes de ejecución material, de redacción y de material fungible. Como el coeficiente de ponderación para presupuestos menores de 30.050 € viene definido por el COIT con un valor de 1.00, el coste de los derechos de visado del proyecto asciende a la cantidad de: Por tanto el coste de los derechos de visado del proyecto asciende a setenta y cuatro euros con setenta y ocho céntimos (74,78 €).
PRESUPUESTO 76 6.6 Gastos de tramitación y envío Los gastos de tramitación y envío están fijados en 6.01 €. 6.7 Aplicación de impuestos El coste total del proyecto, antes de aplicarle los correspondientes impuestos, asciende 18.523,72 €, a lo que hay que sumarle el 7% de IGIC, con lo que el coste definitivo del Trabajo Fin de Grado es: Tabla 9. Presupuesto total del proyecto RECURSOS MATERIALES 1.467,85 € TRABAJO TARIFADO POR TIEMPO EMPLEADO 10.930,64 € REDACCIÓN DEL TFG 765,14 € MATERIAL FUNGIBLE 65 € DERECHOS DE VISADO 74,78 € GASTOS DE TRAMITACIÓN Y ENVÍO 6,01 € SUBTOTAL 13.309,42 € APLICACIÓN DE IMPUESTOS (IGIC 7%) 931,66 € TOTAL PRESUPESTO 14.241,08 € El presupuesto total asciende a la cantidad de catorce mil doscientos cuarenta y un euros y ocho céntimos (14.241,08 €). Las Palmas de Gran Canaria a 14 de Diciembre del 2015. Fdo.: Dailos Fernando Ramírez Guski
ANEXOS 83 Anexo II. En el anexo 2 se halla el esquemático del módulo de desarrollo UMFT311EV. Indica la función de los distintos pines que forman parte del FT311D. Además señala las distintas configuraciones que se pueden realizar con los jumpers para obtener el modo de comunicación que se desee. Figura 69. Esquemático FTDI Chip DS-UMFT311EV
ANEXOS 84 Anexo III. En este anexo se expondrá el código desarrollado durante el TFG. El código comprende tanto las tareas de adquisición de señal, como la de su representación y transmisión hacia el soporte Android. Este código pertenece al fichero main.c. int main(void){ static int i = 0; static int j = 0; static float cociente = 0; static float result; static uint16_t valor_pixel; static uint16_t dato; static uint16_t promedio = 0; static uint16_t aux = 0; uint8_t vuelta = 0; uint16_t x = 0; uint16_t datoAlto, datoBajo; uint8_t contador= 0; static uint8_t datoTx1, datoTx0; init_Buffer(&buffer2, 100); /* System clocks configuration -------------------------------*/ RCC_Configuration(); /* NVIC configuration ----------------------------------------*/ NVIC_Configuration(); /* GPIO configuration ----------------------------------------*/ GPIO_Configuration(); /* TIM configuration -----------------------------------------*/ TIM_Configuration(); /* ADC configuration -----------------------------------------*/ ADC_Configuration(); /* TIM Enable ------------------------------------------------*/ TIM_Enable(); /* USART configuration ---------------------------------------*/ USART_Configuration(); /* GLCD configuration ----------------------------------------*/ LCD_Initializtion(); LCD_Clear(Blue);
ANEXOS 85 /* TouchPanel Inicializacion ---------------------------------*/ TP_Init(); TouchPanel_Calibrate(); config_visual(); Retardo (10000000); LCD_Clear(White); cociente = (((float)233)/((float)4096)); calculo_Inicial(tiempo); Ejes(); while (1) { while(convertir == 0); //Esta es la variable que cambia de valor una vez se entre en la ISR del timer1 for (j = 0; j< 4; j++){ ADC_SoftwareStartConvCmd(ADC1, ENABLE); /*Habilitamos el disparo por Software del ADC*/ while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); aux = ADC_GetConversionValue(ADC1); /*Se coge el valor proporcionado por el ADC*/ promedio = aux + promedio; /*Se va sumando a la variable promedio el valor que se va adquiriendo en cada momento del ADC*/ } ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); promedio = (promedio/j); /*Se calcula el promedio del total de unas 4 muestras que se adquieren casi simultáneamente */ Ejes(); push (&buffer2, promedio); /*Se mete en la cola circular el dato promediado en la parte superior de este código*/ resultado = popFast(&buffer2); dato = *resultado; result = (((float)dato)*(cociente)); /*Se calcula el pixel a pintar*/ valor_pixel = (uint16_t) result; /*en esta variable se guarda el pixel a pintar*/ if(valor_pixel>=233){ valor_pixel = 233 /*Forzamos a que el valor máximo de esta variable sea 233 para que en la resta no de menos de 2 en ningún momento, consiguiendo así el límite superior*/ } valor_pixel = 235 - valor_pixel; almacen_Datos[i] = valor_pixel; actual = almacen_Datos[i]; i++;
ANEXOS 86 if (i > 1){ if (vuelta > 0){ x = eje_x; for (j = 0; j< 30; j++){ LCD_DrawLine(x, 2, x, 235, White); x++; } } anterior = almacen_Datos[i-2]; if(i == 100){ almacen_Datos[0] = almacen_Datos[i-1]; i = 1; } dibujar_Linea2(eje_x,actual, (eje_x-incremento_x), anterior, Blue); contador = 0; } eje_x = eje_x + incremento_x; if (eje_x >= 310){ eje_x = 10; vuelta = 1; } /* Se realizan las operaciones necesarias para coger los primeros 6 bits de datos del ADC*/ datoAlto = ((dato & 0xFC0) >> 6); datoAlto = (datoAlto | 0x40); datoTx1 = datoAlto; /* Se realizan las operaciones necesarias para coger los ultimos 6 bits de datos del ADC*/ datoBajo = ((dato & 0x3F) | 0x80); datoTx0 = datoBajo; /* Enviamos por la USART1 los primeros 6 bits con cabecera 0x40*/ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, datoTx1); /* Enviamos por la USART1 los ultimos 6 bits con cabecera de 0x80*/ while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, datoTx0); /*Ponemos a 0 de nuevo la variable convertir para que el timer le vuelva a dar valor de 1 y se dispare el ADC*/ convertir = 0; } }
ANEXOS 87 void Retardo (int cont){ int j = cont; for( j = cont; j>0; j--); } /* Función para dibujar los ejes X e Y*/ void Ejes (void){ uint16_t k; uint16_t p = 10; uint16_t x = 10; for(k = 0; k< 23; k ++){ LCD_DrawLine(12,p,8,p,Black); p = p +10; } LCD_DrawLine (x,2, x, 235, Black); //Eje y LCD_DrawLine(310,236,10,236, Black); //Eje x }
ANEXOS 88 Anexo IV. El código que se presentará a continuación corresponde al fichero en el que se realizan las configuraciones de aquellas prestaciones que se van a realizar. Este código pertenece al fichero config.c. void RCC_Configuration(void) { /* ADCCLK = PCLK2/6 */ RCC_ADCCLKConfig(RCC_PCLK2_Div6); /*Poner Div6 implica que el ADCCLK vaya a 9.33 MHz. Se pone a esta frecuencia porque en el reference manual dice que tiene que ser como maximo 14 MHz*/ /* Enable peripheral clocks ----------------------------------*/ /* Enable DMA1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); /* Enable GPIOC, ADC1 and TIM1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1, ENABLE); /*Enable TIM1 clock */ RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2, ENABLE); /* Forces or releases Low Speed APB (APB1) peripheral reset */ //RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE); } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure PC.01 (ADC Channel11) as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOC, &GPIO_InitStructure); } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Configure and enable TIM2 interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
ANEXOS 89 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* TIM1 configuration ----------------------------------------*/ /* 72MHz/Prescaler(7200) = 10KHz -> 10KHz / Frecuencia deseada = Period */ /* Time Base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 12 - 1; /*Muestreo a 833 Hz*/ TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* TIM2 channel1 configuration in Compare mode */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); } void TIM_Enable(void){ /* TIM1 counter enable */ TIM_Cmd(TIM2, ENABLE); /* TIM1 main Output Enable */ TIM_CtrlPWMOutputs(TIM2, ENABLE); } void USART_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
ANEXOS 90 /*USART1_TX -> PA9 , USART1_RX -> PA10 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); USART_Cmd(USART1, ENABLE); } void ADC_Configuration(void){ ADC_InitTypeDef ADC_InitStructure; /* ADC1 configuration ----------------------------------------*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //MODIFICADO ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); /* ADC1 regular channel11 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_1Cycles5); /* Enable ADC1 external trigger */ ADC_ExternalTrigConvCmd(ADC1, DISABLE); //MODIFICADO /* Enable EOC interrupt */ ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
ANEXOS 91 /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); }
ANEXOS 92 Anexo V. El siguiente código que se presenta es el que corresponde al fichero dibujar.c y es el código que se ha desarrollado para la configuración del tiempo en el que queremos representar la señal. void calculo_Inicial (uint16_t tiempo){ uint16_t mps, pixeles; /* mps = muestras por segundo*/ pixeles = 300; if(tiempo == 1 || tiempo == 2 || tiempo == 3 || tiempo == 6){ if(tiempo == 6){ incremento_x = 1; }else if( tiempo == 3){ incremento_x = 2; }else if(tiempo == 2){ incremento_x = 3; }else if(tiempo == 1){ incremento_x = 6; } }else{ GUI_Text(45,140, "Tiempo invalido", White, Blue); } } void config_visual(){ uint16_t x, y, p; uint16_t oper = 0; uint8_t et1 = 0, et2 = 0, et3 = 0, et5 = 0, et6 = 0; LCD_Clear(Blue); GUI_Text(23,70,"Tiempo a mostrar:",White,Blue); LCD_CheckBox(20,90,0,Green); GUI_Text(45,90," 6 segundos ",Blue,White); LCD_CheckBox(20,110,0,Green); GUI_Text(45,110," 3 segundos ",Blue,White); LCD_CheckBox(20,130,0,Green); GUI_Text(45,130," 2 segundos ",Blue,White); LCD_CheckBox(20,150,0,Green); GUI_Text(45,150," 1 segundos ",Blue,White); while(oper == 0){ p = LCD_TouchRead(&display); /lee la posición del puntero sobre la pantalla */ x = display.x; /*extrae coordenada x*/ y = display.y; /*extrae coordenada y*/ if(p == 1) { /*detecta pulsación sobre la pantalla*/ if( (et1==0) && (x>20) && (x<36) && (y>150) && (y<176) ) {et1=1,oper=1;} if((et2==0) && (x>20) && (x<36) && (y>130) && (y<156)){et2=1,oper=1;} if((et3==0) && (x>20) && (x<36) && (y>110) && (y<126)){et3=1,oper=1;}
ANEXOS 99 /* allocate buffer */ writeBuffer = new byte[64]; readBuffer = new byte[4096]; actualNumBytes = new int[1]; init_UART(); init_Graph(); handlerThread = new handler_thread(handler); handlerThread.start(); } @Override protected void onResume() { // Ideally should implement onResume() and onPause() // to take appropriate action when the activity looses focus super.onResume(); if (2 == uartInterface.ResumeAccessory()) { baudRate = 9600; stopBit = 1; dataBit = 8; parity = 0; flowControl = 0; } Runnable mTimer = new Runnable() { @Override public void run() { if (running) { for(int i=0; i<30;i++){ graph2LastXValue += 1d; mSeries.appendData(new DataPoint(graph2LastXValue, generateData()), true, 900); } } mHandler.postDelayed(this, 100); } }; mHandler.postDelayed(mTimer, 100); //tiempo que tarda en empezar a dibujar } @Override protected void onPause() { super.onPause(); } @Override protected void onStop() { super.onStop(); } @Override
ANEXOS 100 protected void onDestroy() { uartInterface.DestroyAccessory(bConfiged); super.onDestroy(); } final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { for (int i = 0; i < actualNumBytes[0]; i++) { dataReceived[write] = Integer.valueOf((readBuffer[i] & 0xff)); write++; if (write == 4096) { write = 0; } } } }; /* usb input data handler */ private class handler_thread extends Thread { Handler mHandler; /* constructor */ handler_thread(Handler h) { mHandler = h; } public void run() { Message msg; while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { } status = uartInterface.ReadData(4096, readBuffer, actualNumBytes); if (status == 0x00 && actualNumBytes[0] > 0) { msg = mHandler.obtainMessage(); mHandler.sendMessage(msg); } } } } private double generateData() { double result = 0; int dataFirstFrame = dataReceived[read]; int dataSecondFrame = dataReceived[read + 1]; int firstFrameMask = 0x40; int secondFrameMask = 0x80; if ((dataFirstFrame & firstFrameMask) != firstFrameMask) {
ANEXOS 101 read++; } else if ((dataFirstFrame & firstFrameMask) == firstFrameMask) { dataFirstFrame = ((dataFirstFrame & 63) << 6); if ((dataSecondFrame & secondFrameMask) == secondFrameMask) { dataSecondFrame = (dataSecondFrame & 63); } read += 2; if (read == 4096) { read = 0; } result = (double) (dataFirstFrame | dataSecondFrame); } return result; } public void init_UART() { baudRate = 9600; /* baud rate */ stopBit = 1; /* 1:1stop bits, 2:2 stop bits */ dataBit = 8;/* 8:8bit, 7: 7bit */ parity = 0; /* 0: none, 1: odd, 2: even, 3: mark, 4: space */ flowControl = 0; /* 0:none, 1: flow control(CTS,RTS) */ uartInterface = new FT311UARTInterface(this); uartInterface.SetConfig(baudRate, stopBit, dataBit, parity, flowControl); } public void init_Graph() { GraphView graph = (GraphView) findViewById(R.id.graph); mSeries = new LineGraphSeries<DataPoint>(); graph.addSeries(mSeries); mSeries.setColor(Color.GREEN); graph.getViewport().setScrollable(true); graph.getViewport().setScalable(true); graph.getViewport().setYAxisBoundsManual(true); graph.getViewport().setXAxisBoundsManual(true); graph.getViewport().setMinY(0); graph.getViewport().setMaxY(4095); graph.getViewport().setMinX(0); graph.getViewport().setMaxX(900); graph.setBackgroundColor(0xFF0F3B05); graph.getGridLabelRenderer().setGridColor(0x4490EE90); graph.getGridLabelRenderer().setHorizontalLabelsColor(0xFF0F3B05); graph.getGridLabelRenderer().setVerticalLabelsColor(0xFF0F3B05); graph.getGridLabelRenderer().setNumHorizontalLabels(27);
ANEXOS 102 graph.getGridLabelRenderer().setNumVerticalLabels(15); graph.getGridLabelRenderer().setVerticalLabelsVisible(false); graph.getGridLabelRenderer().setHighlightZeroLines(false); } public void playAndStop(View view) { GraphView graph = (GraphView) findViewById(R.id.graph); ToggleButton button_playStop = (ToggleButton) findViewById(R.id.button_playStop); boolean on = button_playStop.isChecked(); if (!on) { running = false; graph.getViewport().setScalable(true); } else { running = true; } } }