Tesis Audiometro Con Raspberry Pi
Tesis Audiometro Con Raspberry Pi
Y SISTEMAS DE TELECOMUNICACIÓN
VºBº
Calificación:
El Secretario,
Diseño e implementación de un audiómetro con Raspberry Pi
Resumen
Resumen
La interfaz que ayuda al operario a comunicarse con el oyente es un teléfono móvil, con
sistema operativo Android 9, en él está instalada la aplicación que permite al operario
modificar los parámetros antes mencionados, así como ver representada en forma de
gráfica el umbral de audición del oyente (una vez haya terminado la prueba) junto a la
curva típica según su edad y sexo. Una vez finalizada la audiometría, se podrá obtener
un informe detallado de los resultados de la prueba, en ambos canales, y ser enviado al
paciente vía correo electrónico a la dirección que haya indicado en la aplicación. El
lenguaje de programación utilizado para el diseño de esta aplicación es Java, y XML
(eXtensible Markup Language) para la interfaz gráfica.
Los resultados de las audiometrías realizadas, filtradas por edad y sexo, tienen gran
correlación con los umbrales de audición medios, de acuerdo a esos parámetros.
Página 2
Diseño e implementación de un audiómetro con Raspberry Pi
Abstract
Abstract
The project has the title of design and implementation of an audiometer with Raspberry
Pi, the development of that it is summarized below.
Regarding audiometers, the system has to comply with UNE-EN 60645-1 standard,
which determined the requirements related with frequency response, harmonic
distortion, signal to noise ratio, pressure levels, etc. In this norm talks about four types
of audiometers, the audiometer to be implemented in this project is type 2. The
requirements of this type are better adjusted to the objectives of this project.
To the development of this audiometer has been used the single-board computer of
Raspberry Pi 3 B+ [2], which by GPIO (General Purpose Input/Output) pins has been
added the stereo sound card Audio Injector [3]. The Raspbian operating system of
Mathworks is embedded in this board. In this system is installed the audiometer
application, which has been designed from MATLAB/Simulink. This application allows
receiving via UDP (User Datagram Protocol) the necessary guidelines to make a correct
audiometry. These are the selection of the frequency of the tone, the level of the same
one and the channel by which it is desired to transmit. These parameters arrive at a code
implemented in MATLAB (System object) that processes it and executes it. As output
of the Raspberry system is the DD45 headphones, these complies the requirements to
realize these measurements, having been previously calibrated (by an ear simulator).
These are connected to the sound card by means of the headphone jack.
Página 3
Diseño e implementación de un audiómetro con Raspberry Pi
Abstract
The interface that helps the user to communicate with the listener is a mobile phone,
with Android 9 operating system, in this mobile phone it is installed the application
which permit to the technician change the parameters (previous mentioned), as well as
seeing the listener‟s hearing threshold (once the test is finished) represented next to the
typical curve according to age and sex. Once the audiometry is finished, the user can
obtain the results of the test, in both channels, and sent to the patient via email (to the
address indicated in the application). The programming language used for the design of
this application is Java, and XML (eXtensible Markup Language) for the graphic
interface.
As mentioned above, the communication protocol between these two devices is the
UDP protocol. In order to be communicate this devices, they have to be in the same
network. This is the reason about a WAP (Wireless Access Point) is created from the
mobile phone, allowing a private network between the mobile device and the Raspberry
Pi. It is necessary previously to assign a static IP address to the Raspberry, in order to
create a socket and communicate both devices. Once this communication is created,
datagrams are sent from the phone to the Raspberry with the channel, frequency and
level information. It processes this information continuously and in real time, and
transmits it to the sound card to be reproduced. At the end, after evaluating all the
frequencies and channels, the result of the audiometry will be obtained.
With regard to the Budget of the Project is 205.94€, of which the student has paid
63.26€ and the rest are articles contributed by Universidad Politécnica de Madrid
(UPM).
The results of the audiometries performed, filter by age and sex, have a high correlation
with the average hearing thresholds, according to these parameters.
Página 4
Diseño e implementación de un audiómetro con Raspberry Pi
Índice
Índice:
Resumen ........................................................................................................................... 1
Abstract ............................................................................................................................. 3
Índice: ............................................................................................................................... 5
Índice de figuras ............................................................................................................... 7
Índice de tablas ............................................................................................................... 10
Lista de acrónimos .......................................................................................................... 11
Introducción .................................................................................................................... 12
Objetivos......................................................................................................................... 14
Audiómetro ..................................................................................................................... 15
Definición .............................................................................................................. 15
Normativa.............................................................................................................. 17
Requisitos generales................................................................................ 18
Requisitos de seguridad .......................................................................... 19
Requisitos de la señal de ensayo ............................................................. 19
Transductores .......................................................................................... 21
Calibración ............................................................................................................ 21
Manual de instrucciones ........................................................................................ 24
Audiometría .................................................................................................................... 25
Definición .............................................................................................................. 25
Normativa.............................................................................................................. 26
Preparación de la audiometría ................................................................. 28
Determinación del umbral de audición, en condución aérea, por
audiometría de frecuencias fijas.............................................................. 28
Procedimiento de ensayo sin enmascaramiento ...................................... 29
Audiometría de reconocimiento .............................................................. 29
Audiograma............................................................................................. 30
Ruido ambiente admisible....................................................................... 30
Mantenimiento del equipo audiométrico ................................................ 30
Problemas médicos ......................................................................................................... 32
Umbrales de audición ..................................................................................................... 34
Marco tecnológico y recursos ......................................................................................... 39
Página 5
Diseño e implementación de un audiómetro con Raspberry Pi
Índice
Página 6
Diseño e implementación de un audiómetro con Raspberry Pi
Índice de figuras
Índice de figuras
Figura 23 ......................................................................................................................... 51
Página 7
Diseño e implementación de un audiómetro con Raspberry Pi
Índice de figuras
Página 8
Diseño e implementación de un audiómetro con Raspberry Pi
Índice de figuras
Página 9
Diseño e implementación de un audiómetro con Raspberry Pi
Índice de figuras
Índice de tablas
Página 10
Diseño e implementación de un audiómetro con Raspberry Pi
Índice de tablas
Lista de acrónimos
Frecuencias Convencionales - FC
Desviación Estándar - DE
Intervalo de Confianza - IC
Página 11
Diseño e implementación de un audiómetro con Raspberry Pi
Introducción
Introducción
Por medio de las administraciones públicas se intenta reducir los graves y peligrosos
efectos que tiene la contaminación acústica sobre la salud personas; una de las
principales medidas es limitar los niveles de ruido generados por ciertas actividades a
través de legislaciones que limitan el ruido permitido, teniendo en cuenta diversos
factores sociales y laborales. Del mismo modo se otorgan subvenciones para mejorar el
aislamiento en los hogares que se enfrentan a diario a altos niveles de contaminación
acústica, los cuales no pueden ser paliados de otro modo ya que no pueden ser a penas
limitados.
Este proyecto se define en cinco grandes bloques, el primero trata acerca de los
audiómetros, su normativa y restricciones, a continuación se menciona en qué consiste
una audiometría y cómo esta ha de ser realizada, de acuerdo a la normativa relacionada
con la ejecución de las mismas. El segundo bloque trata de la implementación del
audiómetro, defición y comunicación entre todos los componentes del proyecto. El
tercer bloque trata sobre el desarrollo de la aplicación en la Raspberry Pi, las
características de la misma, la aplicación desarrollada en ella, su salida y comunicación
con el paciente. El cuarto bloque aborda la comunicación con este controlador, que se
hace a través de una aplicación desde un teléfono móvil con el sistema operativo
Android. Por último, se muestran las audiometrías realizadas a diversos oyentes para
comprobar el correcto funcionamiento del audiómetro. Se finaliza la memoria con una
conclusión acerca del desarrollo del proyecto.
Página 13
Diseño e implementación de un audiómetro con Raspberry Pi
Objetivos
Objetivos
Para realizar este objetivo, se implementa una aplicación sobre el sistema operativo
embebido en la Raspberry-Pi, la cual permitirá seleccionar el canal de trabajo, la
frecuencia y el nivel del tono.
Para la comunicación entre estos dispositivos se creará una red inalámbrica entre estos
dispositivos desde un teléfono móvil, de fácil implementación y que el usuario pueda
activar de una manera simple, sin necesidad de ser reconfigurada una vez haya sido
diseñada.
Aparte de lo indicado anteriormente, también se hará uso de una tarjeta de sonido sobre
la Raspberry-Pi que permitirá gestionar las salidas y demás funcionalidades de audio.
Página 14
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
Audiómetro
Definición
Un audiómetro es un instrumento que sirve para medir la audición de un oyente.
Mediante la repetición de pruebas subjetivas se conocerá el límite para el cual el oyente
deja de percibir un sonido. A esto se le llama umbral de audición, se tratará sobre ello
más adelante. Las pruebas que delimitan el umbral de umbral de audición son conocidas
como audiometrías.
En lo referente a la materia que se va a tratar hay varios términos que han de ser
conocidos para poder ser tratados posteriormente, todos ellos han sido obtenidos
directamente de la normativa UNE-EN 60645-1 [5]:
Página 15
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
se activa por aquella señal eléctrica de entrada que, con el auricular aplicado
al oído implicado, correspondería al umbral de audición.
- Nivel de presión acústica umbral equivalente de referencia; RETSPL:
A una frecuencia concreta, el valor medio, modal o mediana de los niveles de
presión acústica equivalentes de un número suficientemente grande de oídos de
personas otológicamente normales de uno y otro sexo de edades entre 18 y 25
años inclusive, expresando el umbral de audición en un simulador de oído o en
un acoplador acústico para un tipo de auriculares determinado.
- Nivel de fuerza umbral equivalente de referencia; RETFL:
A una frecuencia especificada, el valor medio de los niveles de fuerza umbral
equivalentes de un número suficientemente grande de oídos de personas
otológicamente normales, de uno y otro sexo, con edades entre los 18 años y los
25 años inclusive, expresando el umbral de audición en un acoplador mecánico
especificado, para una configuración especificada del vibrador óseo.
- Nivel de audición de un tono puro; HL:
A una frecuencia especificada, para un tipo de transductor específico y para
una manera de aplicación especificada, el nivel de presión acústica o el nivel de
fuerza vibratoria generado por el transductor en un simulador de oído,
acoplador acústico o acoplador mecánico especificados, menos el RETSPL o el
RETVFL apropiado.
- Nivel umbral de audición para tonos puros:
A una frecuencia especificada, el umbral de audición a esa frecuencia
expresado como nivel de audición.
- Simulador de oído:
Dispositivo para medir la salida acústica de fuentes de sonido donde la presión
acústica se mide mediante un micrófono calibrado acoplado a la fuente de
forma que la impedancia acústica total del dispositivo se aproxima a la de un
oído humano normal en una localización dada y en una banda de frecuencias
dada.
- Enmascaramiento:
Proceso mediante el cual el nivel de audición de un sonido se eleva por la
presencia de otro sonido (enmascarante).
- Nivel de enmascaramiento efectivo:
Nivel de un sonido enmascarante especificado que es numéricamente igual a
aquél nivel de audición al que el umbral de tono de la persona normal ideal se
elevaría por la presencia de ese sonido enmascarante.
Una vez se han descrito diferentes conceptos básicos para tratar el tema que nos ocupa
nos podemos centrar en la realización del audiómetro y en los requisitos básicos que
este debe tener.
Para adentrarnos en esta materia hay que citar en un primer lugar que se va a
implementar un audiómetro de tipo 2, destinado a realizar audiometrías por vía aérea de
Página 16
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
Normativa
La norma UNE-EN 60645-1 cubre los requisitos para los audiómetros de tonos puros.
Esta norma describe el equipo que está diseñado para las mediciones de la audición en
el rango de frecuencias de 125 Hz a 16 000 Hz (el margen de frecuencias para el equipo
que se desarrollará es, sin la alta frecuencia extendida, únicamente las octavas que van
desde 125 Hz a 8 000 Hz.). Los objetivos primordiales de esta norma son dos: que los
ensayos de audición realizados en el rango de frecuencias mencionado, en un oído
humano, realizados con audiómetros diferentes que cumplan esta normativa, den
resultados sustancialmente iguales; y el otro objetivo es que los resultados obtenidos
representen una comparación válida entre la audición del oído ensayado y el umbral de
audición de referencia [5].
Página 17
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
interés desarrollarlo, aunque esta puede ser desarrollada con facilidad en el caso
de que en un futuro quiera implementarse.
- Del mismo modo que el anterior punto, la respuesta por parte del sujeto ha de
ser visual.
Conducción ósea X X X
Niveles de audición y
frecuencias de ensayo
Ruido enmascarante de
X X X
banda estrecha
Indicador de señal X X
Monitorización audible de
X
la señal de ensayo
X
X
Comunicación verbal Solo operado al
Bidireccional
oyente
NOTA: El rango de alta frecuencia extendido es opcional para los cuatro tipos de audiómetros
Requisitos generales
Página 18
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
Requisitos de seguridad
La norma también indica que si el suministro eléctrico del audiómetro es por red
eléctrica, como es el caso, si se produce cualquier interrupción del suministro eléctrico
de hasta 5s, el audiómetro debe revertir a una condición que ni pondrá en peligro la
audición del sujeto, ni dará lugar a resultados no válidos. Esto se cumplirá siempre en el
caso del audiómetro implementado en este proyecto, ya que el control de esto se realiza
por medio de una interfaz con una batería portátil. Las salas de ensayo para los ensayos
subjetivos deben cumplir con los requisitos relacionados con el ruido de fondo, en la
sección de Audiometría.
Página 19
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
Respecto a la distorsión armónica total máxima no debe exceder los valores indicado en
la tabla 3. Se ha indicado únicamente por conducción aérea.
Niveles de audición
En dB
Tipo 1 Tipo 4
Tipo 2 Tipo 3
Clínico/Investigación Exploración/
Clínico Diagnóstico básico
Frecuencia [Hz] avanzado monitorizado
125 70 - 60 - - - -
250 90 45 80 45 70 35 70
750 120 60 - - - - -
8000 100 - 90 - 80 - -
Página 20
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
±3,7 dB del valor indicado para cualquier ajuste del dial del nivel de audición a las
frecuencias indicadas en el rango de 125 Hz a 4 kHz y no en más de ±6,2 dB a
frecuencias hasta 8 kHz inclusive. Estas limitaciones indicadas en la normativa son
cumplidas por el audiómetro implementado, tal y como se indica en la sección de
calibración de la memoria del proyecto.
Transductores
Calibración
Se pasa a explicar la calibración del audiometro. Para ello se hace uso de un instrumento
de medida como el de la figura 1 (derecha) y un oído artificial, figura 1 (izquierda).
Página 21
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
El equipo que se desea calibrar son los auriculares DD45 - TDH39, figura 3.
El sistema de calibración queda por tanto montado tal y como se indica en la figura 4
(izquierda), para el canal izquierdo; y figura 4 (derecha) para el canal derecho. Se
registran los valores nominales, a cada frecuencia y cada canal, que proporcionan los
niveles de 110 dB de presión sonora, asegurándose previamente que estos valores se
encuentran en el rango de comportamiento lineal del equipo, y que no distorsionan.
Estos datos se registrarán en la aplicación para obtener todos los niveles posibles de
presión, con saltos de 5 dB en 5 dB, hasta el mínimo valor de -10 dB SPL.
Página 22
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
En la tabla 4 se indican los valores nominales obtenidos a cada frecuencia y cada canal
para obtener 110 dB SPL de presión sonora.
Página 23
Diseño e implementación de un audiómetro con Raspberry Pi
Audiómetro
Manual de instrucciones
El manual de instrucciones diseñado cumple con las características indicadas en la
norma mencionada. Se limita a ser una ayuda al operario para indicarle cómo ha de ser
realizada la audiometría junto a este tipo de audiómetro implementado.
Página 24
Diseño e implementación de un audiómetro con Raspberry Pi
Audiometría
Audiometría
Definición
Tal y como ya se ha mencionado, las audiometrías son pruebas subjetivas que se
realizan para dictaminar el umbral de audición de un oyente, haciendo uso de un
instrumento llamado audiómetro. El tipo de audiómetro que se implementa en este
proyecto es un audiómetro tipo 2, por conducción aérea, en el rango de frecuencias
convencionales.
- Audiograma:
Presentación, en forma de un gráfico o de una tabla, de los niveles liminares de
audición de los oídos del sujeto sometido a ensayo, determinados en
condiciones especificadas y según el método especificado, en función de la
frecuencia.
- Umbral de audición:
Nivel de presión acústica, o nivel de fuerza vibratoria, más bajo para el que, en
condiciones especificadas, una persona da un porcentaje predeterminado de
respuestas correctas de detección en ensayos repetidos.
- Efecto de oclusión:
Cambio de nivel de una señal por conducción ósea que alcanza el oído interno
cuando se coloca un auricular o un tapón sobre, o dentro de, la entrada del
conducto auditivo, formando de esta forma un volumen de aire cerrado en el
oído externo.
- Audiometría automática de frecuencia fija:
Audiometría cuyas variaciones en el nivel de audición son controladas por el
sujeto sometido a ensayo y se registran automáticamente para frecuencias
específicas.
- Audiometría de barrido en frecuencia:
Audiometría cuyas variaciones en el nivel de audición son controladas por el
sujeto sometido a ensayo y donde la frecuencia varía continuamente o por pasos
mucho más pequeños que una banda de tercio de octava.
- Audiometría de reconocimiento:
Procedimiento de acierto-fallo donde se presentan los tonos puros a un nivel
fijo, denominado nivel de reconocimiento.
- Nivel liminar de audición de un oído determinado:
A una frecuencia especificada y para un tipo de transductor específico, el
umbral de audición a esa frecuencia, expresado como nivel de audición.
Página 25
Diseño e implementación de un audiómetro con Raspberry Pi
Audiometría
- Acoplador de acústico:
Dispositivo para medir la señal de salida acústica de las fuentes sonoras donde
la presión acústica se mide con un micrófono calibrado, acoplado a la fuente
mediante una cavidad con forma y volumen predeterminado.
- Vibrador óseo:
Transductor electromecánico destinado a producir la sensación de audición
haciendo vibrar los huesos del cráneo.
- Nivel equivalente de presión acústica liminar:
Para un oído determinado, a una frecuencia especificada, para un modelo de
auricular específico y para una fuerza de aplicación determinada del auricular
al oído humano, nivel de presión acústica producido por el auricular en un
simulador de oído o un acoplador acústico específico, cuando el auricular es
alimentado por la tensión que corresponde al umbral de audición del oído en
cuestión cuando este auricular está aplicado sobre el oído.
Una vez conocidos estos conceptos se detalla cómo realizar estos ensayos
audiométricos, y qué requisitos se han de cumplir.
Normativa
La norma UNE-EN ISO 8253-1 es una norma internacional que especifica los requisitos
y procedimientos para la realización de ensayos audiométricos fundamentales, donde
los tonos puros se presentan al sujeto de ensayo utilizando auriculares o vibradores
óseos, en el caso del audiómetro implementado se trata de auriculares.
Página 26
Diseño e implementación de un audiómetro con Raspberry Pi
Audiometría
Dichos niveles laminares se pueden determinar haciendo uso de tonos de ensayo con
frecuencias fijas o una señal de ensayo con una frecuencia que varía con el tiempo de
acuerdo con la tasa de variación predefinida. El audiómetro implementado se define
como un audiómetro capaz de realizar audiometrías de tonos puros, con un audiómetro
manual, por lo que la parte de la norma referente a audiometrías con barridos en
frecuencia será obviada, al igual que las audiometrías realizadas con los vibradores
óseos.
ASPECTOS GENERALES
A continuación, se van a tratar diversos temas generales que se han de tener en cuenta
para la realización de los ensayos audiométricos.
Página 27
Diseño e implementación de un audiómetro con Raspberry Pi
Audiometría
Preparación de la audiometría
Seguido de esto se ha de indicar al usuario, por parte del operario, el procedimiento que
tiene esta prueba y el modo de respuesta que ha de dar el oyente. En el caso del
sonómetro implementado, un ejemplo común de respuesta sería levantar o bajar a mano
una vez se escuche dicho sonido.
Del mismo modo, el oyente debería quitarse cualquier adorno de la cabeza, así como
gafas, aparatos de corrección auditiva, etc. Para que los transductores se fijen del mejor
modo posible, como han sido diseñados.
frecuencias fijas
El sonido debe ser continuo y presentado durante 1s – 2s. El equipo está diseñado para
que se presente durante dos segundos. El intervalo debe ser variado si se produce una
respuesta.
Página 28
Diseño e implementación de un audiómetro con Raspberry Pi
Audiometría
La norma indica que existen dos procedimientos de ensayo: un método por encuadre y
un método ascendente. Difieren solo en la secuencia de los niveles de los tonos de
ensayo presentados al sujeto. En el ascendente: de menos a más, hasta que se produce
una respuesta del oyente. El método por encuadre: similar al anterior, primero de menos
a más y luego de más a menos (el mismo tono).
Fase 1
Presentar el primero sonido de ensayo a un nivel 10 dB por debajo del nivel más bajo de
la respuesta en la sesión de familiarización. Cada vez que el sujeto no responda al
sonido, se aumentará el nivel del mismo en incrementos de 5 dB hasta que se produzca
una respuesta por parte del oyente.
Fase 2
Método por encuadre: Tras la respuesta, se aumenta el nivel del sonido de ensayo en 5
dB y se empieza una serie descendente, durante la cual el nivel del sonido disminuye en
pasos de 5 dB hasta que no se produzca ninguna respuesta del sujeto sometido a ensayo.
Conviene repetir este proceso completando tres series.
Fase 3
Fase 4
Se termina cuando se hayan sometido a la prueba los dos oídos. Obteniéndose el nivel
liminar de audición a cada frecuencia y para los dos oídos.
Audiometría de reconocimiento
Los tonos de ensayo al nivel de reconocimiento son audibles o inaudibles para el sujeto.
Los resultados de este ensayo muestra si los niveles liminares de audición del oyente
son mejores (más bajos), o peores (más altos) que el nivel de reconocimiento utilizado.
Página 29
Diseño e implementación de un audiómetro con Raspberry Pi
Audiometría
Audiograma
Dicha etapa consiste en medir y comparar los resultados con las normas adecuadas para:
Página 31
Diseño e implementación de un audiómetro con Raspberry Pi
Problemas médicos
Problemas médicos
Para este proyecto se trabajan con tonos de diferentes frecuencias. El nivel necesario
para ser escuchado por el oyente es diferente para cada frecuencia. El oído humano no
es igual de sensible a cualquier frecuencia, su sensibilidad es mayor a frecuencias
medias (500-4000Hz), y tiene una sensibilidad menor a frecuencias bajas y altas. La
respuesta de nuestro sistema auditivo tendría una forma equivalente a un filtro paso
banda. El nivel de presión sonora se mide en dB SPL.
El estudio de hipoacusia en las personas tiene gran relevancia para la población, pues
influye en gran medida no solo en la pérdida de la calidad de vida, sino en una gran
cantidad de años con discapacidades. Según la WHO en 2006, la mitad de los casos de
sordera se pueden prevenir si las causas comunes se atienden en el nivel de la atención
primaria de salud. Para ello la detección e intervención tempranas son factores
importantes para minimizar las consecuencias de la pérdida de audición.
La sonoridad (se mide en fonios) está vinculada con la intensidad del sonido. El oído
humano no tiene igual sensibilidad para todas las frecuencias. Este necesita mayor
energía para sentir las frecuencias más graves y las más agudas, siendo más sensible en
las frecuencias que van desde los 500Hz, a los 4kHz.
Para tratar esta esta sensibilidad dependiente de la frecuencia del sistema auditivo
humano, se desarrollaron las curvas isofónicas, las cuales representan curvas con el
mismo nivel de sensación sonora. Las primeras curvas fueron establecidas por Fletcher
y Munson en 1933, y recalculadas más tarde por Robinson y Dadson en 1956. La curva
de 0 fonios corresponden con el umbral de audición y la de 120 fonios con el umbral del
dolor.
Página 32
Diseño e implementación de un audiómetro con Raspberry Pi
Problemas médicos
La figura 6, muestra las curvas isofónicas normales para tonos puros en condiciones de
escucha en campo libre, según la norma ISO 226 (2003) [7].
Para poder ser controlada esta pérdida de audición, se establecen unos umbrales típicos
para cada rango de edad y género. Estos facilitarán al médico su diagnóstico y ayudarán
al oyente a tener una mejor calidad de vida. Lo referente a estos se trata a continuación.
Página 33
Diseño e implementación de un audiómetro con Raspberry Pi
Umbrales de audición
Umbrales de audición
Según la norma ISO 7029 se establecen una distribución estadística de los umbrales de
audición (en función de la edad y género), especificando el valor medio esperado de los
umbrales de audición con respecto al umbral de audición medio.
En comparación con la norma ISO 7029 (2000), para los grupos de edad de 20 a 69, el
autor de la tesis doctoral encontró que los umbrales de audición de su estudio eran
peores (más elevados) que los que proporcionaba dicha norma, especialmente para las
frecuencias entre 125 y 500Hz, para las frecuencias superiores a dicho rango había gran
correlación con las proporcionadas por la norma.
Página 34
Diseño e implementación de un audiómetro con Raspberry Pi
Umbrales de audición
Grupo edad
Frecuencia (Hz)
(años)
125 250 500 1.000 2.000 4.000 8.000
5-19 (n=158)
Media 17 14 12 9 7 8 11
Mediana 15 15 10 10 5 10 10
DE 6,57 5,97 5,15 5,67 5,56 5,75 7,32
20-29 (n=55)
Media 15 12 11 8 6 8 8
Mediana 15 10 10 10 5 10 5
DE 6,04 7,67 6,65 6,17 5,98 6,84 7,47
30-39 (n=85)
Media 16 13 12 9 6 13 11
Mediana 15 15 10 10 5 10 10
DE 6,13 5,99 6,29 5,87 6,07 10,53 10,83
40-49 (n=56)
Media 16 13 12 10 7 13 16
Mediana 15 12 10 10 5 10 15
DE 6,99 6,17 6,18 5,95 6,20 7,92 10,23
50-59 (n=57)
Media 18 15 15 14 11 18 25
Mediana 20 15 15 15 10 20 25
DE 5,80 5,42 6,10 5,57 6,69 10,17 14,55
60-69 (n=63)
Media 20 16 16 15 15 29 36
Mediana 20 15 15 15 15 25 30
DE 6,49 5,42 5,90 6,92 9,91 16,19 19,09
70-79 (n=39)
Media 21 19 18 20 26 42 53
Mediana 20 20 15 20 20 40 55
DE 6,30 6,89 7,66 8,62 16,19 19,82 18,22
80-90 (n=17)
Media 25 21 22 22 36 56 67
Mediana 25 20 25 25 35 55 70
DE 7,88 5,80 7,08 8,48 9,80 11,11 17,68
Página 35
Diseño e implementación de un audiómetro con Raspberry Pi
Umbrales de audición
La figura 7 [1], muestra la media del umbral de audición para hombres. Las barras de
error representan el IC (Intervalo de Confianza) del 95%.
Página 36
Diseño e implementación de un audiómetro con Raspberry Pi
Umbrales de audición
Grupo edad
Frecuencia (Hz)
(años)
125 250 500 1.000 2.000 4.000 8.000
5-19 (n=147)
Media 18 15 13 10 6 7 11
Mediana 20 15 15 10 5 10 10
DE 6,15 5,99 6,13 5,34 5,17 5,59 7,33
20-29 (n=79)
Media 13 10 10 7 5 6 9
Mediana 15 10 10 5 5 5 5
DE 5,75 6,13 5,15 5,38 5,28 6,26 9,38
30-39 (n=87)
Media 15 13 12 10 7 9 9
Mediana 15 10 15 10 10 10 10
DE 6,02 6,41 6,59 6,66 5,74 7,19 8,19
40-49 (n=68)
Media 17 15 14 11 9 12 15
Mediana 15 15 12 10 10 10 15
DE 7,06 6,69 6,91 6,52 6,73 6,89 9,54
50-59 (n=80)
Media 18 14 14 15 12 16 20
Mediana 15 15 15 15 10 15 20
DE 5,67 5,83 5,37 6,40 7,06 8,52 10,28
60-69 (n=76)
Media 19 17 17 16 17 25 36
Mediana 20 15 15 15 15 25 40
DE 5,60 5,68 6,62 6,92 9,53 10,92 15,92
70-79 (n=35)
Media 21 19 20 19 24 33 49
Mediana 20 15 20 15 25 30 50
DE 6,65 6,47 5,93 7,77 10,34 16,44 18,46
80-90 (n=21)
Media 24 21 24 24 34 51 68
Mediana 25 25 25 25 35 50 70
DE 6,30 6,69 8,53 9,69 11,39 14,76 15,29
Página 37
Diseño e implementación de un audiómetro con Raspberry Pi
Umbrales de audición
La figura 8 [1], muestra la media del umbral de audición para mujeres. Las barras de
error representan el IC del 95%.
Página 38
Diseño e implementación de un audiómetro con Raspberry Pi
Marco tecnológico y recursos
Las telecomunicaciones han supuesto una nueva revolución para todo el mundo, la
forma de vida de las personas ha cambiado mucho de una década a otra, como raras
veces han ocurrido a lo largo de la historia. Esto ha afectado a todos los aspectos de la
vida: en las relaciones sociales, laborales y familiares; en la forma de trabajo y hasta en
el contenido de los trabajos; también en la salud de las personas, y en el estudio y
control de esta. Vivimos en un contexto tecnológico en continua evolución y desarrollo,
en el que cada vez existen más posibilidades de progresar tecnológicamente hablando.
Existen posibilidades infinitas, y en eso se sustenta este proyecto. En este nuevo espacio
que se ha creado, la Fundación Raspberry Pi crea un controlador de bajo coste, con
funcionalidades muy diversas, un tamaño muy reducido, y alta funcionalidad y
escalabilidad para el usuario. En esta placa base pueden ser implementadas muy
diversas aplicaciones prácticas, con un coste muy reducido. Es por ello que para el
objetivo de este proyecto se opta por esta placa de desarrollo.
Del mismo modo los teléfonos móviles han experimentado un progreso exponencial, en
escasos años han pasado de ser meros teléfonos portátiles a tener múltiples
funcionalidades, desde servir como tarjetas de crédito, a representar en ellos señales
cardiacas en tiempo real, etc. Es por ello que se utilizarán estos para servir como
interfaz entre el operario y la Raspberry para el desarrollo de estas audiometrías.
Desarrollando una aplicación bajo el sistema operativo de Android 9, con el lenguaje de
programación Java, y el lenguaje XML para el diseño de la interfaz gráfica.
A su vez un recurso muy importante del que se hace uso para elaborar este proyecto es
el entorno de desarrollo MATLAB/Simulink, el cual facilita la programación enfocada a
la Raspberry Pi, reduciendo su complejidad y poniendo el foco en los conceptos que se
desean implementar. En el apartado de Raspberry Pi se detallará la programación en
este controlador.
Los auriculares que se utilizarán cumplen con la normativa mencionada y han sido
calibrados haciendo uso de un simulador de oído. El tema de la calibración será
abordado cuando se hable de la aplicación del Audiómetro en Android.
Página 39
Diseño e implementación de un audiómetro con Raspberry Pi
Marco tecnológico y recursos
Una vez citado el contexto tecnológico en el cual se enmarca este proyecto, y tras hacer
un repaso de los recursos que se poseen para abordar el objetivo marcado, se pasa a
tratar la interconexión de todos estos dispositivos en forma de diagrama de bloques. De
forma simultánea se determina la configuración en la red de estos dispositivos, para
poder ser tratados en profundidad en capítulos posteriores.
Página 40
Diseño e implementación de un audiómetro con Raspberry Pi
Diseño e implementación del proyecto
Para que esto ocurra y que el sistema trabaje correctamente, los dispositivos se han de
encontrar en una misma red, para que puedan comunicarse entre sí. En el apartado del
diagrama de red se explicará en profundidad las características de esta red y de los
dispositivos en ella.
Diagrama de bloques
El sistema queda resumido en la figura 9. El operario por medio de la interfaz del
teléfono móvil es capaz de comunicarse con el oyente, enviando datagramas, mediante
el protocolo UDP, a la Raspberry. Estos datagramas contienen datos sobre el canal, la
frecuencia y el nivel del tono a emitir. El oyente responde al operario cuando percibe el
sonido, fijando así el umbral de audición. El ordenador se comunica vía SSH (Secure
SHell) con la Raspberry para configurarla e instalar en ella la aplicación del audiómetro.
La configuración del driver de la tarjeta de sonido (ALSA) permite que las señales de
audiometría sean accesibles por el oyente a través de sus auriculares.
Página 41
Diseño e implementación de un audiómetro con Raspberry Pi
Diseño e implementación del proyecto
Página 42
Diseño e implementación de un audiómetro con Raspberry Pi
Diseño e implementación del proyecto
Diagrama de red
En el diagrama de red de la figura 12 se muestra la configuración de la misma. Se
detalla también los puertos UDP de la Raspberry con los que se comunican los dos
dispositivos.
- Teléfono móvil:
o Dirección IP dinámica 192.168.43.X
o Máscara de subred: 255.255.255.0
o Puerta de enlace: 192.168.43.1
- Raspberry Pi:
o Dirección IP estática: 192.168.43.147
o Máscara de subred: 255.255.255.0
o Puerta de enlace: 192.168.43.1
- Ordenador portátil:
o Dirección IP dinámica 192.168.43.X
o Máscara de subred: 255.255.255.0
Página 43
Diseño e implementación de un audiómetro con Raspberry Pi
Diseño e implementación del proyecto
Las direcciones MAC de cada máquina no se indican pues no resulta de interés para el
desarrollo de la memoria del proyecto.
Se han elegido direcciones IP dinámicas tanto para el ordenador portátil como para el
teléfono móvil, pues no necesitan ser conocidas/registradas por ninguno de los
dispositivos presentes en el sistema, por lo que es irrelevante cuál sea esta. No existe
comunicación en ningún momento de este proceso entre el móvil y el ordenador, en lo
referente al envío de información para la audiometría, pero es el teléfono quien le da
acceso a la red, por eso está presente ese enlace en la figura 12. Este sí que se comunica
con la Raspberry para la instalación de la aplicación y para configurar esta, vía SSH. El
teléfono envía datagramas a la Raspberry, con el protocolo UDP, en los puertos: 26000,
26001 y 26002 (de la Raspberry). Este protocolo no tiene establecimiento de la
conexión, ni control de los paquetes que se envían, es por ello que no es necesario el
conocimiento de la IP de origen.
Página 44
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Raspberry Pi
Se pasa a hablar sobre la placa en cuestión, bajo la cual se ha trabajado en este proyecto.
Raspberry Pi 3 Modelo B+
El modelo en cuestión con el que se ha trabajado es el que aparece en la figura 14.
Página 45
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 46
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Para poder localizar todos los componentes sobre la placa se adjunta la figura 15, en la
que es posible identificar los componentes antes mencionados.
Una vez han sido descritas las características del modelo de tarjeta Raspberry Pi, se pasa
a describir la configurar de la misma, previa referencia al entorno de trabajo de
MATLAB.
MATLAB/Simulink
MATLAB (MATrix LABoratory) es un sistema de cómputo numérico que ofrece un
entorno de desarrollo integrado (IDE) con un lenguaje de programación propio. Está
disponible para plataformas Unix, Windows, Mac OS X y GNU/Linux [9].
Página 47
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Para ello han de ser instalados previamente dos paquetes de MATLAB y agregados a la
configuración del mismo, para que este pueda comunicarse con la Raspberry, tal y como
se ha mencionado previamente. Los paquetes a instalar son dos: “MATLAB Support
Package for Raspberry Pi Hardware” y “Simulink Support Package for Raspberry Pi
Hardware”.
Configuración de la Raspberry
Recordando la figura 12 (direcciones IP del sistema), se asigna a la placa de Raspberry
una dirección que se encuentre dentro del rango permitido de la red creada (esto puede
ser realizado a la hora de instalar el sistema operativo). En el diseño de la red, esta debe
de ser capaz de comunicarse con el ordenador, el cual le transferirá la aplicación del
audiómetro que correrá en el sistema operativo antes mencionado, y también con el
teléfono móvil, que le enviará información relevante para la evaluación audiométrica
del oyente.
Página 48
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 49
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Para que la placa pueda comunicarse con el resto de dispositivos ha de tener una
dirección IP estática, dentro del rango permitido, y la misma puerta de red (Default
Gateway) que el resto de dispositivos. En este caso se ha escogido como dirección IP:
“192.168.43.147” para la Raspberry, la máscara de red es “255.255.255.0” y la puerta
de red: “192.168.43.1”.
Página 50
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Una vez el ordenador esté en la misma red, con SSID: “VictorRaspberry”, es posible
trabajar en MATLAB con la Raspberry, sin la necesidad de red Ethernet.
Por medio del protocolo SSH se puede acceder remotamente a la Raspberry. Para ello se
hace uso de la aplicación PuTTY, aplicación con licencia libre, disponible en varias
plataformas, que puede ser llamada desde MATLAB. Los comandos necesarios para
acceder remotamente a la Raspberry aparecen en la figura 23, en dicha figura se observa
a su vez que se accede exitosamente a la Raspberry.
Figura 23
Una vez dentro de la misma se puede acceder al fichero donde se configura los datos de
red, y la asignación de dirección IP estática que se había configurado anteriormente, a la
Página 51
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Utilizando este protocolo se podrá, entre otras cosas, configurar la tarjeta de sonido, por
medio de la cual obtendremos la salida de nuestra aplicación, examinar el rendimiento
de la aplicación, el rendimiento de la CPU (Central Processing Unit), comprobar
niveles de entrada y salida de audio, etc.
Página 52
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 53
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Dispone de dos canales de entrada de audio y otros dos de salida. Incluye un control de
volumen de hardware tanto para entrada como para salidas, se puede modificar el nivel
de estas entradas y salidas con un sencillo fader rotativo. A su vez, dispone de un
preamplificador de auriculares, e incluye la tarjeta un micrófono, no de muy buena
calidad. Utiliza condensadores de desacoplamiento de tantalium DC para tener una alta
calidad de sonido. La frecuencia de muestreo es de 92 kHz, y trabaja sobre 32 bits.
Proporciona el mismo encabezado GPIO para poder ser ampliado el sistema, aunque
esto no será necesario para el objetivo de este proyecto.
Página 54
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Este finalmente queda modificado como se indica en la figura 28, para guardar dicho
archivo se ha de pulsar Ctrl+X y guardar el mismo. Esto hará que quede definida como
tarjeta principal de audio la tarjeta de Audio Injector, y quedará establecida como
principal. Para que queden registradas dichas operaciones se ha de reiniciar el
dispositivo. Esto se hace con el comando sudo reboot. Una vez realizadas estas
operaciones, cada vez que se inicie el equipo arrancará con esta configuración.
Página 55
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Se han de configurar los parámetros necesarios para que la salida del sonido se realice
por los conectores oportunos, así como configurar ciertas entradas para que se puedan
realizar pruebas previas acerca del buen funcionamiento de la tarjeta. Para ello se
enviará el comando alsamixer. Viendo todas las configuraciones posibles del sonido, se
quedará tal y como se muestra en la figura 29. Activando y desactivando las entradas y
salidas oportunas, así como la entrada de micrófono, etc. La ganancia del Master de
salida ha de ser de 0 dB. Para activar y desactivar entradas y salidas, se realiza pulsando
la tecla „m‟ o espacio, así se pueden conmutar todas estas opciones. Para salir se pulsa la
tecla escape, y se reinicia el sistema para dejar esta configuración salvada.
Página 56
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Figura 29 - AlsaMixer
Aplicación: Audiómetro
Se ha de adentrar en el objetivo principal del proyecto que no es otro que la
implementación de un audiómetro sobre Raspberry Pi.
Página 57
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Esta área ha sido diseñada para recibir información enviada por el usuario desde el
teléfono móvil, concretamente la información consiste en datos acerca de la frecuencia,
nivel y canal de escucha. Dicho bloque ha sido implementado para escuchar de forma
independiente en tres sockets distintos y bien diferenciados (figura 31).
Página 58
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 59
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
concatenar los tres datos en un mismo datagrama y enviarlos por un único puerto, y una
vez lleguen al destino, a la Raspberry, obtener la información referente a estos tres datos
que fueron encapsulados en un único datagrama. Esta opción es más costosa y resulta
poco eficiente pues el coste computacional del uso de estos tres puertos no supone un
problema para este sistema.
Esta área (figura 33) está dedicada a la gestión de la información que proviene de los
módulos UDP para convertirlos en los tonos que escuchará el oyente. El sistema
dispone de tres entradas diferenciadas, como los tres argumentos que gestiona, mediante
la interfaz, el operador para dictaminar el umbral de audición del oyente. Una vez
procesada dicha información se genera un tono que es enviado a la salida. El sistema
posee dos salidas, como los dos canales de audición a evaluar.
Página 60
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
end
properties(DiscreteState)
end
Página 61
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
methods(Access = protected)
function setupImpl(obj,canal,frecuencia,nivel)
% Perform one-time calculations, such as computing
% constants
% Inicialización de variables
obj.N=24576; %longitud de los
frames de datos de entrada
obj.t=(0:obj.N-1)/(obj.Fs); %Duración del tiempo
% datos de entrada
obj.yL=zeros(obj.N,1); % Frame de salida canal L
obj.yR=zeros(obj.N,1); % Frame de salida canal R
end
outL=obj.yL(1:obj.N,1);
outR=obj.yR(1:obj.N,1);
end
Página 62
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
function resetImpl(obj)
% Initialize / reset discrete-state properties
end
end
end
Por último resta por explicar el último módulo de esta área, se trata de un módulo
llamado Matrix Concatenate (figura 35), cuya traducción explica el funcionamiento del
mismo. Se trata de un módulo dedicado a concatenar las dos salidas del System object,
los dos canales (estéreo), en una única señal de salida. Se crea una matriz de dichas
dimensiones para poder ser transferida al siguiente área dedicada a crear la salida del
sistema.
Audioinjector: Salida
El área dedicada a la salida del Audio Injector (figura 36) contiene tres módulos bien
diferenciados y fáciles de describir. Esta área consiste en armar una señal capaz de ser
enviada al driver ALSA de salida de la tarjeta Audio Injector estéreo para Raspberry.
Página 63
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 64
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Por último el bloque dedicado a la reproducción ALSA Audio Playback (figura 39), la
salida es una señal analógica. Se trata de un convertidor que envía al driver de la tarjeta
de sonido la señal analógica generada. Las dimensiones de la matriz son [Nx2], donde N
es el tamaño de la muestra. La frecuencia de muestreo ha de coincidir con la cual se ha
generado la señal en el área de Generación del tono: 48 000 Hz, tal y como se refleja en
la figura indicada que ha sido seleccionada en este módulo. El campo que indica el
nombre del dispositivo (Device name) es plughw:card,device los dos últimos
parámetros han sido configurados con anterioridad, pueden ser obtenidos utilizando el
comando “aplay –l” en la ventana de comandos de la Raspberry. Una vez enviada la
señal al usuario, este interactuará con el operario indicándole si es capaz de escuchar la
señal.
Página 65
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Control LED
Área encargada de mostrar de forma visual al operario que la aplicación está abierta y
trabajando (figura 40). Se trata de una generación de pulsos periódicos que son
reproducidos en forma de señal luminosa, en el LED ubicado en la placa de la
Raspberry Pi. Esta señal se reproduce siempre que la aplicación está corriendo. Esta
función se divide en tres módulos, tal y como se aprecia en la figura 40.
El primer bloque de esta área (figura 41) es el encargado de generar una señal tipo pulso
que será enviada tras pasar por un convertidor al LED para ser emitida como señal
lumínica. Como parámetros relevantes de interés, en la figura anteriormente
mencionada se puede observar que la amplitud seleccionada es la más alta posible, que
se trata de una señal periódica con un periodo de 0.5s, que el ancho del periodo es de
10%. El resto de parámetros son los configurados por defecto.
El siguiente bloque (figura 42), conectado al del Generador de pulsos, es el Data Type
Conversion, la configuración es similar al otro bloque del mismo tipo mencionado
Página 66
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
anteriormente, con la gran salvedad de que el tipo de datos a la salida de este bloque y
entregado al módulo dedicado al LED es: Inherit, que es el tipo de dato requerido para
este cometido.
Por último en esta área se encuentra el bloque dedicado al LED (figura 43). Este bloque
es perteneciente a la librería Simulink orientado a Raspberry Pi, como son los bloques
de recepción UDP y Alsa Audio Playback. En este bloque se ha de seleccionar el
modelo de Raspberry con el que se trabaja, que en este caso es: Raspberry Pi 3 Modelo
B+, y como solo se tiene un LED para trabajar con él, se selecciona el led0, color verde
(Green).
Osciloscopio
Página 67
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 68
Diseño e implementación de un audiómetro con Raspberry Pi
Raspberry Pi
Página 69
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
Ha habido 16 versiones diferentes de este sistema operativo, durante la corta vida que
tiene. La aplicación desarrollada en este proyecto se instala sobre la última versión de
este sistema operativo: Android 9.0 (“Pie”).
Página 70
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
Página 71
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
También hay que recordar que anteriormente se creó una red privada para que puedan
comunicarse todos estos dispositivos, en la cual el teléfono móvil estaba configurado
como router con una IP dinámica. Además, se estableció que el SSID de la red fuera
“VictorRaspberry”.
Página 72
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
Aplicación: Audiómetro
Uno de los objetivos del proyecto es diseñar una aplicación móvil que sirva de interfaz
para comunicarse con la tarjeta Raspberry Pi y poder enviar los parámetros necesarios
para generar la señal de audiometría (sinusoide) y esta pueda ser percibida por el
oyente, y a la vez obtener el audiograma, resultado de la audiometría.
En un primer momento se pensó en realizar una nueva tarjeta que sirviese de esta
interfaz, pero sus funcionalidades se quedaban limitadas, es por eso que se buscó por
nuevas soluciones. Entre ellas se descubrió que la mejor opción posible era una
aplicación sobre un dispositivo portátil como es un teléfono móvil, desde donde se
pudiese transferir estos parámetros, necesarios para la creación de los tonos de
frecuencia delimitados por la normativa anteriormente explicada.
Desde esta aplicación se desea comunicar con la tarjeta Raspberry Pi, vía UDP (por
medio de tres sockets) para modificar las características de la señal emitida, representar
el umbral de audición del oyente y generar un documento “pdf” con todos los resultados
del ensayo para posteriormente enviarlo al paciente.
Página 73
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
En android cada actividad tiene su parte lógica, un archivo *.java, y su parte gráfica, un
archivo *.xml. Para poder explicar de forma correcta esta aplicación se procederá por
partes, y como el uso de la misma siempre tiene una secuencia igual, se seguirá la
secuencia de uso de la misma para poder ser explicada. Se detallará primero el código
del fichero java, cuál es el objetivo del mismo, y luego la interfaz gráfica.
Por último mencionar la “carpeta” res, donde se encuentran las vistas (las interfaces
gráficas de la aplicación, los layout) y los valores generales como strings.xml que serán
utilizados más tarde en la aplicación.
La figura 52 (lado derecho), se muestran los archivos del proyecto: a destacar las dos
librerías externas de las que se hará uso (app/libs): GraphView-4.0.1.jar e itextpdf-
5.4.4.jar.
Página 74
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
Página 75
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
El este primer Fragment (FragmentDatos) del código destinado al registro de los datos
tanto del oyente como del operario; los cuales han de ser enviados a la actividad
principal, por medio de la interfaz: FragmentDatosListener, como ya se había
mencionado.
Por medio de Spinner y EditText se obtienen todos los datos necesarios para formalizar
el registro de los agentes implicados en la audiometría. Este registro se realiza cuando el
operario pincha en el botón de registrar datos, y estos se envían al canal de
comunicación de toda la aplicación que es la actividad principal, por medio de la
interfaz anteriormente mencionada.
Página 76
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
Cada vez que se desea reproducir un tono diferente se ha de accionar el botón play
indicado. Creando un nuevo hilo en cada ocasión. Este muere cuando finaliza el envío.
Página 77
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
Dicha clase, dicho Fragment, contiene como vista el Layout llamado audiometría.xml,
que se muestra a continuación del código de la clase FragmentAudiometria. Este Layout
sigue la misma lógica que el del Fragment de datos, con la única salvedad de los
FloatingActionButton, que sirven para reproducir la señal y el segundo para indicar que
ya se encuentra accesible la gráfica de la audiometría. Este último se muestra oculto
hasta que se completa de registrar todos los valores del ensayo audiométrico, es
entonces cuando se visualiza.
Se procede a explicar la clase del hilo que ha sido declarado en la anterior clase:
UdpClientThread. La clase se guarda en el paquete principal: com.example.audiometria.
Como se explicó en el diagrama de bloques del sistema, es necesario que se realice una
comunicación entre el teléfono móvil y la Raspberry, la cual tiene como dirección IP en
la red “VictorRaspberry”: "192.168.43.147". La Raspberry se va a encontrar
escuchando información en los puertos UDP: 26000, 26001 y 26002; en dichos puertos
se envía la siguiente información: canal, frecuencia y nivel, respectivamente.
Esta clase no contiene ninguna vista, pues es un hilo que corre ajeno al hilo principal de
la aplicación. Cada vez que se crea, arranca y muere. La clase se llama
UdpClientThread y hereda de la clase Thread.
Cuando se instancia lo hace con los valores anteriormente explicados. Cuando corre
(run) es cuando se intenta realizar estas transmisiones.
Página 78
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
En el anexo 7 se muestra el código. Esta clase no tiene asociado ningún layout ya que se
trata de un hilo.
Al comienzo de la clase se fijan los ejes de las gráficas, las leyendas de los mismos y la
estética de estas, a la vez que se agregan las series (LineGraphSeries) a los gráficos. Se
continúa instancializando los arrays referentes al valor de las frecuencias, y al array
multidimensional referente a los umbrales medios de audición, dependientes del sexo,
rango de edad y frecuencia de la población española, citados anteriormente en la
memoria del proyecto.
A continuación se fijan los límites superior e inferior del eje de abscisas (mínima y
máxima frecuencias evaluadas).
Página 79
Diseño e implementación de un audiómetro con Raspberry Pi
Teléfono móvil con Android
El botón destinado a generar el documento pdf queda habilitado cuando se muestran los
dos canales. Habiéndose obtenido previamente, tal y como se ha mencionado, todos los
datos del oyente y del operario vía el canal de comunicación de la actividad principal, se
pasa a generar el documento pdf, que tendrá como nombre: FILENAME =
"Audiometria_" seguido del nombre y apellidos del oyente. Se creará un objeto de la
clase PdfManager, el cual por medio del método “createPdfDocument” se generará el
archivo pdf, con todos los parámetros necesarios. Una vez hecho esto, se enviará por
email el mismo con el método: “sendPdfByEmail”.
A su vez, se define una interfaz encargada de recoger los datos del canal de
comunicación creado con la actividad principal de la aplicación, llamada
“FragmentGraficaListener”.
Página 80
Diseño e implementación de un audiómetro con Raspberry Pi
Manual de usuario
Manual de usuario
En un primer lugar se ha de crear una Zona WiFi desde el teléfono móvil para que se
puedan enviar datos entre los dos dispositivos. Dicha red ya está configurada y solo será
necesario activar la zona Wifi para que sea posible la comunicación entre ambos. Para
ello se ha de acceder al menú de “Ajustes”, luego a la opción de “Conexiones
inalámbricas y redes”. Se pulsa a continuación en “Anclaje y zona Wi-Fi”, después
“Zona Wi-Fi portátil”, para finalmente seleccionar “VictorRaspberry”. Ya se habrá
activado la misma y se podrá regresar al menú principal del teléfono móvil.
Página 81
Diseño e implementación de un audiómetro con Raspberry Pi
Manual de usuario
Una vez realizadas estas acciones podrá comenzar la audiometría. Para ello ha de
conectar la tarjeta Raspberry-Pi a la corriente eléctrica, por medio de un cargador
universal USB 3.0 tipo C, y conectar los auriculares DD45 - TDH39 a la salida de
auriculares.
Una vez conectada la aplicación del audiómetro empieza a correr de forma autónoma en
la Raspberry. Está en continua espera de recibir información desde la aplicación
instalada en el móvil, sin necesidad de realizar nada más sobre el sistema de la
Raspberry.
Página 82
Diseño e implementación de un audiómetro con Raspberry Pi
Manual de usuario
Nada más iniciar la aplicación aparece la pestaña “DATOS”. Han de ser rellenados
todos los campos: los referidos al paciente (con especial relevancia a la edad y al sexo
son obligatorios) y los del operario (visibles utilizando la pestaña hacia abajo).
Una vez estos han sido rellenados, se ha de pulsar en “REGISTRAR DATOS” para que
estos sean guardados. Si esto se ha realizado correctamente la aplicación lo notifica al
operario con el siguiente mensaje: “Se han registrado los datos del paciente”. En el caso
de que haya habido un error se puede volver a pulsar en “REGISTRAR DATOS”.
Una vez se han registrado todos los valores (de 125Hz – 8000Hz, para los dos canales)
el programa indica al operario que ya “Se ha dibujado la gráfica” y se indica en la
esquina derecha un icono de una gráfica, indicando al operario que ya puede pasar a la
siguiente pestaña para ver los resultados. Igualmente todavía puede ser modificada
alguna frecuencia si así lo desea el operario.
Página 84
Diseño e implementación de un audiómetro con Raspberry Pi
Manual de usuario
Página 85
Diseño e implementación de un audiómetro con Raspberry Pi
Manual de usuario
Como una utilidad añadida de la gráfica se puede pulsar en cualquier valor de las dos
series que se representan y ver su valor para la frecuencia seleccionada, indicando a su
vez la serie que ha sido escogida.
La serie “Media” (color rojo) indica la media del umbral de audición para el rango de
edad y sexo seleccionado por el operario al que pertenece el paciente.
Una vez hecho esto se visualiza y habilita el botón “GENERAR Y ENVIAR PDF”. Se
selecciona el método/aplicación de envío. Finaliza enviando al oyente sus resultados por
la vía de envío escogida.
Página 86
Diseño e implementación de un audiómetro con Raspberry Pi
Resultados
Resultados
Página 87
Diseño e implementación de un audiómetro con Raspberry Pi
Resultados
Página 88
Diseño e implementación de un audiómetro con Raspberry Pi
Presupuesto
Presupuesto
Tabla 11 – Presupuesto
PRECIO Presupuesto parcial
ARTÍCULO UNIDADES
(EUR €)/Unidad (EUR €)
Placa de desarrollo
Raspberry Pi 3 Modelo B+ 1 35,66
BCM2837B0 – MPU 35,66
Página 89
Diseño e implementación de un audiómetro con Raspberry Pi
Conclusiones
Conclusiones
Se trata de un sistema de bajo coste que puede ser replicado y utilizado en entornos con
bajos presupuestos, para tener control sobre la población en este problema de la pérdida
de capacidad auditiva, ya que si esta no es controlada puede derivar en años de
discapacidad y pérdida de calidad de vida.
Página 90
Diseño e implementación de un audiómetro con Raspberry Pi
Conclusiones
comunicación por un dispositivo USB OTG desde el teléfono móvil, que se comunicaba
con la Raspberry vía cable Ethernet (conector RJ45); viendo que el operario debía estar
conectado de una forma poco cómoda al manejo del dispositivo, se acabó desechando;
y, por último, se optó por la comunicación vía UDP, bajo una red creada por el mismo
dispositivo móvil. Esta fue la más útil, cómoda y efectiva forma de realizar la
comunicación.
Entre las futuras líneas de mejora del audiómetro implementado se encuentran las
siguientes: adaptar el mismo para poder cumplir con otras normativas, realizar
audiometrías para señales vocales, señales de ensayo de duración corta, audiometrías de
alta frecuencia extendida, audiometrías por vía ósea, etc.; diferenciando las nuevas
funcionalidades agregadas a las actuales. Concretando qué clase de audiómetro es cada
uno, y si cumple o no las normativas oportunas. Del mismo modo se pueden
implementar los requisitos oportunos para que el audiómetro que se ha diseñado en este
proyecto cumpla con los requisitos de un audiómetro tipo 1.
Página 91
Diseño e implementación de un audiómetro con Raspberry Pi
Referencias
Referencias
[2] Fundación Raspberry Pi. (Sin fecha). Raspberry Pi 3 Model B+, [disponible on-
line: https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus/], consultado en
Abril de 2019.
[3] Audio Injector. (Sin fecha). Stereo Raspberry pi sound card, [disponible on-line:
http://www.audioinjector.net/rpi-hat], consultado en Abril de 2019.
Página 92
Diseño e implementación de un audiómetro con Raspberry Pi
Referencias
Página 93
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexos
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.WRITE_INTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.READ_INTERNAL_STORAGE"/>
</manifest>
Página 94
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<string-array name="canalGrafica">
<item>Seleccionar Canal:</item>
<item>Canal: Izquierdo</item>
<item>Canal: Derecho</item>
</string-array>
<string-array name="canal">
<item>Izquierdo</item>
<item>Derecho</item>
</string-array>
<string-array name="sexo">
<item>...</item>
<item>Hombre</item>
<item>Mujer</item>
</string-array>
<string-array name="frecuencia">
<item>125</item>
<item>250</item>
<item>500</item>
<item>1000</item>
<item>2000</item>
<item>4000</item>
<item>8000</item>
</string-array>
<string-array name="nivel">
<item>-10</item>
<item>-5</item>
<item>0</item>
<item>5</item>
<item>10</item>
<item>15</item>
<item>20</item>
<item>25</item>
<item>30</item>
<item>35</item>
<item>40</item>
<item>45</item>
<item>50</item>
<item>55</item>
<item>60</item>
<item>65</item>
<item>70</item>
<item>75</item>
<item>80</item>
<item>85</item>
<item>90</item>
<item>95</item>
Página 95
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<item>100</item>
<item>105</item>
<item>110</item>
</string-array>
</resources>
Página 96
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 3: MainActivity
package com.example.audiometria;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.widget.Toast;
import com.example.audiometria.ui.main.FragmentDatos;
import com.example.audiometria.ui.main.FragmentGrafica;
import com.example.audiometria.ui.main.FragmentAudiometria;
import com.example.audiometria.ui.main.SectionsPagerAdapter;
import java.util.ArrayList;
import java.util.List;
SectionsPagerAdapter sectionsPagerAdapter;
ViewPager viewPager;
private List<Fragment> listaFragments;
public double[] datosIzq,datosDer;
public String
nombre,apellidos,edad,sexo,correo,nombreTecnico,correoTecnico,telefono
Tecnico;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sectionsPagerAdapter = new
SectionsPagerAdapter(this,getSupportFragmentManager(),
listaFragments);
Página 97
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
// Establecemos el Adapter
viewPager.setAdapter(sectionsPagerAdapter);
//TabLayout
tabs.setTabMode(TabLayout.MODE_FIXED);
// Permisos
//if (Build.VERSION.SDK_INT >= 23) { //permission is
automatically granted on sdk<23 upon installation
if(ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED &&
//ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE) !=
ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,},
1000);
}
else{
Toast.makeText(this, "Tiene permisos de lectura y
escritura en la memoria" , Toast.LENGTH_LONG).show();
}
}
@Override
public void onDatosIngresados(double[] datosIzq, double[]
datosDer) {
this.datosIzq = datosIzq;
this.datosDer = datosDer;
}
@Override
public double[] getDatosIzq() {
return this.datosIzq;
}
@Override
public double[] getDatosDer() {
return this.datosDer;
}
@Override
public String getNombre() {
return this.nombre;
}
@Override
public String getApellidos() {
return this.apellidos;
Página 98
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
@Override
public String getEdad() {
return this.edad;
}
@Override
public String getSexo() {
return this.sexo;
}
@Override
public String getCorreo() {
return this.correo;
}
@Override
public String getNombreTecnico() {
return this.nombreTecnico;
}
@Override
public String getCorreoTecnico() {
return this.correoTecnico;
}
@Override
public String getTelefonoTecnico() {
return this.telefonoTecnico;
}
@Override
public void onDatosPacienteIngresados(String nombre, String
apellidos, String edad, String sexo, String correo,
String nombreTecnico, String
correoTecnico, String telefonoTecnico) {
this.nombre = nombre;
this.apellidos = apellidos;
this.edad = edad;
this.sexo = sexo;
this.correo = correo;
this.nombreTecnico = nombreTecnico;
this.correoTecnico = correoTecnico;
this.telefonoTecnico = telefonoTecnico;
}
}
Página 99
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="@dimen/appbar_padding"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar
.Title" />
<android.support.v7.widget.Toolbar
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="23dp"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"></android.support
.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
Página 100
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 4: SectionPagerAdapter
package com.example.audiometria.ui.main;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import com.example.audiometria.R;
import java.util.List;
/**
* A [FragmentPagerAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
@StringRes
private static final int[] TAB_TITLES = new
int[]{R.string.tab_text_1, R.string.tab_text_2, R.string.tab_text_3};
private final Context mContext;
private List<Fragment> fragments;
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given
page.
// Return a PlaceholderFragment (defined as a static inner
class below).
return fragments.get(position);
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return
mContext.getResources().getString(TAB_TITLES[position]);
}
@Override
public int getCount() {
// Show 3 total pages.
return 3; // return fragments.size();
}
}
Página 101
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 5: FragmentDatos
package com.example.audiometria.ui.main;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.support.v4.app.Fragment;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.example.audiometria.R;
/**
* A placeholder fragment containing a simple view.
*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof FragmentDatosListener){
this.listener = (FragmentDatosListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
Página 102
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
buttonPaciente.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
listener.onDatosPacienteIngresados(Nombre.getText().toString(),Apellid
os.getText().toString(),
Edad.getText().toString(),(String)Sexo.getSelectedItem().toString(),Co
rreo.getText().toString(),
NombreTecnico.getText().toString(),CorreoTecnico.getText().toString(),
TelefonoTecnico.getText().toString());
Página 103
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.PlaceholderFragment">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="395dp"
android:layout_height="715dp"
android:orientation="vertical"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="6dp"
app:layout_constraintStart_toStartOf="parent">
<Space
android:layout_width="match_parent"
android:layout_height="25dp" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Nombre"
android:textSize="24sp"
android:textStyle="bold" />
<EditText
android:id="@+id/editTextNombre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint=" ..." />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Apellidos"
android:textSize="24sp"
android:textStyle="bold"/>
Página 104
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<EditText
android:id="@+id/editTextApellidos"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:hint=" ..." />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Edad"
android:textSize="24sp"
android:textStyle="bold"/>
<EditText
android:id="@+id/editTextEdad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:maxLength="2"
android:hint=" ..." />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<TextView
android:id="@+id/textView8"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Sexo"
android:textSize="24sp"
android:textStyle="bold"/>
<Spinner
android:id="@+id/spinnerSexo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:entries="@array/sexo" />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<TextView
android:id="@+id/textView33"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Correo"
android:textSize="24sp"
android:textStyle="bold"/>
Página 105
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<EditText
android:id="@+id/editCorreoPaciente"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textEmailAddress"
android:hint=" ..." />
<Space
android:layout_width="match_parent"
android:layout_height="170dp" />
<TextView
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Nombre Técnico"
android:textSize="24sp"
android:textStyle="bold"/>
<EditText
android:id="@+id/editTextNombreTecnico"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Víctor Manuel Díaz Conejo" />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<TextView
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Correo Técnico"
android:textSize="24sp"
android:textStyle="bold"/>
<EditText
android:id="@+id/editTextCorreoTecnico"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textEmailAddress"
android:text="[email protected]" />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<TextView
android:id="@+id/textView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Teléfono Técnico"
android:textSize="24sp"
Página 106
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
android:textStyle="bold"/>
<EditText
android:id="@+id/editTextTelefonoTecnico"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="phone"
android:text="916875234" />
<Space
android:layout_width="match_parent"
android:layout_height="70dp" />
</LinearLayout>
</ScrollView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/buttonDatosPaciente"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="Registrar Datos" />
</FrameLayout>
</android.support.constraint.ConstraintLayout>
Página 107
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 6: FragmentAudiometria
package com.example.audiometria.ui.main;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;
import com.example.audiometria.R;
import com.example.audiometria.UdpClientThread;
FloatingActionButton fab,grafica;
UdpClientHandler udpClientHandler;
Button butregistrarDato;
double[][]datos;
boolean[][]datosBoolean;
Spinner canal,frecuencia,nivel;
UdpClientThread udpClientThread;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof FragmentAudiometriaListener){
this.listener = (FragmentAudiometriaListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
Página 108
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
for(int x=0;x<(canal.getCount()-1);x++) {
for (int y = 0; y <(frecuencia.getCount()-1); y++) {
datosBoolean[x][y] = false;
datos[x][y] = 0;
}
}
fab = v.findViewById(R.id.fab);
grafica = v.findViewById(R.id.grafica);
udpClientHandler = new UdpClientHandler(this);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
butMasFrec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if
(frecuencia.getSelectedItemPosition()<(frecuencia.getCount()-1))
frecuencia.setSelection(frecuencia.getSelectedItemPosition()+1);
}
});
butMenFrec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (frecuencia.getSelectedItemPosition()>(0))
frecuencia.setSelection(frecuencia.getSelectedItemPosition()-1);
}
});
butMasNiv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (nivel.getSelectedItemPosition()<(nivel.getCount()-
1))
nivel.setSelection(nivel.getSelectedItemPosition()+1);
}
});
Página 109
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
butMenNiv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (nivel.getSelectedItemPosition()>(0))
nivel.setSelection(nivel.getSelectedItemPosition()-1);
}
});
butregistrarDato.setOnClickListener(new View.OnClickListener()
{
@SuppressLint("RestrictedApi")
@Override
public void onClick(View arg0) {
datos[canal.getSelectedItemPosition()][frecuencia.getSelectedItemPosit
ion()] = Double.parseDouble(nivel.getSelectedItem().toString());
datosBoolean[canal.getSelectedItemPosition()][frecuencia.getSelectedIt
emPosition()] = true;
for(int x=0;x<(canal.getCount());x++) {
for (int y = 0; y <(frecuencia.getCount()); y++) {
if(datosBoolean[x][y] == false){
enviar = false;
}
}
}
if(enviar == true){
grafica.setVisibility(View.VISIBLE);
//AQUÍ SE ENVÍA TODO
listener.onDatosIngresados(datos[0],datos[1]);
Snackbar.make(arg0, "Se ha dibujado ya la
gráfica.", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
}
});
//Enviar datos a la Raspberry-Pi
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Snackbar.make(arg0, "Se va a reproducir el tono
indicado", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
Página 110
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
udpClientThread.start();
}
});
}
private void updateState(String state){
}
private void updateRxMsg(String rxmsg){
}
private void clientEnd(){
udpClientThread = null;
fab.setEnabled(true);
}
public static class UdpClientHandler extends Handler {
public static final int UPDATE_STATE = 0;
public static final int UPDATE_MSG = 1;
public static final int UPDATE_END = 2;
private FragmentAudiometria parent;
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_STATE:
parent.updateState((String)msg.obj);
break;
case UPDATE_MSG:
parent.updateRxMsg((String)msg.obj);
break;
case UPDATE_END:
parent.clientEnd();
break;
default:
super.handleMessage(msg);
}
}
}
public interface FragmentAudiometriaListener{
public void onDatosIngresados(double[] datosIzq, double[]
datosDer);
}
}
Página 111
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.PlaceholderFragment">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp"
tools:ignore="MissingConstraints">
<Space
android:layout_width="match_parent"
android:layout_height="25dp" />
<TextView
android:id="@+id/textViewCanal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="Canal"
android:textSize="30sp"
android:textStyle="bold" />
<Spinner
android:id="@+id/spinnerCanal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="35dp"
android:entries="@array/canal" />
<Space
android:layout_width="match_parent"
android:layout_height="25dp" />
<TextView
android:id="@+id/textViewFrecuencia"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="Frecuencia"
android:textSize="30sp"
android:textStyle="bold" />
<FrameLayout
android:layout_width="match_parent"
Página 112
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
android:layout_height="wrap_content">
<android.support.design.widget.FloatingActionButton
android:src="@android:drawable/button_onoff_indicator_on"
android:id="@+id/buttonMenosFreq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:backgroundTint="#003F3D3D"
app:borderWidth="5dp" />
<Spinner
android:id="@+id/spinnerFrecuencia"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@null"
android:entries="@array/frecuencia" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/buttonMasFreq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:clickable="true"
android:src="@android:drawable/ic_input_add"
app:backgroundTint="#8B6D6B6B"
app:borderWidth="5dp"
app:rippleColor="#003F3D3D" />
</FrameLayout>
<Space
android:layout_width="match_parent"
android:layout_height="40dp" />
<TextView
android:id="@+id/textViewNivel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="Nivel"
android:textSize="30sp"
android:textStyle="bold" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.FloatingActionButton
android:id="@+id/buttonMenosNivel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:src="@android:drawable/button_onoff_indicator_on"
app:backgroundTint="#003F3D3D"
app:borderWidth="22dp" />
<Spinner
android:id="@+id/spinnerNivel"
Página 113
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@null"
android:entries="@array/nivel" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/buttonMasNivel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:clickable="true"
android:src="@android:drawable/ic_input_add"
app:backgroundTint="#8B6D6B6B"
app:borderWidth="5dp" />
</FrameLayout>
<Space
android:layout_width="match_parent"
android:layout_height="50dp"/>
<Button
android:id="@+id/buttonRegistrarDato"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Registrar Dato" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="@+id/grafica"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:visibility="invisible"
app:srcCompat="@android:drawable/ic_menu_report_image"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|bottom"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_media_play" />
</FrameLayout>
</LinearLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>
Página 114
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 7: UDPClientThread
package com.example.audiometria;
import android.os.Message;
import com.example.audiometria.ui.main.FragmentAudiometria;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
//DatagramSocket socket;
InetAddress address;
this.canal = canal;
this.frecuencia = frecuencia;
this.nivel = nivel;
this.handler = handler;
}
@Override
public void run() {
running = true;
try {
DatagramSocket socketCanal = new DatagramSocket();
address = InetAddress.getByName(dstAddress);
Página 115
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
double value = 0;
byte[] bufCanal = new byte[8];
ByteBuffer buffer =
ByteBuffer.allocate(bufCanal.length);
buffer.putDouble(value);
DatagramPacket packetCanal =
new DatagramPacket(buffer.array(),
buffer.array().length, address, dstPort1);
socketCanal.send(packetCanal);
}else if(canal.equals("Derecho")){
double value = 1;
byte[] bufCanal = new byte[8];
ByteBuffer buffer =
ByteBuffer.allocate(bufCanal.length);
byte[] output = new byte[8];
long lng = Double.doubleToLongBits(value);
for(int i = 0; i < 8; i++) output[i] = (byte)((lng >>
((i) * 8)) & 0xff);
buffer.putDouble(value);
DatagramPacket packetCanal =
new DatagramPacket(output, output.length,
address, dstPort1);
socketCanal.send(packetCanal);
}
bufferFrecuencia.putDouble(vIntFrecuencia);
DatagramPacket packetFrecuencia =
new DatagramPacket(outputFrec, outputFrec.length,
address, dstPort2);
socketFrecuencia.send(packetFrecuencia);
if(canal.equals("Izquierdo")){
if(vIntFrecuencia==125){
vNominalNivel = 0.0386 * reduc;
}else if(vIntFrecuencia==250){
Página 116
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
bufferNivel.putDouble(vNominalNivel);
DatagramPacket packet =
new DatagramPacket(outputNiv, outputNiv.length,
address, dstPort3);
socketNivel.send(packet);
socketCanal.close();
socketFrecuencia.close();
socketNivel.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Página 117
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 8: FragmentGrafica
package com.example.audiometria.ui.main;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;
import com.example.audiometria.PdfManager;
import com.itextpdf.text.DocumentException;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.DataPointInterface;
import com.jjoe64.graphview.series.LineGraphSeries;
import com.jjoe64.graphview.series.OnDataPointTapListener;
import com.jjoe64.graphview.series.Series;
import com.example.audiometria.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Página 118
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
telefonoTecnico;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof FragmentGraficaListener){
this.listener = (FragmentGraficaListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
InicializarFrecuencias();
InicializarUmbralesEdad();
ListarCanales();
graph.addSeries(mSerie);
graph.addSeries(serieEdad);
graph.getViewport().setScalable(true); // Sirve para hacer
escalable la grafica
graph.getViewport().setXAxisBoundsManual(true);
graph_izq.addSeries(mSerieIzq);
graph_izq.addSeries(serieEdad);
graph_izq.getViewport().setScalable(true); // Sirve para hacer
escalable la grafica
graph_izq.getViewport().setXAxisBoundsManual(true);
Página 119
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
graph_der.addSeries(mSerieDch);
graph_der.addSeries(serieEdad);
graph_der.getViewport().setScalable(true); // Sirve para hacer
escalable la grafica
graph_der.getViewport().setXAxisBoundsManual(true);
graph_der.getGridLabelRenderer().setHorizontalAxisTitle("f[Hz]");
graph.getGridLabelRenderer().setHorizontalAxisTitle("f[Hz]");
graph_izq.getGridLabelRenderer().setHorizontalAxisTitle("f[Hz]");
graph_der.getGridLabelRenderer().setVerticalAxisTitle("SPL[dB]");
graph.getGridLabelRenderer().setVerticalAxisTitle("SPL[dB]");
graph_izq.getGridLabelRenderer().setVerticalAxisTitle("SPL[dB]");
graph.getGridLabelRenderer().setNumHorizontalLabels(4);
graph.getGridLabelRenderer().setVerticalAxisTitleTextSize(20);
graph_der.getGridLabelRenderer().setNumHorizontalLabels(4);
graph_der.getGridLabelRenderer().setVerticalAxisTitleTextSize(20);
graph_izq.getGridLabelRenderer().setNumHorizontalLabels(4);
graph_izq.getGridLabelRenderer().setVerticalAxisTitleTextSize(20);
return v;
}
//HOMBRE = 0
//EDAD: 5-19 = 0
umbralEdad[0][0][0] = 17; //125 Hz
umbralEdad[0][0][1] = 14; //250 Hz
umbralEdad[0][0][2] = 12; //500 Hz
umbralEdad[0][0][3] = 9; //1000 Hz
umbralEdad[0][0][4] = 7; //2000 Hz
umbralEdad[0][0][5] = 8; //4000 Hz
umbralEdad[0][0][6] = 11; //8000 Hz
//EDAD: 20-29 = 1
umbralEdad[0][1][0] = 15; //125 Hz
umbralEdad[0][1][1] = 12; //250 Hz
umbralEdad[0][1][2] = 11; //500 Hz
umbralEdad[0][1][3] = 8; //1000 Hz
umbralEdad[0][1][4] = 6; //2000 Hz
umbralEdad[0][1][5] = 8; //4000 Hz
Página 120
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
umbralEdad[0][1][6] = 8; //8000 Hz
//EDAD: 30-39 = 2
umbralEdad[0][2][0] = 16; //125 Hz
umbralEdad[0][2][1] = 13; //250 Hz
umbralEdad[0][2][2] = 12; //500 Hz
umbralEdad[0][2][3] = 9; //1000 Hz
umbralEdad[0][2][4] = 6; //2000 Hz
umbralEdad[0][2][5] = 13; //4000 Hz
umbralEdad[0][2][6] = 11; //8000 Hz
//EDAD: 40-49 = 3
umbralEdad[0][3][0] = 16; //125 Hz
umbralEdad[0][3][1] = 13; //250 Hz
umbralEdad[0][3][2] = 12; //500 Hz
umbralEdad[0][3][3] = 10; //1000 Hz
umbralEdad[0][3][4] = 7; //2000 Hz
umbralEdad[0][3][5] = 13; //4000 Hz
umbralEdad[0][3][6] = 16; //8000 Hz
//EDAD: 50-59 = 4
umbralEdad[0][4][0] = 18; //125 Hz
umbralEdad[0][4][1] = 15; //250 Hz
umbralEdad[0][4][2] = 15; //500 Hz
umbralEdad[0][4][3] = 14; //1000 Hz
umbralEdad[0][4][4] = 11; //2000 Hz
umbralEdad[0][4][5] = 18; //4000 Hz
umbralEdad[0][4][6] = 25; //8000 Hz
//EDAD: 60-69 = 5
umbralEdad[0][5][0] = 20; //125 Hz
umbralEdad[0][5][1] = 16; //250 Hz
umbralEdad[0][5][2] = 16; //500 Hz
umbralEdad[0][5][3] = 15; //1000 Hz
umbralEdad[0][5][4] = 15; //2000 Hz
umbralEdad[0][5][5] = 29; //4000 Hz
umbralEdad[0][5][6] = 36; //8000 Hz
//EDAD: 70-79 = 6
umbralEdad[0][6][0] = 21; //125 Hz
umbralEdad[0][6][1] = 19; //250 Hz
umbralEdad[0][6][2] = 18; //500 Hz
umbralEdad[0][6][3] = 20; //1000 Hz
umbralEdad[0][6][4] = 26; //2000 Hz
umbralEdad[0][6][5] = 42; //4000 Hz
umbralEdad[0][6][6] = 53; //8000 Hz
//EDAD: 80-90 = 7
umbralEdad[0][7][0] = 25; //125 Hz
umbralEdad[0][7][1] = 21; //250 Hz
umbralEdad[0][7][2] = 22; //500 Hz
umbralEdad[0][7][3] = 22; //1000 Hz
umbralEdad[0][7][4] = 36; //2000 Hz
umbralEdad[0][7][5] = 56; //4000 Hz
umbralEdad[0][7][6] = 67; //8000 Hz
//MUJER = 1
//EDAD: 5-19 = 0
umbralEdad[1][0][0] = 17; //125 Hz
umbralEdad[1][0][1] = 14; //250 Hz
umbralEdad[1][0][2] = 12; //500 Hz
umbralEdad[1][0][3] = 9; //1000 Hz
umbralEdad[1][0][4] = 7; //2000 Hz
Página 121
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
umbralEdad[1][0][5] = 8; //4000 Hz
umbralEdad[1][0][6] = 11; //8000 Hz
//EDAD: 20-29 = 1
umbralEdad[1][1][0] = 15; //125 Hz
umbralEdad[1][1][1] = 12; //250 Hz
umbralEdad[1][1][2] = 11; //500 Hz
umbralEdad[1][1][3] = 8; //1000 Hz
umbralEdad[1][1][4] = 6; //2000 Hz
umbralEdad[1][1][5] = 8; //4000 Hz
umbralEdad[1][1][6] = 8; //8000 Hz
//EDAD: 30-39 = 2
umbralEdad[1][2][0] = 16; //125 Hz
umbralEdad[1][2][1] = 13; //250 Hz
umbralEdad[1][2][2] = 12; //500 Hz
umbralEdad[1][2][3] = 9; //1000 Hz
umbralEdad[1][2][4] = 6; //2000 Hz
umbralEdad[1][2][5] = 13; //4000 Hz
umbralEdad[1][2][6] = 11; //8000 Hz
//EDAD: 40-49 = 3
umbralEdad[1][3][0] = 16; //125 Hz
umbralEdad[1][3][1] = 13; //250 Hz
umbralEdad[1][3][2] = 12; //500 Hz
umbralEdad[1][3][3] = 10; //1000 Hz
umbralEdad[1][3][4] = 7; //2000 Hz
umbralEdad[1][3][5] = 13; //4000 Hz
umbralEdad[1][3][6] = 16; //8000 Hz
//EDAD: 50-59 = 4
umbralEdad[1][4][0] = 18; //125 Hz
umbralEdad[1][4][1] = 15; //250 Hz
umbralEdad[1][4][2] = 15; //500 Hz
umbralEdad[1][4][3] = 14; //1000 Hz
umbralEdad[1][4][4] = 11; //2000 Hz
umbralEdad[1][4][5] = 18; //4000 Hz
umbralEdad[1][4][6] = 25; //8000 Hz
//EDAD: 60-69 = 5
umbralEdad[1][5][0] = 20; //125 Hz
umbralEdad[1][5][1] = 16; //250 Hz
umbralEdad[1][5][2] = 16; //500 Hz
umbralEdad[1][5][3] = 15; //1000 Hz
umbralEdad[1][5][4] = 15; //2000 Hz
umbralEdad[1][5][5] = 29; //4000 Hz
umbralEdad[1][5][6] = 36; //8000 Hz
//EDAD: 70-79 = 6
umbralEdad[1][6][0] = 21; //125 Hz
umbralEdad[1][6][1] = 19; //250 Hz
umbralEdad[1][6][2] = 18; //500 Hz
umbralEdad[1][6][3] = 20; //1000 Hz
umbralEdad[1][6][4] = 26; //2000 Hz
umbralEdad[1][6][5] = 42; //4000 Hz
umbralEdad[1][6][6] = 53; //8000 Hz
//EDAD: 80-90 = 7
umbralEdad[1][7][0] = 25; //125 Hz
umbralEdad[1][7][1] = 21; //250 Hz
umbralEdad[1][7][2] = 22; //500 Hz
umbralEdad[1][7][3] = 22; //1000 Hz
umbralEdad[1][7][4] = 36; //2000 Hz
umbralEdad[1][7][5] = 56; //4000 Hz
umbralEdad[1][7][6] = 67; //8000 Hz
Página 122
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
adaptador.setDropDownViewResource(android.R.layout.simple_spinner_drop
down_item);
canal.setAdapter(adaptador);
canal.setOnItemSelectedListener(new
AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View
view, int pos, long id) {
setCanalGrafica(pos);
if(pos!=0){
Toast.makeText(parent.getContext(), "Seleccionada:
" + parent.getItemAtPosition(pos).toString(),
Toast.LENGTH_SHORT).show();
}
edad = listener.getEdad();
sexo = listener.getSexo();
double edadDouble=0;
if(pos==0){
graph.removeAllSeries();
graph_der.removeAllSeries();
graph_izq.removeAllSeries();
mSerie = new LineGraphSeries<DataPoint>();
graph.addSeries(mSerie);
for(int x=0;x<(frecuencia.length);x++) {
mSerie.appendData(new DataPoint(frecuencia[x],
0), true, 160);
}
}
if(pos==1){
graph.removeAllSeries();
graph_izq.removeAllSeries();
mSerie = new LineGraphSeries<DataPoint>();
serieEdad = new LineGraphSeries<DataPoint>();
mSerieIzq = new LineGraphSeries<DataPoint>();
serieEdad.setColor(Color.RED);
graph.addSeries(mSerie);
Página 123
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
graph.addSeries(serieEdad);
graph_izq.addSeries(serieEdad);
graph_izq.addSeries(mSerieIzq);
double[] datosIzq = listener.getDatosIzq();
for(int x=0;x<(frecuencia.length);x++) {
mSerie.appendData(new DataPoint(frecuencia[x],
datosIzq[x]), true, 160);
mSerieIzq.appendData(new
DataPoint(frecuencia[x], datosIzq[x]), true, 160);
if (sexo != null){
if (sexo.equals("Hombre")){
sexoInt=0;
serieEdad.appendData(new
DataPoint(frecuencia[x], umbralEdad[0][edadInt][x]), true, 160);
}else if (sexo.equals("Mujer")){
sexoInt=1;
serieEdad.appendData(new
DataPoint(frecuencia[x], umbralEdad[1][edadInt][x]), true, 160);
}
}else{
serieEdad.appendData(new
DataPoint(frecuencia[x], 0), true, 160);
}
}
booleanIzq = true;
}
if(pos==2){
graph.removeAllSeries();
graph_der.removeAllSeries();
mSerie = new LineGraphSeries<DataPoint>();
serieEdad = new LineGraphSeries<DataPoint>();
mSerieDch = new LineGraphSeries<DataPoint>();
serieEdad.setColor(Color.RED);
graph.addSeries(mSerie);
graph.addSeries(serieEdad);
graph_der.addSeries(serieEdad);
graph_der.addSeries(mSerieDch);
double[] datosDer = listener.getDatosDer();
for(int x=0;x<(frecuencia.length);x++) {
mSerie.appendData(new DataPoint(frecuencia[x],
datosDer[x]), true, 160);
mSerieDch.appendData(new
DataPoint(frecuencia[x], datosDer[x]), true, 160);
if (sexo != null){
if (sexo.equals("Hombre")){
serieEdad.appendData(new
DataPoint(frecuencia[x], umbralEdad[0][edadInt][x]), true, 160);
}else if (sexo.equals("Mujer")){
serieEdad.appendData(new
DataPoint(frecuencia[x], umbralEdad[1][edadInt][x]), true, 160);
}
}else{
serieEdad.appendData(new
DataPoint(frecuencia[x], 0), true, 160);
}
}
booleanDer = true;
}
Página 124
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
mSerie.setTitle("Paciente");
mSerieDch.setTitle("Paciente");
mSerieIzq.setTitle("Paciente");
serieEdad.setTitle("Media");
// Display the legend.
graph.getLegendRenderer().setVisible(true);
graph_izq.getLegendRenderer().setVisible(true);
graph_izq.getLegendRenderer().setFixedPosition(0,0);
graph_izq.getLegendRenderer().setWidth(250);
graph_der.getLegendRenderer().setVisible(true);
graph_der.getLegendRenderer().setFixedPosition(0,0);
graph_der.getLegendRenderer().setWidth(250);
//Así podemos fijar el eje de la gráfica
graph_der.getViewport().setMinX(125);
graph_der.getViewport().setMaxX(8000);
graph_izq.getViewport().setMinX(125);
graph_izq.getViewport().setMaxX(8000);
graph.getViewport().setMinX(125);
graph.getViewport().setMaxX(8000);
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Página 125
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
butPdf.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageStat
e())) {
ruta = new
File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTO
RY_DOWNLOADS), INVOICES_FOLDER);
if(ruta != null) {
if(!ruta.mkdirs()) {
if(!ruta.exists()) {
}
}
}
}
File fichero = null;
if(ruta != null) {
fichero = new File(ruta, "audiometria_izq.png");
if(fichero.exists()) {
// El fichero ya existe, borrarlo
fichero.delete();
}
fichero = new File(ruta, "audiometria_izq.png");
}
Bitmap bitmap =
Bitmap.createBitmap(graph_izq.getWidth(), graph_izq.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
graph_izq.draw(canvas);
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
output);
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ruta = null;
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageStat
e())) {
ruta = new
File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTO
RY_DOWNLOADS), INVOICES_FOLDER);
if(ruta != null) {
if(!ruta.mkdirs()) {
if(!ruta.exists()) {
}
Página 126
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
}
}
}
fichero = null;
if(ruta != null) {
fichero = new File(ruta, "audiometria_dch.png");
if(fichero.exists()) {
// El fichero ya existe, borrarlo
fichero.delete();
}
fichero = new File(ruta, "audiometria_dch.png");
}
output = null;
try {
output = new
FileOutputStream(fichero.getAbsolutePath(),true);
Bitmap bitmap =
Bitmap.createBitmap(graph_der.getWidth(), graph_der.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
graph_der.draw(canvas);
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
output);
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
nombre = listener.getNombre();
apellidos = listener.getApellidos();
edad = listener.getEdad();
sexo = listener.getSexo();
correoPaciente = listener.getCorreo();
nombreTecnico = listener.getNombreTecnico();
correoTecnico = listener.getCorreoTecnico();
telefonoTecnico = listener.getTelefonoTecnico();
Página 127
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
pdfManager.sendPdfByEmail(FILENAME,correoPaciente,correoTecnico,
getContext());
}
});
}
@Override
public void onResume() {
super.onResume();
}
Página 128
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Space
android:layout_width="match_parent"
android:layout_height="20dp" />
<Spinner
android:id="@+id/spinnerCanalGrafica"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:entries="@array/canalGrafica" />
<Space
android:layout_width="match_parent"
android:layout_height="15dp" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/layout_graph_vista"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:scrollbarAlwaysDrawHorizontalTrack="true"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="horizontal|vertical">
<com.jjoe64.graphview.GraphView
android:id="@+id/graph"
android:layout_width="345dp"
android:layout_height="373dp"
android:layout_gravity="center"
android:visibility="visible" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom">
<Space
android:layout_width="match_parent"
Página 129
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
android:layout_height="80dp" />
<Button
android:id="@+id/buttonPdf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="invisible"
android:text="Generar y Enviar PDF" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_graph_oculta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<Space
android:layout_width="match_parent"
android:layout_height="800dp" />
<com.jjoe64.graphview.GraphView
android:id="@+id/graph_izq"
android:layout_width="350dp"
android:layout_height="373dp"
android:visibility="visible" />
<com.jjoe64.graphview.GraphView
android:id="@+id/graph_der"
android:layout_width="350dp"
android:layout_height="373dp"
android:visibility="visible" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Página 130
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Anexo 9: PdfManager
package com.example.audiometria;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import android.widget.Toast;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
Página 131
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
this.sexo=sexo;
this.frecuencia=frecuencia;
this.datosDer=datosDer;
this.datosIzq=datosIzq;
this.datosIzqEdad=datosIzqEdad;
this.datosDerEdad=datosDerEdad;
this.correoPaciente=correoPaciente;
this.nombreTecnico=nombreTecnico;
this.correoTecnico=correoTecnico;
this.telefonoTecnico=telefonoTecnico;
// Se crea el documento
Document document = new Document();
try {
//Creamos las carpetas en nuestro dispositivo, si existen
las eliminamos.
File fichero = createDirectoryAndFileName();
FileOutputStream ficheroPDF = new
FileOutputStream(fichero.getAbsolutePath());
document.close();
Página 132
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageStat
e())) {
ruta = new
File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTO
RY_DOWNLOADS), APP_FOLDER_NAME);
if(ruta != null) {
if(!ruta.mkdirs()) {
if(!ruta.exists()) {
return null;
}
}
}
}
File fichero = null;
if(ruta != null) {
fichero = new File(ruta, FILENAME);
if(fichero.exists()) {
// El fichero ya existe, borrarlo
fichero.delete();
}
fichero = new File(ruta, FILENAME);
}
return fichero;
}
//PDF library add file metadata function
private void addMetaData(Document document) {
document.addTitle("Audiometría de " + nombre + " " +
apellidos);
document.addKeywords("Audiometria, Raspberry, UPM, PFG");
document.addAuthor("Víctor Manuel Díaz Conejo");
document.addCreator("Víctor Manuel Díaz Conejo");
}
addEmptyLine(preface, 1);
Página 133
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
if(sexo == 0) {
preface.add(new Paragraph("Sexo: Hombre"));
}else if(sexo == 1) {
preface.add(new Paragraph("Sexo: Mujer"));
}
addEmptyLine(preface, 1);
int TABLE_COLUMNS = 4;
//Instaciamos el objeto Pdf Table y creamos una tabla con las
columnas definidas en TABLE_COLUMNS
PdfPTable table = new PdfPTable(TABLE_COLUMNS);// number of
table columns
//Definimos el ancho que corresponde a cada una de las 4
columnas
float[] columnWidths = new float[]{100f, 150f, 150f, 80f};
table.setWidths(columnWidths);
Página 134
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
Página 135
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
cell.setPhrase(new Phrase(String.valueOf(datosCanal[y])));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(cell);
cell.setPhrase(new
Phrase(String.valueOf(datosCanalEdad[y])));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(cell);
cell.setPhrase(new
Phrase(String.valueOf(datosCanalDif[y])));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(cell);
Página 136
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
}
}
//Procedimiento para mostrar el documento PDF generado
public void showPdfFile(String fileName, Context context){
Toast.makeText(context, "Leyendo documento",
Toast.LENGTH_LONG).show();
File ruta = null;
// Así va correctamente la dirección
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageStat
e())) {
ruta = new
File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTO
RY_DOWNLOADS), APP_FOLDER_NAME);
if(ruta != null) {
if(!ruta.mkdirs()) {
if(!ruta.exists()) {
ruta = null;
}
}
}
}
File fichero = null;
if(ruta != null) {
fichero = new File(ruta, fileName);
}
Uri uri;
Intent viewFile = new Intent(Intent.ACTION_VIEW);
uri = FileProvider.getUriForFile(context,
BuildConfig.APPLICATION_ID, fichero);
viewFile.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
viewFile.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
viewFile.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
viewFile.putExtra(Intent.EXTRA_STREAM, uri);
viewFile.setType("application/pdf");
try {
context.startActivity(viewFile);
//startActivity(viewFile);
}
catch (ActivityNotFoundException e) {
Toast.makeText(context, "No Application Available to View
PDF", Toast.LENGTH_SHORT).show();
}
}
//Procedimiento para enviar por email el documento PDF generado
public void sendPdfByEmail(String fileName, String emailTo, String
emailCC, Context context){
File ruta = null;
// Así va correctamente la dirección
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageStat
e())) {
ruta = new
File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTO
RY_DOWNLOADS), APP_FOLDER_NAME);
if(ruta != null) {
if(!ruta.mkdirs()) {
if(!ruta.exists()) {
ruta = null;
}
}
Página 137
Diseño e implementación de un audiómetro con Raspberry Pi
Anexos
}
}
File fichero = null;
if(ruta != null) {
fichero = new File(ruta, fileName);
}
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Audiometría: " +
nombre + " " + apellidos);
emailIntent.putExtra(Intent.EXTRA_TEXT, "Muchas gracias. Esta
es su audiometría, cuídese.");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new
String[]{emailTo});
emailIntent.putExtra(Intent.EXTRA_BCC, new String[]{emailCC});
Uri uri;
uri = FileProvider.getUriForFile(context,
BuildConfig.APPLICATION_ID, fichero);
emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
emailIntent.setType("application/pdf");
context.startActivity(Intent.createChooser(emailIntent, "Send
email using:"));
}
}
Página 138