scieee AI-readable full text Open interactive document viewer

Reconstrucción de trayectorias en la especialidad deportiva de lanzamiento de martillo a partir de datos de acelerómetros

Raspeño Priego, Carlos

Abstract

En el mundo del deporte los resultados que obtienen los atletas son determinantes. La existencia de sensores que recogen todo tipo de información resulta muy importantes a la hora de analizar este tipo de datos con el fin de mejorar el rendimiento de los deportistas. La adopción de sistemas como las placas Raspberry Pi facilitan el acceso a la tecnología. Esto, junto a la gran comunidad existente en torno a los proyectos que se realizan con estos sistemas, dan como resultado que la gran mayoría de la documentación y ayuda se encuentre de manera online, permitiendo que desarrolladores de todo distintos lugares intercambien sus conocimientos. En este proyecto se ha utilizado una placa Rasberry Pi Zero y una unidad de medición inercial para recoger los datos de un atleta de lanzamiento de martillo, enviarlos a través de la conectividad Bluetooth a otro dispositivo y poder realizar el análisis exhaustivo de dichos datos. De esta manera, sería posible analizar los datos del atleta y usarlos para mejorar su técnica y ejecución, así como otros aspectos que puedan mejorar su rendimiento y convertirlo en un mejor atleta.

Full text

Universidad Complutense de Madrid Facultad de Informática Reconstrucción de trayectorias en la especialidad deportiva de lanzamiento de martillo a partir de datos de acelerómetros Curso Académico 2018/2019 Trabajo fin de grado Grado en Ingeniería de Computadores Autor: Carlos Raspeño Priego Directores de proyecto: Luis Llana Díaz Alberto Núñez Covarrubias 0 Resumen En el mundo del deporte los resultados que obtienen los atletas son determinantes. La existencia de sensores que recogen todo tipo de información resulta muy importantes a la hora de analizar este tipo de datos con el fin de mejorar el rendimiento de los deportistas. La adopción de sistemas como las placas Raspberry Pi facilitan el acceso a la tecnología. Esto, junto a la gran comunidad existente en torno a los proyectos que se realizan con estos sistemas, dan como resultado que la gran mayoría de la documentación y ayuda se encuentre de manera online, permitiendo que desarrolladores de todo distintos lugares intercambien sus conocimientos. En este proyecto se ha utilizado una placa Rasberry Pi Zero y una unidad de medición inercial para recoger los datos de un atleta de lanzamiento de martillo, enviarlos - a través de la conectividad Bluetooth - a otro dispositivo y poder realizar el análisis exhaustivo de dichos datos. De esta manera, sería posible analizar los datos del atleta y usarlos para mejorar su técnica y ejecución, así como otros aspectos que puedan mejorar su rendimiento y convertirlo en un mejor atleta. Palabras clave Raspberry Pi Bluetooth Unidad de medición inercial Multiplataforma Python Cliente-Servidor i ii Abstract In sports, the results obtained by athletes are decisive. The existence of sensors that collect all kind of information is very important for analyzing this type of data in order to improve the performance of athletes. The adoption of systems such as Raspberry Pi boards makes easier the access to technology. This, together with the large community around the projects that are carried out with these systems, makes the majority of documentation and help is found online, allowing developers from all different places to share their knowledge. In this project, a Rasberry Pi Zero board and an inertial measurement unit have been used to collect data from a hammer throw athlete, send them - via Bluetooth connectivity - to another device and make an exhaustive analysis of these data. In this way, it would be possible to analyze the athlete’s data and use them to improve his technique and execution, as well as other things that can improve his performance and make him a better athlete. Keywords Raspberry Pi Bluetooth Inertial measurement unit Multi platform Python Client-Server iii iv Índice general Índice v 1. Introducción 1 1.1. Antecedentes ................................... 2 1.2. Objetivos ..................................... 2 1.3. Plan de trabajo .................................. 3 2. Introduction 5 2.1. Background .................................... 6 2.2. Objetives ..................................... 6 2.3. Workplan ..................................... 7 3. Dispositivos 9 3.1. Raspberry Pi ................................... 9 3.2. Sensor BNO055 .................................. 12 3.3. Sensor MPU-9250 ................................. 14 3.4. TP4056 charger .................................. 16 3.5. Fuente de alimentación Lipo Shim ........................ 17 4. Desarrollo 19 4.1. Python ....................................... 19 4.2. Sistema operativo utilizado ............................ 22 4.3. Conectividad ................................... 24 v 4.3.1. LMP .................................... 25 4.3.2. L2Cap ................................... 25 4.3.3. SDP .................................... 26 4.3.4. RFCOMM ................................. 26 4.4. Pybluez ...................................... 26 4.5. Kivy ........................................ 31 4.6. Sensores ...................................... 36 4.7. Guante ....................................... 40 5. Resultados 43 6. Presupuesto 47 6.1. Componentes ................................... 47 6.2. Desarrollo e investigación ............................. 48 7. Conclusiones 51 8. Conclusions 53 Bibliografía 56 vi Capítulo 1 Introducción Los avances tecnológicos en los últimos años han hecho posible la reducción del tamaño de los componentes. Como consecuencia de esto, la reducción del tamaño de los dispositivos ha dado como resultado la aparición de los wearable, dispositivos electrónicos que se incorporan en alguna parte de nuestro cuerpo interactuando de forma continua con el usuario, así como con otros dispositivos con la finalidad de realizar alguna función concreta, tales como relojes inteligentes, pulseras de actividad y gafas de realidad aumentada. Proyectos como el de la placa Raspberry Pi permiten, de una manera asequible, disponer de las capacidades de un ordenador en unas dimensiones reducidas. Su principal objetivo era estimular el aprendizaje de la informática en las escuelas, pero su bajo coste, junto con su versatilidad han hecho que sea uno de los de los componentes más usados en la comunidad “maker”. Éste término se fundamenta en la frase "hacértelo tú mismo", un concepto que ha sido capaz de generar una gran cantidad de proyectos simplemente con una conexión a internet para acceder a la información, tiempo, foros en los que se produce un intercambio de conocimiento, y recursos de muy bajo coste como las placas Raspberry Pi o Arduino. Actualmente existen multitud de libros acerca del mundo de la Raspberry. Sin embargo, debido a la naturaleza cambiante de este tipo de tecnología y a los nuevos dispositivos que se pueden utilizar en estas placas, la mayor parte de la documentación útil se encuentra de manera online gracias a la gran comunidad que existe en el desarrollo de proyectos con este tipo de hardware. Debido a ello, para realizar este proyecto se ha pretendido unir estos dos mundos, usando una RaspberryPi Zero y una unidad de medición inercial con el fin de crear, desde cero, un dispositivo capaz de registrar datos de un atleta y analizarlos con el fin de usarlos en el beneficio de éste. 1 8 Capítulo 3 Dispositivos El hardware empleado para realizar el proyecto consiste en una placa Raspberry Pi zero, conectada a una unidad de medición inercial o IMU. En un principio se hizo uso del sensor MPU-9250 como IMU, sin embargo, tras implementarlo y realizar las primeras pruebas, fue sustituido por el sensor BNO055, el cual es capaz de tomar mediciones que resultan mas útiles a la hora de analizar los datos y realizar los correspondientes cálculos matemáticos necesarios para su análisis. Para dotar de portabilidad al conjunto, se ha empleado una batería de polímero de litio o LiPo, acompañada de un circuito de carga TP4056. La batería con el circuito de carga acoplado, se conecta a la placa a través de una fuente de alimentación Lipo Shim, que permite fácilmente la conexión de la batería a través del conector de tipo JST, además de otras funciones explicadas en este apartado. En este capítulo se presentará con detalle el hardware usado para realizar el proyecto. 3.1. Raspberry Pi La Raspberry Pi19 es un ordenador de bajo coste y tamaño reducido que fue desarrollado en el Reino Unido por la Fundación Raspberry Pi, con el objetivo de estimular la enseñanza de informática en las escuelas y fue puesto a la venta por primera vez en en año 2012. Actualmente existen tres generaciones de placas Raspberry Pi: Pi 1, Pi 2 y Pi 3, y en general ha existido un Modelo A y un Modelo B de la mayoría de las generaciones. El Modelo A es una variante más barata y tiende a tener RAM y puertos reducidos como USB y Ethernet. 9 Actualmente se encuentra en la tercera versión del hardware llamada Raspberry Pi 3 y cuenta con diferentes versiones con distintas características: Raspberry pi 3B: Incorpora un procesaror Quad-Core de la compañía Broadcom que funciona a 1.20GHz y cuenta con 1 GB de RAM. Su mayor novedad con respecto a los anteriores modelos fue la inclusión de Wi-Fi y Bluetooth (4.1 Low Energy) sin necesidad de adaptadores. Raspberry pi 3B+: Se trata de una actualizacion del modelo anterior y entre sus mejoras cuenta con un nuevo procesador y mejor conectividad,su procesador pasa de tener 1.2Ghz a tener 1.4Ghz e incorpora doble banda a 2,4GHz y 5GHz de conectividad, y su nuevo puerto Ethernet se triplica, pasa de 100 Mbits/s en el modelo anterior a 300 Mbits/s en el nuevo modelo, también cuenta con Bluetooth 4.2 (Low Energy). Raspberry pi 3A+: Los modelos A+ presentan menores prestaciones a un menor precio por lo que estan destinados a proyectos mas pequeños. Cuenta con 256 MB RAM, un solo puerto USB y sin puerto de conexión de red por cable (RJ-45), sin embargo, sigue manteniendo el mismo procesador que el modelo B+. Figura 3.1: Diferentes versiones de Raspberry Pi a lo largo de los años. Fuente: https://opensource.com/resources/raspberry-pi Uno de los principales atractivos de este tipo de placas es la inclusión de los GPIO. El GPIO17 (General Purpose Input Output) es un sistema de entrada y salida de propósito general, y esta formado por una serie conexiones que se pueden usar como entradas o salidas. Estos pines están incluidos en todos los modelos de Raspberry Pi. 10 La primera versión de Raspberry Pi cuenta con 26 pines GPIO mientras que a partir de la segunda versión, el número de pines aumentó a 40 (figura 2.2). Sin embargo, ya que los 26 primeros pines mantienen su función original, la compatibilidad es total. Cuando se utilizan los pines de GPIO hay que poner especial atención para no dañar la propia placa. Los pines de GPIO pueden generar y consumir tensiones compatibles con los circuitos de 3.3V por lo que conectar componentes de 5V puede provocar daños irreversibles en la placa. La intensidad de corriente que sale de los pines del GPIO es de unos 3mA por cada pin, con la que se pueden encender diodos led, pero poco más. Figura 3.2: Pines GPIO para Raspberry Pi 2 Modelo B. Fuente: www.programoergosum.com/cursos-online/raspberry-pi/238-controlde-gpio-con-python-en-raspberry-pi/que-es-gpio Además del modelo principal, también se creó el modelo Zero (el cual se utilizará para la realización de este proyecto, figura 2.3). Este modelo se caracteriza por ser mucho más pequeño y menos potente que la versión principal. Sin embargo, presenta un gasto energético mucho menor y resulta más asequible por lo que esta destinado a proyectos en los que el tamaño y consumos sean importantes pero no se requiera de mucha potencia. La Raspberry Pi Zero tiene un microprocesador Broadcom BCM2835, que funciona a 1GHz con un solo núcleo, posee 512MB de RAM, y comparte la gráfica VideoCore IV. Debido a su tamaño cuenta con un puerto MiniHDMI, dos MicroUSB (uno de alimentación y otro de datos). Posee salida RCA, pero en vez de por clavija son solo dos conectores integrados en la placa y usa MicroSD como sistema de almacenamiento. Existe una actualizacion de este modelo llamada Raspberry Pi Zero W, cuya única novedad con respecto a su antecesora es la inclusión de Wi-Fi y Bluetooth 11 Figura 3.3: Raspberry Pi Zero W. Fuente: https://www.raspberrypi.org/products/raspberry-pi-zero-w/ 3.2. Sensor BNO055 El BNO055 es un sensor que incorpora un acelerómetro, magnetómetro y giroscopio en una placa junto con un procesador basado en ARM Cortex-M0 de alta velocidad para procesar todos los datos recogidos sensor. El BNO055 puede sacar los siguientes datos a partir de los sensores: Orientación Absoluta (Vector de Euler, 100Hz): Tres ejes de orientación basados en una esfera de 360o. Vector de Velocidad Angular (100Hz): Tres ejes de velocidad de rotación en rad/seg. Vector de Aceleración (100Hz): Tres ejes de aceleración (gravedad + movimiento lineal) en m/s2. Vector de Campo Magnético (20Hz): Tres ejes de sensor de campo magnético en micro Tesla (uT). Vector Lineal de Aceleración (100Hz): Tres ejes de aceleración lineal (aceleración menos gravedad) en m/s2. Vector de Gravedad (100Hz): Tres ejes de aceleración gravitacional (menos cualquier movimiento) en m/s2. Temperatura (1Hz): Temperatura ambiente en grados celsius. En cuanto a los pines de conexión, el BNO055 consta de los siguientes. 12 Figura 3.4: Vista del sensor BNO055 y sus pines. Fuente: https://learn.adafruit.com/adafruit-bno055-absolute-orientationsensor/overview Pines de alimentación: VIN: Entada de alimentación 3.3-5.0V. 3VO: Salida desde el regulador de voltaje lineal incorporado, puede tomar hasta 50 mA según sea necesario. GND: El pin GND para alimentación y lógica. Pines para la conexión I2C: SCL: Pin de reloj I2C, se conecta a la línea de reloj I2C del microcontrolador. Este pin se puede usar con lógica de 3V o 5V, y tiene un pullup de 10K. SDA: Pin de datos I2C, se conecta a la linea de datos I2C del microcontrolador. Este pin se puede utilizar con lógica de 3V o 5V, y tiene un pullup de 10K. Otros pines: RST: Pin de reinicio de hardware. Poner la tensión de este pin en bajo y luego en alto provoca un reinicio en el sensor. INT: El pin de salida de interrupción de HW, que se puede configurar para generar una señal de interrupción cuando se producen ciertos eventos como el movimiento del acelerómetro, etc. (Actualmente no se admite en la biblioteca Adafruit, pero el chip y el HW pueden generar esta señal). El nivel de voltaje es 3V 13 ADR: Poner la tensión de este pin en alto para cambiar la dirección I2C predeterminada para el BNO055 si necesita conectar dos circuitos integrados en el mismo bus I2C. La dirección por defecto es 0x28. Si este pin está conectado a 3V, la dirección será 0x29 PSO yPS1: Estos pines pueden usarse para cambiar el modo del dispositivo (también puede hacer HID-I2C y UART) y también se proporcionan en caso de que Bosch proporcione una actualización de firmware en algún momento para el MCU ARM Cortex en el interior del sensor. Normalmente se deben dejar desconectados. 3.3. Sensor MPU-9250 El sensor MPU-92503es una unidad de medición inercial o IMU (del inglés inertial measurement unit) fabricado por Invensense que incorpora un acelerómetro, un magnetómetro y un giroscopio. Este sensor permite la comunicación tanto por SPI (serial peripheral interface) como por I2C (Inter-Integrated Circuit) y sus componentes principales cuentan con las siguientes características: Giroscopio: Giroscopio con ejes X, Y y Z de salida digital con un rango programable por el usuario de +- 250, +- 500, +- 1000, y +- 2000 grados/ seg y conversores analógicos digitales (ADC) de 16bits. Low-pass filter programable digitalmente. Corriente de operación de 3.2mA. Modo sleep de 8µA. Factor de escala de sensibilidad calibrada de fábrica. Test de Autoevaluación. 14 Acelerómetro: Triple eje de salida digital con un rango de escala programable de +- 2g, +- 4g, +- 8gand +- 16gand y conversores analógicos digitales (ADC) de 16bits. Corriente de operación de 450µA. Corriente del modo baja potencia: 8,4µA a 0.98Hz, 19,8µA a 31.25Hz. Modo sleep de 8µA. Interrupciones programables por el usuario. Interrupción Wake-on-motion (reactivación por movimiento) para el funcionamiento de baja potencia del procesador de aplicaciones. Test de Autoevaluación. Magnetómetro: Sensor magnético de silicio de efecto Hall con 3 ejes y concentrador magnético. Amplio rango de medición dinámico y alta resolución con menor consumo de corriente. Resolución de datos de salida de 14 bits (0,6µT / LSB). Rango de medición de +- 4800µT. Corriente de operación del magnetómetro de 280µA a una tasa de repetición de 8Hz. Función de Autoevaluación con fuente magnética interna para confirmar el funcionamiento del sensor magnético. 15 El motor interno Digital Motion Processing (DMP) admite funciones avanzadas de procesamiento de movimiento y baja potencia, como el reconocimiento de gestos mediante interrupciones programables y la funcionalidad de podómetro de baja potencia permite que el procesador host entre en modo sleep mientras el DMP mantiene el conteo de pasos. Figura 3.5: Sensor MPU-9250 y pines usados en el proyecto. Fuente: https://www.luisllamas.es/usar-arduino-con-los-imu-de-9dof-mpu9150-y-mpu-9250/ 3.4. TP4056 charger El TP40564es un cargador lineal completo de corriente constante / voltaje constante para baterías de iones de litio de una celda. Su paquete SOP y su bajo número de componentes externos hacen que el TP4056 sea ideal para aplicaciones portátiles. Figura 3.6: Vista del TP4056. Fuente: https://www.daraz.pk/products/tp4056-37v-li-ion-charger-module1a-with-battery-protection-i111146658-s1262278023.html 16 3.5. Fuente de alimentación Lipo Shim Su principal objetivo es ser la fuente de alimentación para Raspberry Pi. Este componente13 no permite la carga por lo que se hace necesario un cargador como el TP4056 anteriormente descrito si se utiliza una batería. El convertidor de refuerzo TPS61232 de Texas Instruments ofrece hasta un 96 por ciento de eficiencia. La placa incluye indicadores LED de encendido y batería baja. Durante el apagado (debido a la baja tensión o la selección externa), la corriente de reposo es solo de 15 uA. Especificaciones: PCB de 0.8 mm de grosor Perfil lo más bajo posible Conector JST de 2 polos, ideal para la mayoría de baterías LiPo/LiIon LEDs indicadores de alimentación y bajo nivel de batería Proporciona corriente continua de 1.5A Alerta de nivel bajo de batería a 3.4V Apagado automático a 3.0V para proteger la batería Pines VBAT+, GND y EN accesibles Consumo de corriente en reposo de 15uA (a) Lipo Shim (b) Lipo Shim montado en el GPIO de la RPI Figura 3.7: Lipo Shim. Fuente: https://thepihut.com/products/lipo-shim 17 4.3. Conectividad Para conectar el cliente y el servidor se ha usado la conectividad bluetooth. Bluetooth2es una especificación industrial para Redes Inalámbricas de Área Personal (WPAN) de corto alcance creado por Bluetooth Special Interest Group, Inc. que posibilita la transmisión de voz y datos entre diferentes dispositivos mediante un enlace por radiofrecuencia en la banda ISM de los 2.4 GHz con un rango óptimo de 10 m. Debido a que uno de los tipos de wifi20 opera en el mismo rango que el bluetooth (2.4 GHz) es posible que si se esta haciendo uso de esta conexión en la Raspberry Pi o en el dispositivo cliente se produzcan interferencias que dificulten la conexión o el intercambio de datos. El estándar de intercambio de datos inalámbrico Bluetooth utiliza una variedad de protocolos14. Los protocolos centrales están definidos por la organización comercial Bluetooth SIG. Se han adoptado protocolos adicionales de otros organismos de normalización. Bluetooth está definido como un protocolo de arquitectura de capa que está formado por unos protocolos centrales, protocolos de reemplazo de cable, protocolos de control de telefonía, y protocolos adoptados. La pila de protocolo Bluetooth se divide en dos partes: el “controller stack” o “pila de controlador” que contiene la interfaz de radio bluetooth cuyo funcionamiento es critico con respecto al tiempo, y el “host stack” o “pila de host” que trata con datos de alto nivel. La pila del controlador generalmente se implementa en una placa, la cual tamben contiene la radio Bluetooth y un microprocesador. La pila de host se implementa generalmente como parte del sistema operativo, o como un paquete instalable. Como mínimo, toda pila de protocolos de Bluetooth debe tener los siguientes protocolos: LMP(controller stack), L2CAP(host stack) y SDP(host stack). Además, los dispositivos que se comunican por Bluetooth pueden usar casi siempre los protocolos HCI(controller stack) y RFCOMM(host stack). En este proyecto para comunicar el cliente con el servidor se ha utilizado el protocolo RFCOMM asi como el protocolo SDP para establecer la conexión con el servicio deseado. Toda la información referente a este apartado, se puede encontrar de manera más extensa en las referencias 2, 20 y 14 de la bibliografía. 24 4.3.1. LMP El protocolo de control de enlace (Link Management Protocol, LMP) se usa para el establecimiento y control del enlace de radio entre dos dispositivos. Está implementado en el controlador. 4.3.2. L2Cap L2CAP es un protocolo que define una serie de puertos que se pueden utilizar para mandar y recibir datos mediante las capas inferiores de bluetooth, es decir, define una forma en la que varias aplicaciones pueden enviar datos y recibir datos utilizando las ondas de radio de bluetooth. Las funciones de L2CAP incluyen: Multiplexación de datos entre diferentes protocolos de capa superior. Segmentación y reensamblaje de paquetes. Proporcionar administración de transmisión unidireccional de datos de multidifusión a un grupo de otros dispositivos Bluetooth. Gestión de calidad de servicio (QoS) para protocolos de capa superior. En su modo básico, L2CAP proporciona a los paquetes una carga útil que se puede configurar hasta 64 kB, y con una MTU por defecto de 672 bytes. En los modos de Retransmisión y control de flujo, L2CAP puede configurarse para datos asíncronos o para un canal de datos fiables mediante la retransmisión y la comprobación de CRC. La fiabilidad en cualquiera de estos modos es opcional y / o adicionalmente garantizada por la capa inferior Bluetooth BDR / EDR. El apéndice 1 de la especificación de Bluetooth añade dos modos adicionales a L2CAP. Estos nuevos modos dejan obsoletos los anteriores modos de retransmisión y control de flujo: Modo de retransmisión mejorado (Enhanced Retransmission Mode, ERTM):Este modo es una versión mejorada del modo original de retransmisión. Proporciona un canal L2CAP confiable. Modo streaming (Streaming Mode, SM): Es un modo muy simple, sin retransmisión ni control de flujo. Proporciona un canal L2CAP no confiable. 25 4.3.3. SDP Service discovery protocol (SDP) se utiliza para permitir que los dispositivos descubran qué servicios son compatibles entre sí y qué parámetros usar para conectarse a ellos. Cada servicio se identifica mediante un identificador único universal (UUID), con servicios oficiales (perfiles Bluetooth) asignados a un UUID de forma corta (16 bits en lugar de los 128 completos). En la pila de protocolos, SDP está vinculado a L2CAP. 4.3.4. RFCOMM El protocolo Bluetooth RFCOMM es un conjunto simple de protocolos de transporte, hecho sobre el protocolo L2CAP, que proporciona puertos serie RS-232 emulados (hasta sesenta conexiones simultáneas a un dispositivo Bluetooth a la vez). El protocolo se basa en la norma ETSI TS 07.10. A veces se le conoce como emulación de puerto serie. El perfil del puerto serie de Bluetooth se basa en este protocolo. RFCOMM proporciona un flujo de datos simple y confiable para el usuario, similar a TCP. Muchas aplicaciones Bluetooth utilizan RFCOMM debido a su amplio soporte y API disponible públicamente en la mayoría de los sistemas operativos. Además, las aplicaciones que usan un puerto en serie para comunicarse se pueden portar rápidamente para usar RFCOMM. En la pila de protocolos, RFCOMM está vinculado a L2CAP. 4.4. Pybluez PyBluez8es un modulo de Python que permite que el código acceda a los recursos Bluetooth de la máquina host. El uso de este modulo facilita la programación para comunicarse a través de Bluetooth usando Python. Los sockets de Python pueden ser usados para la comunicación por Bluetooth (a partir de Python 3.3). Para una aplicación simple, el código es casi idéntico frente a usar PyBluez, sin embargo, para algunas tareas, como el descubrimiento de dispositivos y los anuncios de servicios Bluetooth, no parece posible realizarlos utilizando sockets de Python. 26 Se ha hecho uso principalmente de las siguientes funciones, tal y como se explica en la API de Pybluez. En la parte del servidor, la función: 1advertise_service(sock, name, service_id=’’, service_classes=[], profiles=[], provider=’’, description=’’) Anuncia un servicio con el servidor SDP local. “Sock” debe ser un socket de escucha enlazado, “nombre” debe ser el nombre del servicio y “service_id” (si se especifica) debe ser una cadena de la siguiente forma “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXX”, donde cada ’X’ es un dígito hexadecimal. “service_classes” es una lista de clases de servicio a las que pertenece este servicio. Cada servicio de clase es un UUID de 16 bits en la forma “XXXX”, donde cada ’X’ es un dígito hexadecimal, o un UUID de 128 bits en la forma “XXXXXXXX-XXXX-XXXXXXXX-XXXXXXXXXXXX”. Hay algunas constantes para los servicios estándar, como por ejemplo, SERIAL_PORT_CLASS que es igual a “1101”. Algunas constantes de clase son: SERIAL_PORT_CLASS LAN_ACCESS_CLASS DIALUP_NET_CLASS HEADSET_CLASS CORDLESS_TELEPHONY_CLASS AUDIO_SOURCE_CLASS AUDIO_SINK_CLASS PANU_CLASS NAP_CLASS GN_CLASS “profiles” es una lista de perfiles de servicio que cumple este servicio. Cada perfil es una tupla con (uuid, versión). La mayoría de los perfiles estándar utilizan clases estándar como UUID. PyBluez ofrece una lista de perfiles estándar, por ejemplo SERIAL_PORT_PROFILE. Todos los perfiles estándar tienen el mismo nombre que las clases, excepto que el sufijo _CLASS se reemplaza por _PROFILE. “provider” es una cadena de texto que especifica el proveedor del servicio. “description” es una cadena de texto que describe el servicio. De esta manera, para crear un servicio y anunciarlo mediante SDP para que un cliente pueda conectarse buscando este servicio en concreto y aceptar la conexion del socket de dicho cliente se ha creado con un código como el siguiente: 1server_sock=BluetoothSocket( RFCOMM ) 2server_sock.bind(("",PORT_ANY)) 3server_sock.listen(1) 4 5port = server_sock.getsockname()[1] 6 27 7uuid = #uuid que deseemos para este servicio concreto 8 9advertise_service( server_sock, """nombre del servicio""", 10 service_id = uuid, 11 service_classes = [ uuid, SERIAL_PORT_CLASS ], 12 profiles = [ SERIAL_PORT_PROFILE ] 13 ) 14 15 16 client_sock, client_info = server_sock.accept() Tras la conexión, se ha creado un bucle que recibe las distintas ordenes del cliente y las procesa. Para cerrar la conexion con el socket cliente se usará: 1client_sock.close() Y para cerrar el socket del servidor y terminar la ejecución se usará: 1server_sock.close() En cuanto al cliente, la función: 1find_service(name=None, uuid=None, address=None) Busca servicios SDP que coincidan con los criterios especificados y devuelve los resultados de la búsqueda. Si no se especifican criterios, devuelve una lista de todos los servicios cercanos detectados. Si se especifica más de uno, entonces los resultados de búsqueda coincidirán con los criterios especificados. Si se especifica uuid, debe ser un UUID de 16 bits en la forma “XXX”, donde cada ’X’ es un dígito hexadecimal, o como un UUID de 128 bits en la forma “XXXXXXXXXXXX-XXXX-XXXXXXXXXXXXXXXX”. Un caso especial de dirección es “localhost”, que buscará servicios en la máquina local. Los resultados de la búsqueda serán una lista de diccionarios. Cada diccionario representa una coincidencia de búsqueda y tendrá los siguientes pares clave / valor: Host: La dirección Bluetooth del dispositivo que anuncia el servicio. Nombre: El nombre del servicio que se anuncia. Descripción: Una descripción del servicio que se anuncia. 28 Proveedor: El nombre de la persona u organización que presta el servicio. Protocolo: Ya sea ’RFCOMM’, ’L2CAP’. Ninguno si el protocolo no estaba especificado, o ’DESCONOCIDO’ si el protocolo fue especificado pero poco reconocido. Puerto: El L2CAP PSM # si el protocolo es ’L2CAP’, el RFCOMM canal # si el protocolo es ’RFCOMM’, o Ninguno si no fue especificado. Clases de servicio: Una lista de ID de clase de servicio (cadenas UUID), posiblemente vacío. Perfiles: Una lista de perfiles - (UUID, versión) , posiblemente vacío. Service-id: El ID de servicio. Ninguno si no fue establecido. Ver la especificación de Bluetooth para la diferencia entre Service ID yService Class ID List. De esta manera, para crear un cliente que busque un servicio determinado con un uuid concreto se ha creado con un codigo como el siguiente: 1addr = None 2 3if len(sys.argv) < 2: 4print("Buscando el servicio en los dispositivos cercanos") 5else: 6addr = sys.argv[1] 7print("Buscando el servicio en %s" % addr) 8 9# Busqueda del servicio 10 uuid = #uuid del servicio que se quiere buscar 11 service_matches = find_service(uuid=uuid, address=addr) 12 13 if len(service_matches) == 0: 14 print("No se pudo encontrar el servicio =(") 15 sys.exit(0) 16 17 first_match = service_matches[0] 18 port = first_match["port"] 19 name = first_match["name"] 20 host = first_match["host"] 21 22 print("Conectando a \" %s\" en %s" % (name, host)) 23 24 # Creacion del socket cliente 25 sock = BluetoothSocket(RFCOMM) 26 sock.connect((host, port)) 29 Con dicho código, si se especifica una dirección mac Bluetooth en la que esta el servidor, se buscara el uuid en dicha dirección, si no, la dirección (addr en el código) permanecerá a “None” y se buscará en todos los dispositivos cercanos, devolviendo las coincidencias. Hay que tener en cuenta que si se encuentran varios servidores con el mismo uuid, solo se tomara como válido el primero que se encuentre. Tras la conexión, se ha creado un bucle (al igual que en el servidor) con el menu y las distintas opciones que tiene el programa y cuyas órenes se mandarán al servidor para procesarlas. En el caso de la versión con GUI, ese bucle no esta presente ya que se ha usado un framework para la creación de dicho menu con interfaz grafica. En este caso para terminar solo sera necesario cerrar el socket propio del cliente: 1sock.close() La API completa de Pybluez se encuentra en el directorio “docs” del repositorio oficial, así como los requisitos o dependencias de cada plataforma para su instalación https://github.com/pybluez/pybluez. Para la instalación se utilizará pip (tambien se encuentran los binarios para Windows en PyPI) con la siguiente instrucción: pip install pybluez En caso de que pip no funcione sera necesario descargar el repositorio de Github (o realizar un git clone sobre dicho repositorio) y ejecutar la siguiente orden dentro de la ruta de dicha descarga: python setup.py install En los testeos realizados, sobre GNU/Linux ha sido necesaria la descarga del repositorio y el método anteriormente descrito para su instalación. En el caso de Windows, a pesar de cumplir con las dependencias descritas en las instrucciones de instalación en su Github, ninguno de los métodos parecía funcionar para instalar Pybluez, sin embargo se encontró una manera modificando el archivo setup.py ya que no éste reconocía de manera correcta la ruta del Windows SDK. Para ello se cambio la siguiente linea de codigo: 1candidate_paths.append(r’Microsoft SDKs\Windows\v10.0A’) # Visual Studio 14 30 Por la siguiente: 1candidate_paths.append(r’C:/Program Files (x86)/Windows Kits/10’) # Visual Studio 14 Tras lo cual, al ejecutar python setup.py install Pybluez se instaló de manera correcta. 4.5. Kivy Para la creacion de la GUI, se ha usado el framework Kivy. Tal y como se especifica en su pagina web12 y Github7, Kivy es un framework Python de código abierto y multiplataforma para el desarrollo de aplicaciones que hacen uso de interfaces de usuario innovadoras y multitáctiles. El objetivo es permitir un diseño de interacción rápido y fácil y una creación rápida de prototipos al tiempo que hace que el código sea reutilizable e implementable. Kivy está escrito en Python y Cython, basado en OpenGL ES 2, es compatible con varios dispositivos de entrada y tiene una extensa biblioteca de widgets. Con el mismo código base, puede funcionar en Windows, macOS, Linux, Android e iOS. Todos los widgets de Kivy están construidos con soporte multitáctil. Kivy tiene licencia MIT, está desarrollada activamente por una gran comunidad y cuenta con el respaldo de muchos proyectos administrados por la Organización Kivy. Figura 4.2: Logo de Kivy. Fuente: https://kivy-designer.readthedocs.io/en/latest/ Una de las peculiaridades de este framework es que permite separar la parte del diseño visual de la interfaz, de la interacción y la lógica de la aplicación mediante el lenguaje KV. De esta manera se puede programar los widgets y su comportamiento en python, y especificar, por ejemplo, la disposición de los botones, transiciones y otras componentes visuales de la interfaz de usuario en Kv. 31 En el proyecto el código de la GUI esta dividido en 3 archivos: rfcomm_client.py: Contiene las funciones necesarias para la conexión, desconexión, y recepción del archivo con la información de los sensores mediante bluetooth. main.py: Contiene las clases (o widgets), que componen cada una de las vistas del programa y su lógica, ventanas con errores etc. app.kv: Contiene la parte gráfica de las clases de main.py, es decir, en este archivo se encuentra el diseño visual de cada ventana. Por ejemplo, una de las clases implementadas es la clase menú que muestra el menu principal. En el archivo main.py esta definida de la siguiente manera: 1class Menu(Screen): 2 3def csv(self): 4sock.send("Genera") 5 6def recibir(self): 7sock.send("Envia") 8ret = sock.recv(1024) 9recibido = ret.decode(’utf-8’) 10 if recibido == "Error": 11 noFile() 12 else: 13 sock.send("Sync") 14 recibir(sock) 15 fileRec() En ella están definidas únicamente las funciones csv yrecibir. La función csv únicamente se encarga de enviar una orden a el servidor para que empiece a recopilar información del sensor, y la función recibir envía dicha opción a el servidor, y si no ocurre ningún error, llama a la función recibir de rfcomm_client.py para proceder a la recepción del archivo de datos. En caso de haber algún error, se lanzara una ventana de tipo popup que mostrará dicho error. En el archivo app.kv la definición gráfica de dicha función es la siguiente: 1<Menu>: 2GridLayout: 3cols:1 4Label: 5text: "Menu Principal" 32 6font_size: (root.width**2 + root.height**2) / 14**4 7 8BoxLayout: 9orientation: ’vertical’ 10 Button: 11 12 text: "Recibir datos en tiempo real" 13 on_release: 14 app.root.current = "TR" 15 root.manager.transition.direction = "left" 16 17 Button: 18 19 text: "Generar archivo de datos en el dispositivo" 20 on_release: 21 app.root.current = "csv" 22 root.manager.transition.direction = "left" 23 root.csv() 24 25 Button: 26 27 text: "Recibir archivo de datos" 28 on_release: 29 root.recibir() 30 31 Button: 32 33 text: "Calibrar sensores" 34 on_release: 35 app.root.current = "cal" 36 root.manager.transition.direction = "left" 37 38 Button: 39 40 text: "Salir" 41 on_release: 42 app.stop() En dicho código se definen el texto que indica en que ventana se encuentra (“Menu principal en este caso”), los distintos botones que generan acciones o transiciones a las distintas ventanas así como la disposición de estos en el panel. También es posible definir ventanas popup (como la anteriormente mencionada) que se mostraran al encontrarse un error, o para mostrar información relevante como por ejemplo en el siguiente caso: 33 15 # (metros por segundo al cuadrado): 16 print(bno.read_gravity()) De este modo se puede hacer un print para mostrar los datos por terminal como en el ejemplo anterior, o guardarlos en un archivo externo (en el caso de este proyecto se ha guardado en un archivo CSV) y encerrar dicho código en un bucle para obtener lecturas periódicamente y guardarlas en consonancia. 4.7. Guante Para la realización del diseño del soporte que usará el atleta se tuvieron varios factores en cuenta, como la ergonomía, espacio para los componentes, ubicación óptima de los mismos, seguridad, sujeción sin influenciar el desempeño del atleta, etc. Como resultado se optó por un guante estilo muñequera completa que cubre la mano hasta los dedos. De esta manera se podría satisfacer de la mejor forma los requisitos anteriormente enunciados. Figura 4.5: Guante La placa, junto con la batería, se ubican en la parte exterior del antebrazo, en un bolsillo especialmente diseñado que permite el movimiento de la muñeca y también su extracción e inserción sin demasiado problema. La placa se mantiene segura y sujeta durante los lanzamientos, y permite la salida de los cables que van al sensor cuando el bolsillo esta cerrado. 40 Figura 4.6: Conexiones de la placa La ubicación del sensor se decidió que fuera lo mas cercana a la mano posible, por lo que se colocó en la parte superior, prácticamente en el nudillo. Para ello se diseñó un espacio que, al igual que en la placa, permitiera su extracción e inserción sin demasiado problema, manteniendo el sensor fijo durante los lanzamientos y permitiendo la salida de los cables que van a la placa. Figura 4.7: Conexiones del sensor 41 42 Capítulo 5 Resultados El resultado de las pruebas realizadas se guarda en un archivo .csv, éste archivo contiene las lecturas tomadas por el sensor en el lanzamiento monitorizado. Figura 5.1: Parte de la tabla de las lecturas del sensor Tal y como se puede observar en la figura 4.1 (aunque debido al tamaño, no se ha mostrado completa en dicha figura), la tabla esta formada por las siguientes columnas: Timestamp: Contiene el instante de tiempo en el que se realiza la lectura. Euler heading, roll, pitch: Estas 3 columnas contienen los ángulos de Euler, que sirven para especificar la orientación de un sistema de referencia normalmente móvil, respecto a otro sistema de referencia normalmente fijo. Quaternion x, y, z, w: Estas 4 columnas están formadas por las 4 componentes del cuaternión, el cual sirve para representar las orientaciones y las rotaciones de objetos en tres dimensiones. Magnetómetro x, y, z: Contiene las componentes x, y, z del magnetómetro en cada columna respectivamente. 43 Giroscopio x, y, z: Información de los 3 ejes del giroscopio, divididos en 3 columnas. Acelerómetro x, y, z: Datos de cada eje del acelerómetro en cada una de las 3 columnas. Aceleración lineal x, y, z: Aceleración lineal en cada uno de los ejes (3 columnas, una para cada eje). Aceleración de la gravedad x, y, z: Información de los 3 ejes de aceleración gravitacional, cada eje en 1 columna. Una vez obtenidos estos datos, es necesario realizar una serie de cálculos matemáticos, obteniendo así los puntos en el espacio 3D y la velocidad para poder representarlos. Por desgracia, el alumno de la Facultad de Matemáticas cuyo proyecto consistía en realizar esos cálculos, no lo ha terminado a tiempo, por lo que dicha parte queda pendiente. Sin embargo, si que se ha creado la función para representar los datos. Para ello se ha usado la librería de Python llamada Matplotlib. Mediante dicha librería es posible representar de manera gráfica los datos y guardarlos si así se desea. La instalacion de la libreria se realiza mediante pip: python -m pip install -U pip python -m pip install -U matplotlib Para la representación, una vez hechos los import necesarios para el uso de la biblioteca, y desactivado el modo interactivo de la misma de la siguiente manera: 1from mpl_toolkits import mplot3d 2import numpy as np 3import matplotlib.pyplot as plt 4 5plt.ioff() Se han creado dos figuras independientes usando plt.figure() en cada una. Para la figura tridimensional es necesario especificarlo mediante ax = plt.axes(projection=’3d’), para luego representar los puntos x, y, z con la función ax.plot3D(x, y, z). Para la gráfica de la velocidad, no es necesario especificar que es bidimensional, y usando la función plt.plot(x, y) quedaria representada. Por último, una vez representados los datos correctamente, plt.show() crea las 2 ventanas con las gráficas correspondientes a los datos. 44 En las figuras 4.2 y 4.3, se puede observar el resultado obtenido en las pruebas, utilizando para ellas, datos simulados. Figura 5.2: Representación de la trayectoria de un lanzamiento con datos simulados Figura 5.3: Representación de la velocidad de un lanzamiento con datos simulados 45 El software desarrollado para la realización de este TFG9se puede encontrar en el siguiente enlace: https://github.com/CRP8/TFG 46 Capítulo 6 Presupuesto En este apartado se desglosarán los costes de desarrollo, así como los costes de los materiales, investigación, montaje, diseño, etc. 6.1. Componentes En este apartado se presenta el gasto de los componentes, cantidad y materiales que componen el hardware del proyecto. No se han tenido en cuenta las herramientas utilizadas para su desarrollo, como por ejemplo, un teclado para la Raspberry Pi, adaptador HDMI y cable, etc. La lista de precios (ver tabla 6.1) se ha elaborado con distintos proveedores para cada pieza, tomando en cuenta los precios, las fechas de envío, etc. Se ha incluido en los precios el importe por el envío, en el caso de que dicho producto no tuviera envío gratuito. En el caso de la Raspberry Pi, se ha tenido en cuenta el precio del proveedor que figura en la pagina oficial, junto con los gastos de envío que indica dicho proveedor. En el presupuesto, también se ha tenido en cuenta el sensor MPU-9250, que aunque más tarde fue sustituido por el BNO055, fué el que se utilizó en un primer momento, y tuvo importancia en el desarrollo. 47 Componentes Producto Precio Unidades Total Raspberry Pi Zero W 18.52 e1 18.52 e Tarjeta MicroSD Sandisk 9.68 e1 9.68 e Sensor BNO055 27.99 e1 27.99 e Sensor MPU-9250 4.90 e1 4.90 e TP4056 charger 1.16 e1 pack 5 unidades 1.16 e Fuente de alimentación Lipo-shim 12.30 e1 12.30 e Muñequera 5 e2 10 e Cables Dupont, hembra a hembra 3.99 e1 3.99 e Baterías 12.33 e1 pack 4 unidades 12.33 e Total (iva incluido) 100.87 e Tabla 6.1: Tabla de precios de los materiales 6.2. Desarrollo e investigación Para realizar el cálculo del precio por hora de trabajo, se ha supuesto que el trabajador contratado trabaja para la empresa CRP-SL. En la tabla 6.2 se especifica tanto el sueldo bruto, como el resto de cotizaciones que paga la empresa, con el fin de obtener el coste real para realizar dicho cálculo. 48 Calculo del trabajador a la empresa Salario bruto 35000 e35000 e Contingencias comunes + 23.60% 8260 e Desempleo + 5.50 % 1925 e Formación profesional + 0.60% 210 e Fondo de garantía salarial + 0.20% 70 e Accidentes + 1% 350 e Total 45815 e Tabla 6.2: Coste del sueldo del trabajador a la empresa Una vez obtenida dicha cifra y teniendo en cuenta que el convenio especifica que el número de horas de trabajo anuales es de 1750, se obtiene un precio de 26.18 euros por hora de trabajo. Teniendo en cuenta esta cifra, en la tabla 6.3 se ha realizado el calculo del precio en función de las horas empleadas para su desarrollo. Tarea Estimación de horas Precio/hora Desarrollo del software 190 26.18 e Desarrollo del hardware 30 26.18 e Investigación 250 26.18 e Pruebas 90 26.18 e Documentación 40 26.18 e Total 600 15.708 e Tabla 6.3: Tareas realizadas y coste de ellas 49 [11] I2c clock stretching - raspberry pi forums. URL: https://www.raspberrypi. org/forums/viewtopic.php?p=146272. Accessed: 2019-04-30. (Archived by WebCite R at http://www.webcitation.org/7821mz7B5). [12] Kivy: Cross-platform python framework for nui development. URL: https:// kivy.org//#home. Accessed: 2019-04-30. (Archived by WebCite R at http:// www.webcitation.org/781h6hQSe). [13] Lipo-shim | the pi hut. URL: https://thepihut.com/products/lipo-shim. Accessed: 2019-04-29. (Archived by WebCite R at http://www.webcitation. org/780IYSJVf). [14] List of bluetooth protocols - wikipedia. URL: https://en.wikipedia. org/wiki/List_of_Bluetooth_protocols. Accessed: 2019-04-30. (Archived by WebCite R at http://www.webcitation.org/781fdH54i). [15] Python. URL: https://www.python.org/. Accessed: 2019-04-29. (Archived by WebCite R at http://www.webcitation.org/780J2qkdd). [16] Python faq. URL: https://docs.python.org/3/faq/general.html. Accessed: 2019-04-29. (Archived by WebCite R at http://www.webcitation.org/ 780JCQL1c). [17] Que es un gpio. URL: https://www.programoergosum.com/cursosonline/raspberry-pi/238-control-de-gpio-con-python-enraspberry-pi/que-es-gpio. Accessed: 2019-04-29. (Archived by WebCite R at http://www.webcitation.org/780HsD9jI). [18] Software | bno055 absolute orientation sensor with raspberry pi, beaglebone black | adafruit learning system. URL: https://learn.adafruit.com/ bno055-absolute-orientation-sensor-with-raspberry-pi-andbeaglebone-black/software. Accessed: 2019-04-30. (Archived by WebCite R at http://www.webcitation.org/781iibSFW). [19] What is a raspberry pi? URL: https://opensource.com/resources/ raspberry-pi. Accessed: 2019-04-29. (Archived by WebCite R at http://www. webcitation.org/780H73ZrK). [20] Wifi - wikipedia, la enciclopedia libre. URL: https://es.wikipedia.org/wiki/ Wifi#Estándares_que_certifica_la_Alianza_Wi-Fi. Accessed: 2019-0430. (Archived by WebCite R at http://www.webcitation.org/781fubRRd). 56