Diseño de Aplicación para teléfono Android para

UNIVERSIDAD CARLOS III
ESCUELA POLITÉCNICA
Dto. Sistemas Automáticos
Proyecto Fin de Grado
DISEÑO DE APLICACIÓN
PARA MÓVIL MEDIANTE
PLATAFORMA ARDUINO
ADK
Autor: Javier Aldana Corchón
Tutor: Fernando García Fernández
Título: Diseño de Aplicación para Móvil mediante Plataforma Arduino ADK
Autor: Javier Aldana Corchón
Director: Fernando García Fernández
TRIBUNAL
Presidente:
Vocal:
Secretario:
Realizado el acto de defensa y lectura del Proyecto Fin de Grado el día__ de_____ de
2014 en Leganés, en la Escuela Politécnica Superior de la Universidad Carlos III de
Madrid, acuerda otorgarle la CALIFICACIÓN de:
VOCAL
SECRETARIO
PRESIDENTE
Resumen
Este trabajo tiene como objetivo demostrar cómo un teléfono móvil Android puede
controlar las funcionalidades de un robot seguidor de línea. Para ello, el dispositivo
formará parte del Hardware del robot.
Gracias a esto, y siempre a través de software libre, el número de sus elementos
aumentará sustancialmente, así como su capacidad para realizar tareas mucho más
complejas añadiendo otras funcionalidades al robot.
Para ello, se sustituirá la placa controladora del robot por el conocido Arduino ADK, y
se desarrollará una aplicación que se comunique con el Arduino a través de un cable
USB. Desde esta aplicación se podrá mover el robot en dos modos distintos: en modo
siguelíneas y en modo manual, este último utilizando el acelerómetro del móvil y
pudiendo modificar la velocidad del robot. En cualquiera de los dos modos, será posible
visualizar los datos de los sensores del robot.
Gracias a esto se conseguirán varias mejoras. Por una lado, el robot podrá adquirir otras
funcionalidades, como la opción de ser dirigido manualmente además de seguir una
línea, o la de poder visualizar los datos reales de los sensores que tiene robot. Por otra
parte, la aplicación desarrollada podrá utilizarse como base en proyectos futuros para
incorporar otras funcionalidades, hacer al robot más inteligente, utilizar otros elementos
del teléfono o agregar otros sensores.
Abstract
The objective of this study is to demonstrate how an Android mobile phone can control
the functionalities of a line follower robot. For this, the device is going to be part of the
robot hardware.
As a result the elements will increase substantially and it is having the ability to do
more complex tasks. Also, the robot is going to have others functions, always through
free software.
The robot controller board is replaced by Arduino ADK, and an application will be
developed to communicate with the Arduino through a USB cable. The robot will be
moved in two different modes: in Siguelíneas mode and manual mode, the latest is
using the phone's accelerometer. In either case, you may view the data from the sensors
of the robot.
Thanks to these improvements, we will get some improvements. On the one hand, the
robot may get other functionalities, such as the option to be control manually and follow
a line, or being able to view the actual data from sensors. Moreover, the developed
application may be used as according to future projects to incorporate other
functionalities, as do the robot more intelligent, use other elements of the phone or add
sensors to the robot.
Índice
Índice general
Introducción ................................................................................................................................ 10
1.1 Objetivo del Proyecto ........................................................................................................ 12
1.2 Estado del Arte .................................................................................................................. 14
1.2.1 Robótica ..................................................................................................................... 14
1.2.2 Accessory Development Kit( ADK) .......................................................................... 22
Elementos del Sistema ................................................................................................................ 29
2.1 Sensores y actuadores........................................................................................................ 31
2.2 Arduino Mega ADK .......................................................................................................... 37
2.3 Smartphone Android ......................................................................................................... 40
Diseño del Sistema ...................................................................................................................... 42
3.1 Software de Arduino ......................................................................................................... 44
3.1.1 Entorno de Arduino .................................................................................................... 44
3.1.2 Desarrollo del programa ............................................................................................. 46
3.2 Software de Android ......................................................................................................... 58
3.2.1 Entorno de Eclipse + SDK ......................................................................................... 58
3.2.2 Desarrollo de la aplicación ......................................................................................... 64
Pruebas y evaluación ................................................................................................................... 83
4.1 Descripción del entorno de pruebas .................................................................................. 83
4.2 Pruebas realizadas durante el desarrollo del proyecto....................................................... 86
4.3 Pruebas unitarias ............................................................................................................... 87
4.4 Compatibilidad plataformas Android ................................................................................ 89
Conclusiones y líneas futuras ...................................................................................................... 90
5.1 Conclusiones ..................................................................................................................... 90
5.2 Mejoras futuras.................................................................................................................. 91
Presupuesto ................................................................................................................................. 92
Anexos......................................................................................................................................... 95
8.1 ANEXO I: Datasheet Arduino .......................................................................................... 95
8.2 ANEXO II: Códigos deArduino y Android ...................................................................... 97
Bibliografía ............................................................................................................................... 134
6
Índice
Índice de figuras
Figura 1. Estructura de la aplicación ........................................................................................... 13
Figura 2. Tecnologías aplicadas .................................................................................................. 14
Figura 3. Ciencias y tecnologías en la robótica ........................................................................... 15
Figura 4. Elementos de un robot siguelíneas............................................................................... 20
Figura 5. Hardware ADK de Android ......................................................................................... 22
Figura 6. Arquitectura de Android .............................................................................................. 23
Figura 7. ARduino ADK ............................................................................................................. 27
Figura 8. Comunicación Accesorio- dispositivo Android ........................................................... 28
Figura 9. Esquema con los elementos del antiguo Sistema ........................................................ 29
Figura 10. Incorporación del hardware del ADK ....................................................................... 30
Figura 11. Funcionamiento CNY70 ............................................................................................ 31
Figura 12. Estados posibles ......................................................................................................... 32
Figura 13. Esquema del HC- SR04 ............................................................................................. 32
Figura 14. Diagrama de las señales del HC- SR04 ..................................................................... 33
Figura 15. Sistema de acondicionamiento................................................................................... 35
Figura 16. Señales PWM............................................................................................................. 36
Figura 17. Esquema Arduino ADK ............................................................................................. 39
Figura 18. Esquema de un dispositivo móvil .............................................................................. 40
Figura 19. Selección de la tarjeta ADK....................................................................................... 44
Figura 20. Entorno Arduino ........................................................................................................ 45
Figura 21. Monitor Serie ............................................................................................................. 46
Figura 22. Ciclo de vida de un sketch ......................................................................................... 47
Figura 23. Estructura del programa ............................................................................................. 49
Figura 24. Flujograma del programa en Arduino ........................................................................ 50
Figura 25. Contenido del mensaje ............................................................................................... 52
Figura 26. entorno Eclipse .......................................................................................................... 59
Figura 27. Máquina virtual de Android (AVD) .......................................................................... 60
Figura 28. Creación gráfica de archivos.xml .............................................................................. 61
Figura 29. Estructura de un proyecto en Eclipse ......................................................................... 62
Figura 30. Bibliotecas de Android .............................................................................................. 64
Figura 31. Esquema general de la aplicación .............................................................................. 65
Figura 32. representación de un Relative Layout ........................................................................ 66
Figura 33. Ciclo de vida de una actividad ................................................................................... 68
Figura 34. Clase Actividad Principal .......................................................................................... 69
Figura 35. Flujograma de la Actividad Principal ........................................................................ 70
Figura 36. Ciclo de vida de un Bound Service ............................................................................ 71
Figura 37. Diagrama de counicación en un Bound Service utilizando la clase Messenger ........ 72
Figura 38. Librerías utiizadas en el desarrollo del software........................................................ 74
7
Índice
Figura 39. Elementos del Servicio .............................................................................................. 75
Figura 40. Diagrama de la Clase Servicio ................................................................................... 77
Figura 41. Apariencia de la Actividad Cliente ............................................................................ 80
Figura 42. Diagrama de la Clase Cliente..................................................................................... 81
Figura 43. Entorno de pruebas .................................................................................................... 83
Figura 44. Ordenador portátil ...................................................................................................... 84
Figura 45. Aplicación Demokit ................................................................................................... 86
Figura 46. Impresión de los datos del sensor de ultrasonidos en el monitor serie ...................... 88
8
Índice
Índice de tablas
Tabla 1. Ciencias y tecnologías en ............................................................................................... 16
Tabla 2. Clasificación según su estructura .................................................................................. 18
Tabla 3. Clasificación según generación ..................................................................................... 19
Tabla 4. Estados en el sistema seguidor de línea ........................................................................ 21
Tabla 5. Bibliotecas de Android.................................................................................................. 24
Tabla 6. Entorno de ejecución de Android.................................................................................. 25
Tabla 7. Bibliotecas JAVA.......................................................................................................... 26
Tabla 8. Funcionamiento CNY70 ............................................................................................... 31
Tabla 9. Características HC- SR04 ............................................................................................. 34
Tabla 10. Sensor LDR ................................................................................................................. 34
Tabla 11. Servomotor Futaba S3003 ........................................................................................... 35
Tabla 12. Interruptor RL6 ........................................................................................................... 37
Tabla 13. Puertos necesarios ....................................................................................................... 38
Tabla 14. Especificaciones Arduino............................................................................................ 39
Tabla 15. Especificaciones Huawei Y300................................................................................... 41
Tabla 16. Protocolo del mensaje ................................................................................................. 52
Tabla 17. Protocolo del mensaje ................................................................................................. 58
Tabla 18. Carpetas de un proyecto en Android ........................................................................... 63
Tabla 19. Métodos de una actividad............................................................................................ 69
Tabla 20. Características del Huawei Ascend Y300 ................................................................... 84
Tabla 21. Características del Smartphone BQ Aquaris 5.7 ......................................................... 85
Tabla 22. Robot del laboratorio................................................................................................... 85
Tabla 23. Fases de la memoria .................................................................................................... 92
Tabla 24. Coste mano de obra ..................................................................................................... 93
Tabla 25. Coste de material ......................................................................................................... 93
Tabla 26. Coste total ................................................................................................................... 94
9
Introducción
Capítulo 1
Introducción
El término robótica fue acuñado por Isaac Asimov para describir la tecnología de los
robots.
Procede de las palabras checas robota ( trabajo forzado) y robotnik (sirviente) y fueron
usadas por primera vez en 1921 por el escritor checo Karel Capek, en la obra de teatro
Rossum’s Universal Robot (R.U.R.), en la que se hacía referencia a un humanoide
mecánico.
Se entiende por robótica como la rama de la tecnología que se dedica al diseño,
operación, construcción, disposición estructural, manufactura y aplicación de los robots.
La historia de la robótica va unida a la construcción de “artefactos” que trataban de
materializar el deseo humano de crear seres a su semejanza y que hicieran algunos
trabajos por ellos.
Los robots han tenido una evolución norme. Los primeros surgieron en el siglo I a. C, y
eran máquinas de vapor o artefactos de fuego. En la actualidad, existen robots que
disponen de alta tecnología y con numerosas funcionalidades, llegando a existir robots
humanoides que caminan de forma bípeda y son capaces de interactuar con personas.
Esta evolución y expansión del mundo de la robótica es debido a que se hace uso de
muchas ciencias y áreas multidisciplinares de la tecnología que también han tenido una
gran evolución y que, si además, se combinan unas con otras, la evolución es todavía
más notable.
Actualmente vivimos en una época donde está ocurriendo una revolución tecnológica,
sobre todo en tecnologías de la información, y éstas también se están empezando a
aplicar en robótica. Un ejemplo de esto es combinar la tecnología que posee un robot
con la de un Smartphone. Los teléfonos móviles han pasado de ser dispositivos de
comunicación por voz a distancia a convertirse en ordenadores potentes con interfaz
gráfica, sensores, actuadores y varios tipos de conectividad.
Parece muy interesante incorporar un Smartphone en robots. Es una forma
relativamente barata de transformar un robot que realiza tareas sencillas en uno mucho
más inteligente, aumentar sus funcionalidades, comunicarlo a otros dispositivos con
conexión inalámbrica o conectarlo directamente a Internet.
Algunas empresas líderes tecnológicas invierten en I+ D sobre tema. Un claro ejemplo
es Google, que ha desarrollado una plataforma para comunicar por medio de la interfaz
10
Introducción
USB dispositivos móviles Android con Arduino , una placa controladora muy utilizada
en robótica.
En este proyecto se utiliza esta plataforma para controlar un robot seguidor de línea y
añadirle algunas funcionalidades.
11
Introducción
1.1 Objetivo del Proyecto
El presente proyecto se mueve el mundo de la robótica y la informática.
Se pretende controlar un robot seguidor de línea con un teléfono Android.
El sistema debe de ser:





De bajo consumo.
Relativamente barato.
Hará uso de software libre.
Uso de hardware conocido y asequible.
Funcionamiento autónomo.
Además:
 El sistema deberá leer datos de los siguientes sensores incorporados en el
robot, e imprimirlos por pantalla.
 Sensor de ultrasonidos.
 Sensores de contacto izquierdo y derecho.
 Sensor de iluminación.
 El robot debe tener dos modos de funcionamiento:


Un modo manual, en el que se puede mover el robot con el
acelerómetro del móvil.
Un modo siguelíneas, en el que el robot se mueva siguiendo una
línea negra sobre un fondo blanco.
 En cualquiera de los dos modos en los que opere el robot, deberá pararse
si choca con algún obstáculo.
Básicamente el del sistema consiste en desarrollar un programa que se
cargará en la placa Arduino y una aplicación desarrollada en Android,
que debe de tener la siguiente estructura:
 Una pantalla principal que de la opción de elegir los dos modos de
funcionamiento: “Modo Manual” y “Modo Siguelíneas”.
12
Introducción
 Una pantalla por cada modo de funcionamiento, que sea capaz de sacar
por pantalla los datos de cada sensor y ordenar al robot que se mueva en
el modo correspondiente.
En la siguiente figura se muestra un esquema general de cómo debe ser la
estructura de la aplicación
Pantalla
principal
Modo Manual
Pantalla Modo
Manual
Modo Siguelíneas
Pantalla Modo
Siguelíneas
Activar Modo Manual
Activar Modo Siguelíneas
Datos de los
sensores
Datos de los
sensores
Figura 1. Estructura de la aplicación
13
Introducción
1.2 Estado del Arte
En este apartado se analiza el contexto en el que está enmarcado el Trabajo de fin de
Grado. Estas son las tecnologías de las que se hará uso en este proyecto:
Robótica
Arduino
Trabajo de
Fin de
Grado
Android
Figura 2. Tecnologías aplicadas
Se explica el concepto de Robótica, entrando más en detalle en el robot seguidor de
líneas. A continuación se hablará del ADK (Accessory Development Kit), plataforma
para desarrolladores con el objetivo de comunicar via USB un arduino Mega ADK y un
teléfono Android.
1.2.1 Robótica
Hay ciertas dificultades a la hora de definir qué es un robot. Las definiciones son muy
dispersas:
“Es un dispositivo reprogramable y multifuncional diseñado
para mover materiales, piezas, herramientas o dispositivos
especializados a través de movimientos programados”
Robot Institute of América, 1979.
14
Introducción
“Un dispositivo automático que realiza funciones que
normalmente se consideran, son o deberían ser realizadas por
humanos”
Diccionario Webster.
“Máquina o ingenio electrónico programable, capaz de
manipular objetos y realizar operaciones antes reservadas sólo a
las personas”
Diccionario de la Real academia
La robótica es la rama de la tecnología que se dedica al diseño,
construcción, operación, disposición estructural, manufacturación y manipulación de los
robots.
En robótica se combinan varias áreas de conocimiento:
Mecánica
Física
Electrónica
Ingeniería
de control
Inteligencia
artificial
Informática
Figura 3. Ciencias y tecnologías en la robótica
15
Introducción
Disciplina
Definición
Aplicaciones en un robot
Estudia el movimiento, el
reposo de los cuerpos y su
evolución en el tiempo debido a
la acción de fuerzas.
• Diseño de todo lo que está
relacionado con la parte física del
robot, como sus eslabones,
articulaciones y actuadores (parte
física).
Sistemas cuyo funcionamiento
se basa en el control de flujo de
electrones
• Sensores.
• Actuadores (parte electrónica).
• Microprocesador.
• Sistema de almacenamiento de
datos (ROM, RAM, memoria
Flash..).
• Conversores A/D y D/A.
Mecánica
Electrónica
Informática
Inteligencia
artificial
Ingeniería
de control
Estudia métodos, procesos y
• Programación del microprocesador
técnicas con el fin de procesar y en lenguajes de programación como
transmitir información y datos
C, C++, Java…
en forma digital.
Área multidisciplinar que,
ayudada de la lógica,
informática y la filosofía
estudia entidades capaces de
razonar por sí mismas imitando
la inteligencia humana.
• Algoritmos genéticos.
• Redes neuronales artificiales.
• Algoritmos de lógica análogos al
pensamiento humano.
• Búsqueda del estado deseado sobre
todos los estados posibles, según las
acciones posibles.
Se basa en el uso de
reguladores para el control de
máquinas y procesos
reduciendo la necesidad de
intervención humana.
• Automatización industrial.
• Control y regulación de cualquier
magnitud física.
• Domótica.
Tabla 1. Ciencias y tecnologías en
16
Introducción
Disciplina
Física
•
Definición
Aplicaciones en un robot
Ciencia que estudia el
comportamiento
y
las
propiedades de la materia y
la energía, así como el
tiempo y el espacio, y las
interacciones entre estos
cuatro elementos. Engloba a
todas
las
disciplinas
anteriores.
• Aparte de las aplicaciones
anteriores, existen otros usos de la
física en robótica como imitar a la
naturaleza en algún aspecto, como
en
forma,
movimiento,
dinamismo, comportamiento, etc.
Clasificación de los robots.
Para la clasificar un robot se atiende principalmente a dos criterios: arquitectura y
evolución.
En base a su arquitectura se pueden dividir en:
Tipo
Poliarticulados
Móviles
Descripción
Son sedentarios y están
estructurados para mover sus elementos
terminales en un determinado espacio de
trabajo con un número limitado de grados
de
libertad (manipuladores y algunos robots
industriales).
Tienen una gran capacidad de
desplazamiento, basados en carros o
plataformas y dotados de un sistema
locomotor de tipo rodante. Siguen su
camino por telemando o guiándose por la
información recibida de su entorno a
través de sus sensores.
17
Ejemplo
Introducción
Tipo
Androides
Ejemplo
Descripción
Intentan reproducir total o parcialmente la
forma y el comportamiento cinemático
del ser
humano. Uno de los aspectos más
complejos de estos robots es la
locomoción bípeda (controlar
dinámicamente el movimiento y mantener
elequilibrio del robot).
Imitan en forma y movimiento de
diversos seres vivos.
Zoomórficos
Híbridos
Industriales
Seguridad y
espacio
De servicios
Aquellos de difícil clasificación cuya
estructura se sitúa en combinación con
alguna de las anteriores (un carro móvil
con un brazo, robot personal
antropomorfo, etc).
Son artilugios mecánicos y electrónicos
destinados a realizar de forma automática
determinados procesos de fabricación o
manipulación.
Relativos al uso de robots en tierra, mar y
aire en misiones de seguridad civil o
militar así como su uso en misiones
espaciales.
Sistemas aplicados en los dominios de la
vida: entornos domésticos y de ocio, en
salud y rehabilitación, en servicios
profesionales y en ambientes peligrosos;
que reproducen acciones de ayuda a los
humanos.
Tabla 2. Clasificación según su estructura
18
Introducción
Si atendemos a su evolución se clasifican de la siguiente manera:
Generación
1ª generación
2ª generación
3ª generación
4ª generación
5ª generación
Descripción
Sistema de control basado en “paradas fijas” mecánicamente
(mecanismos de relojería que mueven las cajas musicales o
los juguetes de cuerda).
El movimiento se controla a través de una secuencia
numérica almacenada en disco o cinta magnética (industria
automotriz).
Utilizan las computadoras para su control y tienen cierta
percepción de su entorno a través del uso de sensores. Con
esta generación se inicia la era de los robots inteligentes y
aparecen los lenguajes de programación.
Robots altamente inteligentes con más y mejores extensiones
sensoriales, para entender sus acciones y captar el mundo
que los rodea. Incorporan conceptos “modélicos” de
conducta.
Actualmente se encuentran en desarrollo. Basarán su
acción principalmente en modelos conductuales establecidos.
Tabla 3. Clasificación según generación
•
Robot siguelíneas
Como ya se comentó en la introducción, en este proyecto se utiliza un robot seguidor
de líneas, al cual se le modificará parte del hardware y el software para el objetivo del
proyecto. A continuación se describe qué función tienen estos robots, su estructura y los
elementos que los componen.
Los robots seguidores de línea, como su propio nombre indica, tienen la misión de
seguir una línea, normalmente de color negra, sobre un tablero blanco. Son robots muy
sencillos, y por este motivo su mayor utilización es en la introducción y aprendizaje en
el mundo de la robótica. Se podría decir que son el “hola mundo” en esta disciplina.
Estos robots pueden variar mucho en funcionalidad. Pueden seguir únicamente una
línea o hacer tareas más complejas como salir de un laberinto, detectar objetos, medir
magnitudes en su entorno, etc. También suelen variar en su estructura. Existen múltiples
diferencias en la forma, en el número de ruedas, tipos de sensores y actuadores,
diferentes placas controladoras…..pero todos tienen en común unas partes básicas:
19
Introducción
Tarjeta de
control
Fuente de
energía
Sensores
Motores
Ruedas
Figura 4. Elementos de un robot siguelíneas
Si se tiene en cuenta la clasificación expuesta anteriormente, un robot seguidor de línea
pertenecería al grupo de los móviles, y de 3ª generación, debido a poseer cierta
percepción del entorno gracias a disponer de sensores y una unidad computacional que
controla sus actuadores (los motores de las ruedas principalmente).

Sistema seguidor de línea
La parte más característica de un robot seguidor de línea es el sistema de
detección de línea compuesto por el sensor de infrarrojos. Es la esencia de este
robot, lo que le diferencia del resto de todos ellos. Aunque se volverá a comentar
más adelante, continuación se expone la idea de cómo funciona este sistema.
Por una parte está el procesamiento de la información del microcontrolador y
cómo actúa en consecuencia. El funcionamiento consta básicamente de cuatro
órdenes:
20
Introducción
Estado
Los dos sensores están sobre la línea
El sensor de la derecha ha salido de la
línea.
Respuesta
El robot acanza con las dos ruedas
El robot gira a la izquierda. Esto se
consigue moviendo la rueda derecha y
parando la izquierda.
El sensor de la izquierda ha salido de la
línea.
Hay que girar a la derecha moviendo la
rueda izquierda y manteniendo la derecha
parada.
Ambas ruedas permanecen paradas.
Los dos sensores están fuera de la línea.
Tabla 4. Estados en el sistema seguidor de línea
La otra parte del sistema tiene que ver con el circuito electrónico capaz de detectar la
línea. El sensor de infrarrojos es el más utilizado por su sencillez y precio. Como
ejemplo, en este proyecto se ha utilizado un sensor CNY70, compuesto por un Led de
infrarrojos (IR) y un fototransistor.
Para detectar la línea negra se utilizan dos sensores de este tipo. El led emite rediación
infrarroja, y el fototransistor es sensible a ella. Si está sobre el color blanco, la radiación
se refleja llegando a ser percibida por el fototransitor. Si, por el contrario, se está sobre
la línea negra, se absorbe la radiación. Utilizando dos sensores se consiguen los cuatro
estados posibles.
Una vez que se ha introducido el concepto de robótica y se ha explicado con más detalle
qué es un robot siguelíneas, se explicará la tecnología que se añadirá al robot, el ADK
de Android.
21
Introducción
1.2.2 Accessory Development Kit( ADK)
El ADK consiste en la implementación y desarrollo de código fuente y hardware para
facilitar la construcción de accesorios Android. Algunos de estos accesorios pueden ser
estaciones de conexión para audio, máquinas de ejercicio, estaciones meteorológicas o
cualquier otro dispositivo de hardware externo que se suma a la funcionalidad de
Android. Se trata de comunicar un teléfono Android con una placa Arduino.
Existen dos versiones: El ADK 2011 y la actualización ADK 212. La principal
diferencia entre las dos versiones es que en el ADK 2011 contiene librerías para la
comunicación a través de un USB host, y en el ADK 2012 se añaden librerías para
comunicarse por medio de Bluetooth. En este proyecto el teléfono irá colocado en el
robot y no es necesaria una comunicación inalámbrica, así que se utilizará el ADK
2011.
Figura 5. Hardware ADK de Android
Este kit de desarrollo tiene un gran potencial en el mundo de la robótica debido a sus
numerosas ventajas y posibles aplicaciones, en las que se profundizará más adelante.
A continuación se explican los componentes del ADK.
•
Dispositivo Android
Android es una pila de software desarrollada para dispositivos móviles que incluye un
sistema operativo, middleware y aplicaciones de usuario.
22
Introducción
Fue adquirido por Google en 2005 y es la primera aparición de Google en el mercado de
la telefonía móvil.
Todas las aplicaciones de Android se programan en lenguaje JAVA y son ejecutadas en
una máquina virtual llamada Dalvik. El núcleo de Android es el Linux 2.6.
Android es un software libre. El objetivo es mejorar el desarrollo de aplicaciones
consiguiendo que funcione en cualquier dispositivo móvil, y que cualquier usuario
tenga la opción de contribuir en el desarrollo o en la resolución de problemas.

Arquitectura
A continuación se explicará cómo está constituida la pila de Android. Cada
una de las capas utiliza los servicios de las capas anteriores y ofrece los
suyos propios a las capas superiores.
Figura 6. Arquitectura de Android
23
Introducción
El núcleo de Android es un kernel (núcleo) de Linux versión 2.6. Proporciona
una capa de abstracción que tiene que acceder a las aplicaciones. Para cada
elemento hardware existe un driver. Esto permite utilizar cualquier elemento del
teléfono.
En la siguiente capa se encuentran las bibliotecas. Están escritas en C++ y
compiladas para la arquitectura hardware de cada teléfono, tarea realizada por
cada fabricante. El objetivo es dar funcionalidad a las aplicaciones para tareas
que se repiten con frecuencia, evitando tener que codificarlas y garantizando que
se llevan a cabo de la forma más eficiente.
Las bibliotecas son las siguientes:
LIBRARIES
Biblioteca
Gestor de superficies
(surface Manager)
OpenGL/SL y SGL.
Librerias graficas 3D
y 2D
Bibliotecas
multimedia
Descripción
Compone imágenes que se muestran posteriormente en las
capas gráficas 2D y 3D de tal forma que facilita la
superposición de elementos, transparencias, animaciones, etc.
Las aplicaciones pueden combinar gráficos en 2 y 3
dimensiones.
Permiten tratar el contenido multimedia
animaciones,etc).
( videos, audio,
Motor web utilizado por el navegador.
Webkit.
Protocolo para comunicarse de forma segura.
-SSL( Secure Sockets
Layer).
Freetype.
SQLite.
Permite trabajar con fuentes tipográficas.
Motor de bases de datos relacionales, disponible para todas
las aplicaciones.
Incluye las cabeceras y funciones del lenguaje C.
Biblioteca C de
sistema(libc).
Tabla 5. Bibliotecas de Android
24
Introducción
En el mismo nivel se encuentra el entorno de ejecución. Aquí se encuentran librerías
con clases de JAVA y la máquina virtual Dalvik.
ANDROID RUNTIME
Biblioteca
Dalvik
Descripción
Diseñada para ejecutar aplicaciones que
son propias de dispositivos móviles y no
de JAVA.
Transforman en .dex donde los comprime
para una mayor optimización.
JAVA
Tabla 6. Entorno de ejecución de Android
Las aplicaciones se ejecutan en su propia instancia, evitando así interferencias entre
ellas, y tienen acceso a todas las bibliotecas y al kernel.
En el siguiente nivel se encuentra las bibliotecas de JAVA que acceden a los recursos a
través de la máquina virtual Dalvik. Se enumeran algunas de ellas a continuación:
APPLICATION FRAMEWORK
Biblioteca
Descripción
Controla el ciclo de vida de las
aplicaciones de Android.
Administrador de actividades
(Activity Manager).
Gestiona las ventanas
de las
aplicaciones y utiliza la librería Surface
Administrador de ventanas
Manager.
(Windows Manager).
Proveedor de contenidos
(Content Provider).
Proporciona servicios para notificar al
usuario cuando requiera su atención, como
activar vibrador, sonidos de alerta, etc.
Administrador de notificaciones
(Notification Manager)
Proporciona servicios para notificar al
usuario cuando requiera su atención, como
activar vibrador, sonidos de alerta, etc.
Administrador de paquetes
(Package Manager)
Las aplicaciones se distribuyen en
paquetes (archivos .apk) que contienen
todos los demás archivos necesarios para
una
aplicación
determinada.
Esta
biblioteca permite obtener información
sobre estos paquetes.
25
Introducción
Bibliotecas
Administrador de telefonía
(Telephone Manager)
Administrador de recursos
(Resource Manager)
Administrador de ubicaciones
(Location Manager)
Administrador de sensores
(sensor Manager)
Descripción
Las aplicaciones se distribuyen en
paquetes (archivos .apk) que contienen
todos los demás archivos necesarios para
una
aplicación
determinada.
Esta
biblioteca permite obtener información
sobre estos paquetes.
Proporciona acceso a todos los elementos
propios de una aplicación que se incluyen
directamente en el código.
Determina la posición geográfica (GPS,
mapas, etc).
Gestiona
el
acelerómetro,
giróscopo,sensor de presión, etc).
Gestiona el sensor de la cámara.
Cámara
Multimedia.
Permite reproducir y visualizar video,
audio e imágenes.
Tabla 7. Bibliotecas JAVA
Por último, en la capa superior están las aplicaciones. Se encuentran tanto
las que tiene Android como las que añada el usuario posteriormente.
Para desarrollar aplicaciones en Android se utiliza el Android Software
Development Kit (SDK de Android). Básicamente es el entorno de
desarrollo Eclipse ( IDE para desarrollar programas en Lenguaje JAVA)
al que se le han añadido las herramientas de desarrollo necesarias para
desarrollar una aplicación en Android. Estas herramientas son:
•
•
•
•
ADT plugin.
Herramientas del SDK de Android.
Herramientas de plataforma de Android.
Android Virtual Device (AVD). Un emulador virtual del sistema
operativo de Android para poder ejecutar las aplicaciones sin usar
el dispositivo.
26
Introducción
•
Placa Arduino ADK
Es una plataforma de hardware y software libre desarrollada para hacer más fácil
el diseño de la parte electrónica en proyectos multidisciplinares. Está basada en
un microcontrolador, un puerto USB host por donde se comunicará con el
dispositivo Android, y un entorno de desarrollo llamado Arduino IDE.
El hardware consiste en un micronotrolador Atmel AVR y puertos de entrada y
salida. A continuación se muestra un esquema de la placa:
Pines de señal PWM
Pines de
comunicación
Serie
Conector PC
E/S digitales
USB HOST
Conector DC
Pines de
alimentación
E/S analógicas
Microcontrolador
Atmega2560
Figura 7. ARduino ADK
El entorno de desarrollo se llama Arduino IDE, hace uso del lenguaje C/ C++ y además
existen unas librerías como herramientas de desarrollo:

Librería USB Host Shield
Es una librería que proporciona la lógica para que la tarjeta USB actúe como
USB host. Esto permite al Arduino iniciar la comunicación con otros
dispositivos USB.
27
Introducción

Librería Android Accessory. Esta librería define cómo enumerar el bus,
encontrar un dispositivo Android conectado compatible con el modo
accesorio y cómo configurar la comunicación del dispositivo.

Librerías útiles para la funcionalidad del ADK
 Librería CapSense. Contiene clases funciones para facilitar el uso de
sensores capacitivos.
 Librería I2C/ TWI. Protocolo para la comunicación mediante cable I2C.
 Librería Servo. Contiene clases y funciones para facilitar el uso de
servomotores en Arduino.
 Librería SPI. Permite la comunicación con dispositivos SPI, actuando el
Arduino como maestro en la comunicación.
 Librería Wire. Permite comunicarse con dispositivos I2C/ TWI.
Existen dos formas de comunicación entre la placa Arduino y el dispositivo móvil: el
modo Host y el modo Accessorio.
Figura 8. Comunicación Accesorio- dispositivo Android
En el modo Host el dispositivo Android actúa como anfitrión en la comunicación. Esto
significa que el dispositivo es el que comprueba continuamente si hay un accesorio
conectado, y el accesorio sólo responde si el dispositivo le hace una petición. También
proporciona alimentación a la placa Arduino. Sin embargo, en el modo Accesorio pasa
lo contrario, es la placa Arduino la que actúa como anfitrión en la comunicación y la
que proporciona alimentación al teléfono. En este proyecto se hará uso del ADK en
modo
accesorio.
28
Elementos del Sistema
Capítulo 2
Elementos del Sistema
En el presente capítulo se identificarán los distintos elementos hardware que componen
el sistema. En la siguiente figura se muestra un esquemático muy general de estos
componentes:
Sensor de
contacto
izquierdo
Sensor de
contacto
derecho
Sensor de
ultrasonidos
Sensor
CNY70
izquierdo
Sensor
CNY70
derecho
E/S
E/S
MICROCONTROLADOR
E/S
Motor rueda
izquierda
Motor rueda
derecha
POWER
Sensor
iluminación
Batería
Figura 9. Esquema con los elementos del antiguo Sistema
Al incorporar la plataforma ADK de Google, la placa controladora del robot es
sustituida por un Arduino ADK conectado vía USB a un dispositivo Android:
29
Elementos del Sistema
Sensor de
contacto
izquierdo
Sensor de
ultrasonidos
Sensor de
contacto
derecho
Sensor
CNY70
izquierdo
Sensor
CNY70
derecho
Motor rueda
izquierda
Motor rueda
derecha
Sensor
iluminación
Batería
Figura 10. Incorporación del hardware del ADK
30
Elementos del Sistema
A continuación se describen todos los componentes representados en el esquema
anterior:
2.1 Sensores y actuadores
 Sensor detector de línea CNY70
Para detectar si el robot está sobre la línea negra se utilizan dos sensores CNY70.
Apariencia
Esquema
eléctrico
acondicionamiento
con
El led IR emite luz infrarroja (longitud de onda que va desde 0.7 hasta 1000
micrómetros). Si el fototransistor recibe esa radiación se comporta como una fuente de
corriente y en la patilla “E” hay 5V . La puerta NOT conectada en serie hace que el
estado final sean 0V. Si por el contrario,el fototransistor no recibe la radiación infrarroja
se comportará como un circuito abierto, en la patilla “E” hay 0V y la tensión a la salida
de la puerta NOT son 5V. La patilla “E” de cada sensor irá conectada a una entrada
digital del Arduino.
Tabla 8. Funcionamiento CNY70
Color blanco
Fototransistor
Led IR
Figura 11. Funcionamiento CNY70
31
Elementos del Sistema
Si se tiene en cuenta que el color blanco refleja radiación y el negro la absorbe, se
deduce que cuando el sensor se encuentra sobre el color blanco, el circuito presenta una
salida de 0V, y cuando está sobre la línea negra la salida es de 5V. Así se consiguen los
dos niveles lógicos.
Utilizando dos sensores contiguos podemos obtener cuatro estados posibles.
Figura 12. Estados posibles
 Sensor de ultrasonidos HC- SR04
Figura 13. Esquema del HC- SR04
Con este sensor el robot puede conocer a la distancia que se encuentra de otros objetos.
32
Elementos del Sistema
El sensor dispone de cuatro patillas:
•
•
•
Vcc y GND. Se corresponden a las patillas de alimentación.
Trigger. Señal de disparo. Conectada a una salida digital del Arduino.
Echo. Señal de rebote. Conectada a una entrada digital.
Este sensor tiene un emisor de ondas de ultrasonidos y un receptor de las mismas.
Calcula el tiempo que hay entre la emisión y la recepción de la onda. La velocidad del
sonido, al ser constante y con un valor conocido (340 m/s) es posible calcular la
distancia mediante esta fórmula:
Distancia= tiempo* velocidad del sonido/2.
A continuación se muestra un diagrama del tiempo de cómo debe de ser el tiempo de
disparo para que el sensor funcione correctamente:
Figura 14. Diagrama de las señales del HC- SR04
En el programa de arduino se ha hecho de esta manera:
delayMicroseconds(10);//tiempo de activación de disparo mínimo del trigger del
HC-SR04 según fabricante
digitalWrite(trigger,LOW);
duracion_microsegundos = pulseIn(echo,HIGH,timeOut);
value= conversion(duracion_microsegundos);// función para convertir tiempo
en distancia
33
Elementos del Sistema
A continuación se muestra una tabla con las principales características:
Voltaje de operación
Corrriente de operación
Frecuencia de emisión
Rango máximo
Rango mínimo
Ángulo de medida
Trigger input signal
Echo output signal
Dimensiones
5 V DC
15 mA
40 KHz
70 cm
2 cm
15 º
10 microsegundos, señal TTL
Input TTL
45*20*15 mm
Tabla 9. Características HC- SR04
 Fotorresistor. Light Dependent Resistor (LDR)
Es una Resistencia que varía su valor en función de los fotones que inciden en su
superficie. Su respuesta espectral se encuentra en el visible, alrededor de los 550 nm, y
no es lineal.
Símbolo
Apariencia
Tabla 10. Sensor LDR
34
Respuesta espectral
Elementos del Sistema
Conexionado:
Figura 15. Sistema de acondicionamiento
La salida Vout se conecta a un pin analógico del Arduino configurado como entrada.
 Servomotores Futaba S3003
Especificaciones
Voltaje: [4.8, 6] V
Corriente máxima: 8 mA
Apariencia
Conexionado
Tabla 11. Servomotor Futaba S3003
Estos servos se emplean para mover las ruedas del robot. Básicamente están formados
por un motor eléctrico, una caja reductora y un circuito de control y están diseñados
para girar en un ángulo máximo de 180º. En la siguiente figura se explica cómo se
consigue:
35
Elementos del Sistema
Figura 16. Señales PWM
Un potenciómetro está sujeto al eje de giro sel servo. De esta forma el circuito de
control sabe en qué posición está en cada momento. La posición deseada se le da al eje
por medio de una señal PWM o de ancho de pulso, que consiste en enviar una señal
con un período constante y un pulso que varía en función del ángulo girado.
En este proyecto se pretende que el robot se mueva a distintas velocidades, así que ha
habido que “trucar” los servos para que, por un lado, giren 360 º y, por otro, que se
pueda controlar la velocidad en lugar de la posición.
El procedimiento consiste en liberar el potenciómetro del eje de giro y colocarlo en el
valor medio de su rango de valores, que correspondería q tener el servo con un ángulo
de 90 º.
Haciendo esto se consigue que el motor gire en varios sentidos. Además, existe un
pequeño rango de ángulo, en torno al punto medio en el que el servo tiene una respuesta
aproximadamente lineal. En el programa de Arduino se expandirá esta pequeña zona de
funcionamiento lineal para el rango de datos del acelerómetro. Así se consigue que la
velocidad de giro varíe en función del ángulo del dato del acelerómetro.
El Arduino posee pines específicos para mandar señales PWM y además proporciona la
librería Servo que simplifica mucho el código necesario para mover el servo.
36
Elementos del Sistema
 Sensor de contacto. Interruptor de fin de carrera RL6
Especificaciones
Conexionado
Apariencia
Señal de medida
Voltaje máx: 250 V
GND
Corriente máxima: 16 A
VCC
GND
VCC
Señal de control
Tabla 12. Interruptor RL6
El robot dispone de dos interruptores, uno a cada lado, para detectar posibles colisiones
contra obstáculos.
El modo de funcionamiento es muy sencillo. Si el interruptor está presionado, en la
patilla de medida habrá 5 V. En caso contrario no habrá tensión. En el Arduino se
conectará en una de sus entradas digitales.
Para evitar que haya un cortocircuito cuando esté presionado, se conecta una resistencia
en serie entre la patilla de medida y la patilla de GND.
2.2 Arduino Mega ADK
En el apartado de “1.1 Objetivos del Proyecto” se comentó que el sistema debería ser
barato, de bajo consumo, hacer uso de software libre y tener un hardware bastante
conocido donde hubiera mucha información en la red para facilitar el desarrollo de
mejoras futuras.
El dispositivo más conocido que cumple estos requisitos es Arduino. Arduino es una
plataforma para desarrollo de productos electrónicos, sobre todo para construir
prototipos.
Arduino cuenta con una gran variedad de modelos con distintas características, así
como “shields” de ampliación para añadir elementos de comunicación y otras
funcionalidades. En este proyecto se utiliza uno de los modelos, el Arduino ADK.
37
Elementos del Sistema
Estos dispositivos son relativamente baratos (a partir de 20 euros, dependiendo del
modelo).
Son de bajo consumo. Pueden ser alimentados por USB, por puerto Jack de 2.1 mm o
por los pines Vin y GND, y la placa trabaja a 5V. Si lo alimentamos con Jack, la tensión
de alimentación deberá ser de entre 7V y 12V aunque pueden operar con alimentaciones
de entre 6V y 20V. Si lo alimentamos a menos de 7V, su pin de potencia para alimentar
otros dispositivos podría entregar menos de 5V y si lo hacemos con más de 12V, la
placa podría sufrir daños.
Es software libre. La página oficial de Arduino (http://www.arduino.cc/) se puede
descargar el IDE de Arduino de forma gratuita para desarrollar programas, además de
utilizar bibliotecas creadas por Arduino u otras que sube la gente a la web. El hardware
también es libre ya que te dan la opción de descargarte los planos de la placa para
imprimirla, incluso mejorarla.
El sistema requiere unos requisitos mínimos que debe cumplir la placa. A continuación
se enumeran:
 Puertos E/S
Entradas
Analógicas
salidas
Total pines
1 para el sensor LDR
1
Dgitales
2 para los
interruptores
1 para el “echo” del
sensor HC- SR04
2 señales PWM para
los servos
1 para el “trigger” del
sensor HC- SR04
6
Tabla 13. Puertos necesarios
Además deberá tener un puerto USB HOST, un pin de alimentación de 5 V y un pin
de GND.
 Puerto de alimentación Jack 2.1 mm
Si el robot es autónomo debe de portar una batería que alimente todos sus
componentes.
El arduino ADK cumple con todos estos requisitos además de aportar otras
características:
38
Elementos del Sistema
Especificaciones
Microcontroller
Input Voltage (recommended)
Input Voltage (limits)
Digital I/O Pins
Analog Input Pins
DC Current per I/O Pin
DC Current for 3.3V Pin
Flash Memory
SRAM
EEPROM
ATmega2560
5V
7- 12 V
54 (of which 15 provide PWM output)
16
40 mA
50 mA
6 KB of which 8 KB used by bootloader
8 KB
4 KB
Clock Speed
USB Host Chip
16 MHz
MAX3421E
Tabla 14. Especificaciones Arduino
Pines de señal PWM
Pines de
comunicación
Serie
E/S digitales
Conector PC
USB HOST
Conector
Jack 2.1 mm
Pines de
alimentación
E/S analógicas
Microcontrolador
Atmega2560
Figura 17. Esquema Arduino ADK
39
Elementos del Sistema
2.3 Smartphone Android
Los robots son sistemas electrónicos móviles que requieren requisitos serios como el
tamaño, el peso, la adaptabilidad al escenario, la robustez y, sobre todo, la alimentación.
La mejor solución que cubre todas estas necesidades es utilizar un teléfono móvil. En
esta figura se muestran los elementos que se incorpora un dispositivo móvil en el robot :
Figura 18. Esquema de un dispositivo móvil
Si además el teléfono tiene un sistema operativo Android se cubren las necesidades
anteriormente citadas, como el bajo consumo y el software libre.
En este proyecto se ha utilizado el Smartphone Huawei Ascend Y 300, del que se
detallan algunas características:
40
Elementos del Sistema
Modelo
Sistema operativo
Banda
Dimensiones
Pantalla
Batería
Memoria interna
Memoria de expansión
Conectividad
Cámara
Peso
Procesador
Otros
Especificaciones
Huawei Ascend Y 300
Android 4.1 (Jelly Bean)
UMTS: 900/2100 - EDGE:
850/900/1800/1900 - HSDPA DL
7.2Mbps / UL 5.76Mbps
124,5 x 63,8 x 11,2mm
4,0" TFT-LCD WVGA. Resolución:
800x480. 16M Colores. CORNING®
GORILLA® GLASS 2
Li-ion 1950 mAh
ROM: 4GB, RAM: 512MB
MicroSD hasta 32GB
Bluetooth 2.1 A2DP, Wi-Fi 802.11 b/g/n,
USB 2.0 High-Speed
5 MP AF, Cámara frontal: 0,3MP FF
130g con batería
Qualcomm MSM8225. 1,0 GHz Doble
Nucleo
GPS/AGPS , Emotion UI 1.0, Sensor de
próximidad, Sensor de luz de ambiente,
arranque en 5 segundos, carga rápida,
DLNA
Tabla 15. Especificaciones Huawei Y300
41
Diseño del Sistema
Capítulo 3
Diseño del Sistema
En el presente capítulo se describe el desarrollo del Sistema, que principalmente es todo
desarrollo software. En la figura de la siguiente página podemos ver una idea general de todo
el sistema, tanto del Hardware como del Software.
42
Diseño del Sistema
Sensor de
contacto
izquierdo
Sensor de
ultrasonidos
Sensor de
contacto
derecho
Sensor
CNY70
izquierdo
Sensor
iluminación
Programa
Arduino
Comunicación
USB
Motor rueda
izquierda
Sensor
CNY70
derecho
Motor rueda
derecha
Batería
App
Android
43
Diseño del Sistema
El desarrollo del software en ADK tiene dos partes bien diferenciadas: la programación
en Arduino y la aplicación en Android.
3.1 Software de Arduino
El programa en Arduino, también llamado “sketch”, usa el lenguaje de programación
C/C++ además de incorporar sus propias librerías, las cuales contienen clases y
métodos para la activación y usos de los puertos del chip.
3.1.1 Entorno de Arduino
El IDE de Arduino es un entorno de desarrollo libre que se puede descargar de
forma gratuita en la web www.arduino.cc. Además , para este proyecto es
necesario descargar e incluir en la carpeta libraries las siguientes carpetas:
 USB_Host_Shield. Librerías correspondientes a los Drivers de la placa
controladora. Todo Hardware siempre tiene unos drives para que sea
reconocido por el sistema operativo.
 AndroidAccessory. Librerías que contienen las clases y métodos para la
comunicación con el dispositivo Android.
Otro aspecto importante es seleccionar la tarjeta en la que cargaremos el programa. Se
hace de la siguiente manera:
Figura 19. Selección de la tarjeta ADK
44
Diseño del Sistema
Una vez hecho esto, se pasará a mostrar los diferentes elementos que componen el IDE
de Arduino:
Verificar código. Si hay fallos se indicará en cuadro de mensajes
Cargar el sketch en el Arduino
Crea un sketch nuevo
Abrir un sketch
Abre el monitor serie que muestra los datos
por pantalla enviados desde Arduino.
También permite enviarle datos
Guardar el sketch
Cuadro de mensajes. Aquí se
muestran los errores de
programación, warnings,
modificaciones…
SKETCH
Número de línea donde se encuentra el cursor
Puerto del Arduino en el que se cargará el sketch
Figura 20. Entorno Arduino
45
Diseño del Sistema
El monitor serie se puede ver en la siguiente figura:
Figura 21. Monitor Serie
3.1.2 Desarrollo del programa
Para programar en Arduino hay que tener en cuenta varias partes:
 En primer lugar, se han de incluir las librerías que se van a utilizar:
 A continuación es buena costumbre dar un nombre a los pines que se
van a usar. Es fácil cometer el error de equivocarse con el número del
pin.
46
Diseño del Sistema
 En esta zona también se declaran variables que se usarán en el programa
como variables globales, constantes o instancias de clases. He aquí
algunos ejemplos:
-
Ahora se pasa a explicar el ciclo de ejecución del programa. Tiene dos
funciones principales y obligatorias:
Figura 22. Ciclo de vida de un sketch
 La función setup(). Se ejecuta siempre que se enciende el
Arduino o se reinicia. En esta función :
En este proyecto el Arduino intercambiará datos con el teléfono, así que
es necesario indicar a la velocidad que se transmitirán esos datos de la
siguiente manera:
47
Diseño del Sistema
Es posible dar valores iniciales a variables u objetos que requieran una
asignación de pines:
Además de haber declarado los pines, es necesario indicar si los
pines son de entrada/ salida.
 La función loop(). Se repite cíclicamente.
Aquí va escrito el cuerpo del programa, lo que hace, y se ejecuta
repetidamente de forma indefinida. En el siguiente apartado se
muestra la estructura y se explica cómo funciona el código que
hay en esta función.
 Después de esta función, se pueden implementar otras funciones
que se requieran en el programa y que son llamadas en la función
loop(). Como ejemplo, la siguiente función tiene que ver con el
sensor de ultrasonidos. La función toma como parámetro el
tiempo que mide el ultrasonidos y devuelve una distancia.
48
Diseño del Sistema

Software de Arduino
En este apartado se explicará el software desarrollado en la rutina principal o
loop, el cual se ejecutará de forma indefinida una vez se cargue a la placa de
Arduino.
En la estructura del programa hay tres partes diferenciadas, y que siguen este
orden:
Establecer conexión con el dispositivo
Leer el mensaje del dispositivo, y según el
contenido de éste, mover el robot en uno de los
dos modos
Leer las entradas de los sensores y enviar la
información en un mensaje al dispositivo
Figura 23. Estructura del programa
A continuación se muestra el flujograma que explica cómo se comporta el
código del programa y se entrará en detalle en las partes del código más
características:
49
Diseño del Sistema
Figura 24. Flujograma del programa en Arduino
50
Diseño del Sistema
•
Detección de dispositivos conectados
Es lo primero que se encuentra en la rutina principal. El loop comienza con una
llamada a la función AndroidAccessory::isConnected() para comprobar si hay
un dispositivo conectado. Si lo hay, actualiza los flujos de entrada y salida entre
el dispositivo y Arduino. Si no detecta ningún dispositivo conectado continua
comprobándolo hasta que haya uno conectado. Esta sentencia se traduce en
código de esta manera:
Para usar la función isConnected() hay que crear un objeto global de la clase
AndroidAccessory:
En la rutina principal llamamos a la función de esta manera:
•
Lectura del mensaje
Una vez que ya está establecida la comunicación hay que leer el mensaje que envía la
aplicación Android, en el caso de que exista.
Para comprobar si se ha recibido un mensaje se utiliza otra función de la clase
AndroidAccessory. Con la función read() se lee el flujo de entrada. Si no hay un
mensaje entrante la función devuelve un 0. Si existe un mensaje lo guarda en msg, un
vector de 6 Bytes, donde posteriormente el programa interpretará esa información. En el
siguiente punto se explica qué significado tienen los mensajes para el programa.
51
Diseño del Sistema
•
Protocolo de mensajes
Eje del acelerómetro
[0]
[1]
Dato
Modo de operación
Como se ha dicho anteriormente, la información proveniente de la
aplicación se guarda en un vector de tipo Byte con 6 posiciones. La
información que guarda y va actualizando el vector en cada ciclo es la
siguiente:
[2]
[3]
[4]
[5]
Figura 25. Contenido del mensaje
Posición
[0]
[1]
De [2] a [5]
Descripción
Posee el modo de operación del
robot.
Dato
0x7. Modo Manual.
Especifica si el dato es la
inclinación correspondiente al eje
y o al eje x del teléfono. Sólo es
necesario si estamos en Modo
manual.
El dato medido por el
acelerómetro en cualquiera de los
dos ejes. Sólo es necesario si
estamos en Modo Manual.
0x1. El dato es la
inclinación del eje X.
0x2. El dato es la
inclinación del eje Y.
Tabla 16. Protocolo del mensaje
52
0x1. Modo Siguelíneas.
Diseño del Sistema
Aclaración. El dato del acelerómetro está almacenado en 4 Bytes. Esto es porque el
acelerómetro mide datos analógicos y los convierte a un valor digital de entero. Si se
almacena ese número directamente en una variable de tipo Byte sólo se guardan los 8
primeros bits, perdiendo la información de los bits restantes. El resultado de esta
operación es que se obtiene un número totalmente erróneo, distinto a la medida real.
Para solucionar este problema se utiliza la técnica de bit-shifting, en la que se representa
el dato en su forma binaria y se almacena en 4 Bytes. Supongamos que se quiere
almacenar el número 300. Su representación binaria es 00000000 00000000 00000001
00101100. La idea es almacenar esta información en 4 bytes, de tal manera que en la
posición [2] haya almacenado el 00000000, en la [3] el 00000000, en la [4] el 00000001
y en la 5 el 00101100. En programación esto se puede seguir usando la siguiente
sentencia:
De este modo se envían los datos correctamente sin perder información.
Para realizar la operación inversa, es decir, convertir la información de los 4 Bytes en
un valor entero, se utiliza el método bitwise AND, y la forma de hacerlo en
programación es la siguiente:
Esta operaciones son utilizadas tanto en el código de la aplicación como en el de
Arduino cuando hay una medida analógica que se quiere enviar, como los datos del
acelerómetro, las medidas del sensor de ultrasonidos o del de iluminación.
•
Decisiones del programa
Dependiendo del mensaje que se reciba, se ejecutará una parte el
programa u otra y, por consiguiente, el robot actuará de diferentes
maneras.
53
Diseño del Sistema
-
Si por ejemplo, el primer valor del vector es el 0x7, se ejecuta la parte
del código correspondiente para mover el robot manualmente. Esto es
con los datos del acelerómetro. En este caso es importante la información
de la siguiente posición del vector, ya que si es 0x1 el dato corresponderá
a la inclinación del eje X del teléfono, y si es 0x2, la del eje Y. El resto
de las posiciones contienen el dato. Véase esto traducido a código.
Según lo explicado anteriormente, este sería el caso del dato de la
inclinación del eje X, cuyos valores máximo y mínimo son 100 y -100.
Este dato se convierte a tipo entero por el método de bitwise AND, y se
realiza una conversión de rango por medio de la función map() para que
los valores estén en el rango donde el servo cambia de velocidad. Las
variables rueda_der y rueda_izq son las velocidades finales con las que
se moverán los servos.
Se realiza la misma operación para el caso del eje Y.
Pero en este caso hay que añadir el siguiente código para que el robot
gire en una dirección u otra, esta vez con velocidad constante:
54
Diseño del Sistema
Finalmente se mueven los servos mediante esta sentencia:
Nótese que el programa está escrito en este orden. En cada vuelta del loop()
sólo se recibe el dato del eje X, el dato del eje Y o ninguno de los dos. Si se
mueven los servos al final del código expuesto el robot se moverá con fluidez
y más continuidad porque se hacen todas las operaciones antes. Si movemos
los servos en otra parte de este código o más de una vez el robot se móvera
con menos realismo, incluso se puede saturar la aplicación.
-
Si, por el contrario, el primer valor del vector corresponde al 0x1, el programa
ejecutará el código del Modo Siguelíneas, saltándose el código anterior y
despreciando el resto de la información del vector.
El código del Modo Siguelíneas es muy sencillo. Se hace una lectura digital de
los sensores de infrarrojos y esos datos se someten a los cuatro casos
posibles, ya explicados en el bloque 2 de la memoria ( Estado del arte). Según
estas posibilidades el robot se moverá para que los sensores estén siempre
dentro de la línea negra.
55
Diseño del Sistema
•
Lectura de sensores y envío de mensajes
Es la última parte del programa. Por los pines del arduino se leen las
medidas de los sensores de contacto (derecho e izquierdo), ultrasonidos e
iluminación; pero no de cualquier manera, sino de la más eficiente para
no colapsar el programa.
Existen dos tipos de medidas:
-
Digitales. Correspondientes a los sensores de contacto. El código es el
siguiente:
Primero se hace una medida digital con la función digitalRead() en la
que se actualiza el estado del sensor de contacto. Después se modifica
una variable booleana según el estado actual para detener el robot o no,
se compara el estado actual con el anterior, y finalmente se manda el
mensaje usando la función write() del Accessory. De este modo, y si se
hace una medición al inicio del programa, cuando el teléfono reciba el
mensaje tendrá la información para saber si el sensor está activado o
desactivado.
Es mejor enviar el mensaje justo después de la medición porque el
Arduino tiene que mandar menos información en cada mensaje y la
aplicación tiene menos datos en cola. Aún así, sólo envía 2 Bytes, uno
para identificar qué sensor es y otro con el valor lógico de ‘0’ o ‘1’.
56
Diseño del Sistema
-
Analógicas. Es la información de los sensores de ultrasonidos e
iluminación. Estos sensores sí que tienen que enviar números enteros que
ocupan más. El Arduino tarda en leer una entrada analógica unos 100
microsegundos. Eso significa que como mucho puede hacer 10,000
medidas en un segundo, pero como hay tres sensores más y también tiene
que enviar la información de datos enteros al final enviará bastantes
menos. Por este motivo, y aprovechando que los sensores de iluminación
y ultrasonidos no requieren una respuesta en frecuencia alta se utiliza la
sentencia switch ( count ++ %10). Utilizando esto se reduce la
frecuencia de lecturas analógicas a la mitad porque en cada vuelta sólo
realiza la lectura de uno de los sensores que están dentro del switch. El
código se muestra a continuación:
57
Diseño del Sistema
Como se aprecia en el código, el protocolo de mensajes es el siguiente:
Posición
Descripción
Identificación del sensor.
[0]
Dato del sensor.
Dato
0x5. Sensor de
iluminación.
0x7. Sensor de
ultrasonidos.
El dato tiene 16 bits.
De [1] a [2]
Tabla 17. Protocolo del mensaje
Por último, llama a la función delay() para que transcurran unos
microsegundos ( 5 en este caso) después de cada vuelta para no colapsar la
comunicación con el dispositivo.
3.2 Software de Android
El desarrollo de la aplicación tiene bastante más complicidad que el sketch de Arduino.
Entre otras cosas, porque la aplicación se ejecuta en un sistema operativo.
 Requisitos de software
Para desarrollar aplicaciones en Android es necesario instalar el Java
Development Kit( JDK) y el ADT Bundle. Este último es un paquete que
contiene el entorno de desarrollo Eclipse con las herramientas del
Software Development Kit (SDK) para poder desarrollar las aplicaciones,
incluso ejecutarlas en una máquina virtual de Android.
3.2.1 Entorno de Eclipse + SDK
Las aplicaciones en Android se escriben en JAVA, lenguaje de programación
orientado a objetos de desarrollo totalmente libre.
58
Diseño del Sistema
A continuación se presenta la apariencia con los elementos que componen el
entorno Eclipse:
Barra de herramientas
Editor de
archivos
Estructura de
Elementos
Ventana de
Breakpoints
y
De la aplicación
depuración
de errores
Ventana de
ejecución
Figura 26. entorno Eclipse
•
Barra de herramientas
Las herramientas más significativas son:
SDK Manager. Esta herramienta permite descargar paquetes que
contienen herramientas, APIS y drivers necesarios para desarrollar una
aplicación en en una versión de Android.
AVD Manager. Es una máquina virtual del sistema operativo
Android para poder cargar y ejecutar las aplicaciones que se desarrollen.
Es una alternativa a cargar la aplicación directamente en el teléfono.
A continuación se muestra la apariencia de la máquina virtual de
Android:
59
Diseño del Sistema
Figura 27. Máquina virtual de Android (AVD)
Debug. Comprueba si la aplicación tiene errores. Si es así, abre la
ventana de breakpoints y depuración de errores. En caso de no tener
errores carga la aplicación al teléfono a través de USB, y si no existe un
dispositivo aconectado abre el AVD Manager para cargarla en la
máquina virtual.
Hace exactamente lo mismo que Debug, pero además ejecuta la
aplicación.
•
Editor de archivos
En esta parte es donde se escribe y modifica el código de la aplicación,
ya sea el de los archivos.java o el de los archivos.xml. Aunque más
adelante se explicarán estos archivos con mayor profundidad, se adelanta
que los archivos.java sólo se pueden modificar cambiando el código,
mientras que los archivos.xml pueden ser modificados cambiando el
código o de forma gráfica.
A continuación se muestra la imagen de la ventana para modificar un
archivo.xml de forma gráfica.
60
Diseño del Sistema
Figura 28. Creación gráfica de archivos.xml
•
Ventana de Breakpoints y depuración de errores
En programación se obtienen todo tipo de errores constantemente. Si el
código es corto es fácil encontrarlos, pero en caso contrario puede ser
muy tedioso. Los breakpoints sirven para ejecutar el código de la
aplicación poco a poco para encontrar los errores de forma más sencilla y
rápida.
•
Ventana de ejecución
Es una ventana donde se ve el proceso de ejecución de la aplicación en
tiempo real. Las pestañas más usadas normalmente son la Consola y el
LogCat, muy útiles para reconocimiento de errores.
•
Estructura de elementos de la aplicación
Está formado por el código fuente escrito en java, un código descriptor
(AndroidManifiest.xml) y los recursos.
El código fuente necesita y hace uso de los recursos de la aplicación para
desarrollar un programa Android completo.
61
Diseño del Sistema
A continuación se muestra una imagen de la estructura del proyecto y
una tabla explicando que contiene cada carpeta:
Figura 29. Estructura de un proyecto en Eclipse
62
Diseño del Sistema
Tabla 18. Carpetas de un proyecto en Android
Además, para desarrollar aplicaciones de ADK está la carpeta xml. Esta
carpeta no se crea por defecto cuando creas un proyecto nuevo. Es
necesario crearla aparte y ubicarla dentro de la carpeta res. Dentro de
esta carpeta hay q crear un fichero.xml llamado accessory_filter, cuyo
código es el siguiente:
63
Diseño del Sistema
Este recurso hay que registrarlo en el AndroidManifiest.xml para que lo
reconozca la aplicación. Si no se hace exactamente de esta forma se
generarán errores cuando se depure la aplicación.
3.2.2 Desarrollo de la aplicación
Antes de profundizar en el código fuente y otros elementos de la estructura es
necesario explicar algunos conceptos básicos relacionados con la programación
en Android.
Para desarrollar una aplicación se hace uso de bibliotecas con superclases.
Figura 30. Bibliotecas de Android
Los elementos más básicos que se pueden encontrar en una aplicación son:
•
•
Activity. Es cada pantalla de la aplicación. Puede contener texto,
botones, entradas de texto, etc. Las actividades pueden realizar multitud
de funciones, interactuar entre ellas o con otros elementos, como los
servicios.
Service. Un servicio ejecuta procesos sin necesidad de ninguna
interacción, no tiene entorno gráfico.
•
BroadcastReceiver. Es un componente que recibe y maneja peticiones
que pueden ser enviadas al sistema u otras aplicaciones. Puede
reaccionar en situaciones de batería baja, incluso usado para abrir otra
aplicación.
•
ContentProvider. El proveedor de contenidos es usado para compartir
datos entre multitud de aplicaciones. Un ejemplo sería el proovedor de
contenidos de los contactos del teléfono, usado por muchas aplicaciones
como whta´s App.
64
Diseño del Sistema
La aplicación está compuesta por un servicio, una actividad principal, una actividad
para el Modo Manual y otra actividad para el Modo siguelíneas. En la siguiente figura
se puede ver un esquema general de cómo es la aplicación y las acciones que realiza.
Servicio
• Establece la comunicación via USB
con el arduino ADK .
• Recibe información de los sensores
del ADK.
• Envía información del acelerómetro al
ADK.
Actividad
principal
•Ejecutar el servicio
Actividad
Modo
Manual
•Utilizar el servicio.
• Parar el servicio.
•Abrir
actividad
Modo Manual.
• Abrir actividad
Modo Siguelíneas.
• Dejar de utilizar el
servicio.
Actividad
Modo
Siguelíneas
•
Utilizar
servicio.
el
•Dejar de utilizar el
servicio.
Las actividades utilizan el servicio para :
• Recibir la información de los sensores y sacarlos por pantalla.
• Enviar información al servicio con el modo de funcionamiento.
Figura 31. Esquema general de la aplicación
65
Diseño del Sistema
3.2.2.1 Actividad principal
Representa la primera pantalla que aparece cuando se ejecuta la aplicación. La
programación de la actividad tiene dos partes diferenciadas:
 Programación del entorno gráfico
La programación del entorno gráfico está escrita en lenguaje xml y el
archivo está dentro de la carpeta Layout. Cada actividad tendrá su propio
Layout en esta carpeta.
Todos los elementos necesarios para construir la parte gráfica están
contenidos en la clase View Group. A continuación se describen los
elementos:
Relative Layout
Botones
Figura 32. representación de un Relative Layout
 Layout. Es la estructura donde se construye la interfaz gráfica.
Existen distintos tipos, como el Relative Layout, en el que se
66
Diseño del Sistema
pueden colocar los objetos con total libertad, sin ningún orden o
restricción obligatoria. Todo Layout tiene unos parámetros, como
el tamaño y la identificación.
 Botones. Su uso es realizar acciones cuando son presionados. Sus
principales parámetros son el tamaño, el texto , la identificación .
El código que crea este entorno gráfico es el siguiente:
En el código fuente se
identifica a este botón por este
nombre
Parámetros de la forma y
alineación con el Layout
El código de los otros tres
botones es igual
 Código fuente
El código fuente está escrito en lenguaje JAVA, y cada actividad es una
clase que está dentro de la carpeta src. Para entender el código es
importante conocer el ciclo de vida que tiene una actividad en Android.

Ciclo de vida de una actividad
Una actividad es una clase que puede contener variables y los
métodos que se quiera, pero tiene que tener unos métodos estipulados
y obligatorios para que se ejecute correctamente la actividad. Cuando
se lanza una actividad el Sistema siempre busca y lee estos métodos
en el mismo orden y sigue siempre el siguiente esquema:
67
Diseño del Sistema
Figura 33. Ciclo de vida de una actividad
68
Diseño del Sistema
A continuación se hace una descripción de estos métodos:
Método
onCreate()
Descripción
Es llamada cuando la actividad es creada por primera vez. Aquí se
crean las vistas, variables estáticas y todo inicialización.
onRestart()
El Sistema la llama después de que la actividad ha sido parada.
onStart()
Llamada siempre antes de que la actividad sea visible por el usuario.
OnResume()
Correspondiente a las tareas que haga la aplicación cuando esté
interactuando con el usuario.
onPause()
Llamada cuando el Sistema tiene otra actividad en primer plano (con
el método onResume()) y esta deja de visualizarse parcialmente. En
esta función pausa todo lo que se estaba haciendo en la función
onResume().
Tabla 19. Métodos de una actividad
No es imprescindible que una actividad tenga todos estos métodos. En la actividad
principal de la aplicación sólo están implementados el onCreate() y el onDestroy(). El
Sistema llama al primero de éstos cuando la aplicación es lanzada y después busca los
siguientes métodos. Si no los encuentra, se queda ejecutando el código de onCreate()
hasta que la actividad sea destruida.

Diagrama de la clase Actividad Principal
Una vez explicado el ciclo de vida se presenta la Clase de la Actividad
Principal:
Figura 34. Clase Actividad Principal
69
Diseño del Sistema
Nota aclaratoria: Un callback es un objeto perteneciente a una clase determinada que
tiene unas funciones obligatorias, diseñado así por Android. Para la programación de los
botones se utiliza un callback que tiene una única función llamada onClick(), y el
Sistema ejecuta el código que hay en esta función cada vez que el botón es pulsado. La
forma de programar esto es escribir el callback y después llamarlo en el método
onCreated() para que se ejecute cada vez que se pulse. He aquí un ejemplo de cómo se
implementa:
Callback de un botón:
Llamada en onCreate():
En este caso cuando se pulsa el botón se llama a la función startService(), que comienza
que ejecuta el servicio.

Flujograma de la Actividad Principal
Figura 35. Flujograma de la Actividad Principal
70
Diseño del Sistema
3.2.2.2 Servicio
La funcionalidad del Servicio en esta aplicación es:
1. Establecer comunicación con el Arduino ADK.
2. Enviar información del acelerómetro y del modo de
funcionamiento al ADK.
3. Recibir información del ADK con los datos de los sensores.
4. Comunicarse con las actividades para saber el modo de
funcionamiento y enviar los datos de los sensores a las
actividades.
Estas tareas se podrían hacer con una actividad. El problema es que el teléfono irá
acoplado en el robot, y si no se interactúa con la actividad ésta será destruida por el
sistema tarde o temprano, eliminándose la comunicación entre el teléfono y el ADK.
Un servicio es un componente de una aplicación que realiza procesos sin necesidad de
que el usuario interactúe con él, no tienen interfaz
gráfica, y se ejecuta en el
Background, así que es mucho menos probable que el Sistema acabe destruyéndolo ya
que los servicios son mucho más prioritarios que las actividades a la hora de eliminar
procesos. Existen servicios con estructuras y funcionalidades diferentes.
En esta aplicación se usará un Bound Service . Su función es ser el servidor de la una
interfaz de comunicación servidor/ cliente. Los clientes, tales como actividades, se
pueden unir al servicio, hacer peticiones, respuestas, intercambio de datos y desunirse
cuando acabe el proceso. El servicio se ejecuta mientras que haya alguna actividad
usándolo, en caso contrario el Sistema destruirá el servicio. A continuación se muestra
el ciclo de vida completo de un Bound Service:
Figura 36. Ciclo de vida de un Bound Service
71
Diseño del Sistema
Además, el servicio usará con las actividades un protocolo de comunicación vía
Messenger. Este protocolo se explica a continuación:
 Comunicación con las actividades
Figura 37. Diagrama de counicación en un Bound Service utilizando la clase Messenger
Tanto el servicio como las actividades que se unan a él pertenecen a la misma
aplicación, no forman parte de aplicaciones diferentes. En la aplicación, las actividades
que se unen al servicio son Modo Manual y Modo Siguelíneas y el proceso es
exactamente igual para cada una de ellas. Siguiendo el sentido del esquema se explica el
proceso a continuación:
1. Un Intent es una petición que un elemento de una aplicación
manda a otro para comunicarse con él. La actividad manda un
Intent al Servicio a través de la función bindService(), la cual
opera de forma muy similar a startService(), explicada en la
Actividad Principal.
2. El servicio se inicia si no se había inicado antes.
3. El servicio contiene la función onBind(), la clase Messenger y
la clase IncomingHandler. La función onBind() recibe el Intent
proveniente de la actividad y crea un objeto de la clase
Messenger.
72
Diseño del Sistema
4. La función onBind() envía a la actividad un objeto de la clase
IBinder, la cual contiene elementos de identificación del servicio
y para el establecimiento de la comunicación.
5. . En la actividad, la función onServiceConnected():
• Recibe el objeto IBinder.
• Crea un objeto Messenger con la información del
IBinder. Ahora la actividad y el servicio ya pueden
comunicarse por medio de sus dos clases Messenger.
• Crea un mensaje con la variable de registro.
• El Messenger envía el mensaje con la función send().
6. El Messenger del servicio recibe el mensaje de registro y se lo
pasa a la clase IncomingHandler.
7. La clase IncomingHandler maneja los mensajes provenientes
de la actividad. Registra como cliente a la actividad y la añade a
un array de la clase Client. Con esta esta clase se mandan
mensajes con los datos de los sensores a la actividad, la cual
también tiene una clase IncomingHandler para recibir los datos
y sacarlos por pantalla.
 Comunicación con la placa Arduino
La comunicación USB es una comunicación asíncrona a través de un cable que tiene
cuatro líneas: dos para la alimentación, una para enviar datos y otra para recibir datos.
En el caso del ADK, tiene un protocolo de comunicación en el que el Arduino es el
maestro ( manda peticiones de conexión ) y el dispositivo Android el esclavo ( sólo
puede responder a peticiones de conexión). Además la alimentación la proporciona el
Arduino.
Los teléfonos Android no están preparados para que se conecten dispositivos con USB
host. Usb Accessory es una librería que permite que estos dispositivos puedan
conectarse al teléfono. Por otro lado, la clase que permite acceder al estado del USB y
comunicarse con dispositivos se llama Usb Manager.
73
Diseño del Sistema
Android Accessory
Android
Usb Manager
USB Host
C/ C++
Usb Host Shield
Android Accessory
Se utilizarán estos dos elementos para establecer la comunicación entre el Arduino y el
teléfono.
Figura 38. Librerías utiizadas en el desarrollo del software
La aplicación debe seguir las siguientes pasos siguiendo este orden:
1. Detectar accesorios (como Arduino) que quieren conectarse al USB del teléfono
y elegir el accesorio con que realmente se quiera establecer conexión.
2. Pide al usuario permiso para comunicarse con el accesorio, si no lo ha obtenido.
3. Intercambia datos con el accesorio a través de una interfaz.
A continuación se expone un esquema general con los elementos de la aplicación que
están relacionados con la comunicación del accesorio:
74
Diseño del Sistema
SISTEMA
ANDROID
Notificación
cuando un
evento en
USB ocurre
Registro para el
evento de USB
BROADCAST
RegisterAccessory()
NTENTI FILTER
DESCRIPTOR
THREAT Y RUNNABLE
OpenAccessory()
INPUT STREAM
OUTPUT STREAM
Figura 39. Elementos del Servicio

Establecimiento de conexión. Función RegisterAccessory()
Un Broadcast Receiver es un elemento de Android capaz de percibir
distintos eventos que ocurren en el teléfono, como una llamada entrante,
batería baja, redes de conexión disponibles, etc. El intento de conexión
de un elemento externo al teléfono a través de USB también es un
evento.
La aplicación utiliza un Broadcast Receiver para saber cuándo se están
intentando conectar al USB. Para eso manda al sistema un registro
especificando que le avise sólo de eventos que ocurran en el USB.
El sistema le enviará todos los eventos que ocurran, pero sólo hay que
establecer conexión con el Arduino del robot. Un Intent Filter es un
75
A P L I C A C I Ó N
RECEIVER
Diseño del Sistema
elemento que filtra todos los intentos de conexión de accesorios y
registra el que responde a la identificación del Arduino del robot. El
código de identificación es el recurso accessory_filter.xml, ubicado en
la carpeta res de la aplicación.

Comunicación con el accesorio. Función OpenAccesory()
Una vez que el servicio reconoce el accesorio con el que se quiere
conectar, crea un File Descriptor con los permisos necesarios para la
comunicación. Este archivo se pasará por referencia a la clase File
Input Stream, la cual es capaz de acceder al buffer de la comunicación y
leer los mensajes.
La aplicación está continuamente recibiendo mensajes a la vez que hace
otros procesos, como mostrar la pantalla, comunicarse con las
actividades, etc. Todas estas tareas por defecto se realizan en el UI
Thread (Proceso de ejecución de interfaz de usuario), también llamado
Thread principal. Si se hacen todas estas tareas en un solo proceso
probablemente la aplicación acabe bloqueándose. Para solucionar este
problema se utiliza la clase Threat. Esta clase es capaz de crear un
proceso de ejecución paralelo al principal. La idea es realizar tareas por
separado, como la comunicación con el Arduino, y que el UI Thread
solamente imprima los datos de los sensores. De este modo se evita que
se colapse. Todo el código que queremos que se ejecute en el hilo
paralelo estará en un Runnable. El Sistema buscará este elemento
cuando iniciemos un Thread en la función openAccessory().
Por otro lado se utiliza la clase Output Stream para enviar los datos del
acelerómetro al Arduino.
76
Diseño del Sistema
Una vez explicado la comunicación del servicio con las actividades y con el accesorio
se muestra la clase Servicio y su diagrama de flujo:
 Diagrama de la Clase Servicio
Figura 40. Diagrama de la Clase Servicio
77
Diseño del Sistema
 Flujograma de la Clase Servicio
78
Diseño del Sistema
79
Diseño del Sistema
3.2.2.3 Actividad Cliente
Esta actividad muestra por pantalla los datos de los sensores. Está compuesta por un
botón para utilizar el servicio llamado “Bind to Service” u otro para dejar de utilizarlo
que se llama “Unbind from Service”. Cuando se une al servicio establece comunicación
(ya explicado cuando se describió el servicio), envía al servicio su variable de
identificación y recibe los datos de los sensores para imprimirlos por pantalla. Sólo se
podrá unir al servicio si este se ha iniciado en la actividad principal.
Las actividades Modo Siguelíneas y Modo Manual son actividades cliente. Esta es la
apariencia de la actividad escrita en lenguaje xml:
Botón para utilizar el servicio
Botón para dejar de utilizar el servicio
Datos de los sensores de contacto
Dato del sensor de iluminación
Dato del sensor de ultrasonidos
Datos del acelerómetro (inclinación en
el eje X y en el eje Y del teléfono)
Figura 41. Apariencia de la Actividad Cliente
A continuación se muestra la clase Cliente:
80
Diseño del Sistema
 Diagrama de la Clase cliente
Figura 42. Diagrama de la Clase Cliente
81
Diseño del Sistema
 Flujograma de la Clase Cliente
82
Pruebas y evaluación
Capítulo 4
Pruebas y evaluación
En este capítulo se describen las pruebas que se han hecho al sistema, con las cuales se
aseguran que los requisitos especificados se han cumplido. Se describe el entorno de
pruebas, y a continuación se detallan las mismas.
4.1 Descripción del entorno de pruebas
El entorno de pruebas consta de un ordenador personal, el robot con el Arduino ADK
incorporado y dos Smartphones.
A continuación se muestra una imagen del mismo y se describen sus elementos:
Figura 43. Entorno de pruebas
83
Pruebas y evaluación
•
Ordenador personal. Sony Vaio VGN- NW21
Figura 44. Ordenador portátil
El ordenador es un componente esencial en las pruebas. Es utilizado para:



•
Cargar la aplicación al Smartphone con el entorno Eclipse.
Cargar el programa de Arduino en la placa ADK .
Proporcionar alimentación a la placa Arduino ADK durante las
pruebas.
Smartphones
Se utilizan dos Smartphones para realizar las pruebas: un Huawei Ascend Y 300
y un BQ Aquaris 5. A continuación se hace una breve descripción de sus
características.
 Huawei Huawei Ascend Y300
Características Descripción
Apariencia
Android
OS,
SO
v4.1 (Jelly Bean)
Dual-core 1 GHz
CPU
Cortex-A5
2.0
Versión USB
Se utiliza en todas las pruebas a
lo largo del desarrollo de la
aplicación.
Además
irá
incorporado en el robot.
Tabla 20. Características del Huawei Ascend Y300
84
Pruebas y evaluación
 BQ Aquaris 5.7
Características
SO
Descripción
Apariencia
Android
4.2
Jelly Bean
Quad
Core
CPU
Cortex A7 7 up
to 1.5 GHz
2.0
Versión USB
Sólo es utilizado para estudiar la
compatibilidad
con
otras
plataformas.
Tabla 21. Características del Smartphone BQ Aquaris 5.7
•
Robot utilizado
Componentes
Placa Arduino ADK
Placa Protoboard
Sensor de ultrasonidos
Sensor de iluminación
Apariencia
Sensor de contacto
Sensor detector de línea
Tabla 22. Robot del laboratorio
85
Pruebas y evaluación
4.2 Pruebas realizadas durante el desarrollo del
proyecto
Cuando se desarrolla software, buscar programas que sirvan de ejemplo o desarrollar la
aplicación por partes es primordial para verificar que se va por buen camino hacia la
solución final. A continuación se describen una serie de pruebas que se hicieron, por
orden cronológico, desde el inicio hasta el resultado final del sistema:
 Se descargó y probró la aplicación “Demokit” desarrollada por Google para el
ADK y disponible en Play Store. Esta aplicación es capaz de leer sensores y
realizar acciones como encender leds o servomotores.
Figura 45. Aplicación Demokit
 Se desarrolló el “hola mundo” del ADK. Fue importante para conocer el
entorno de Eclipse, cómo cargar los programas y la estructura básica de una
aplicación con el ADK. La prueba consistía en encender un diodo Led con el
teléfono.
86
Pruebas y evaluación
 A la aplicación anterior se le fueron añadiendo sensores . En las pruebas la
aplicación se bloqueaba. No era capaz de enviar y recibir información al mismo
tiempo. Hubo que modificar la estructuración de la aplicación y del programa
de Arduino.
 Una vez realizada la prueba del éxito del punto anterior, se desarrolló una
aplicación orientada a la solución final. Las pruebas ayudaron a que el robot se
moviera correctamente, pudiendo modificar su velocidad y recibiendo los datos
de los sensores. Parecía que la solución final estaba muy cerca. Sin embargo, al
probar la aplicación en el robot sucedió que funcionaba correctamente sólo
durante un período de tiempo . Esto es debido a que la aplicación estaba
compuesta por un única actividad, y cuando en una actividad no ha interacción
con un usuario a través de la pantalla el Sistema acaba destruyéndola. Esto
suponía una limitación enorme, que se solucionó dando un giro completo a la
estructura de toda la aplicación, utilizando un “Bound Service”.
 Se hicieron pruebas básicas con el ADK utilizando un “Bound Service” como si
se estuviera en la primera fase de desarrollo. Fue una fase complicada. No había
información sobre la utilización del ADK con servicios en Android. Parece ser
que ésta ha sido la primera vez.
 Desarrollo y pruebas de la aplicación final. A pesar de la falta de información y
la incertidumbre que se crea, el sistema acabó funcionando con éxito. Se
comprobó que era posible utilizar el ADK con este tipo de servicio y se superó
la limitación surgida.
4.3 Pruebas unitarias
Las pruebas unitarias son la forma de comprobar el correcto funcionamiento de cada
módulo que conforma el código aisladamente. Esto asegura que cada uno de los
componentes trabaja como es debido por separado.
87
Pruebas y evaluación
 Pruebas en Arduino. Pruebas tales como la verificación de que se reciben los
datos de los sensores correctamente, o que el robot se detiene cuando se activa
un sensor de contacto. Un ejemplo concreto es la comprobación de que el
sensores de ultrasonidos funciona correctamente. Para esto se imprimen los
valores que recibe el Arduino por el monitor serie:
Figura 46. Impresión de los datos del sensor de ultrasonidos en el monitor serie
 Pruebas en el teléfono. Las principales pruebas que se pueden hacer son las
siguientes:
 Cargar la aplicación al teléfono. Cuando surgen errores en este paso,
generalmente es debido a un problema de versión de Android o errores
relacionado con la programación del entorno gráfico (archivos xml).
 Iniciar servicio y comprobarlo en el gestor de aplicaciones del
dispositivo. En el menú de ajustes Gestor de aplicaciones
aplicaciones ejecutándose, se puede comprobar si el servicio se está
ejecutando. Otra forma de comprobarlo es eligiendo un modo y unirse al
servicio. Si está iniciado se imprirán los valores del acelerómetro ( está
así programado).
88
Pruebas y evaluación
4.4 Compatibilidad plataformas Android
La aplicación se ha desarrollado para una versión de Android 4.1 (Jelly Bean).
Teóricamente esta aplicación ADK puede ser cargada y ejecutada correctamente en
cualquier dispositivo con una versión Android igual o superior. Para comprobarlo, se ha
cargado la aplicación en el Smartphone BQ Aquaris 5.7, con una versión de Android
superior, la 4.2. Efectivamente la aplicación se carga y ejecuta correctamente, hasta el
momento en que se conecta al Arduino. La aplicación empieza a recibir datos y
enseguida se bloquea.
De esta experiencia se puede concluir que una aplicación, desarrollada con el ADK, y
para una versión de Android en concreto, no es compatible con todos los dispositivos
con versiones iguales o superiores.
89
Conclusiones y líneas futuras
Capítulo 5
Conclusiones y líneas futuras
En este capítulo, como autor del proyecto, expresaré mis conclusiones sobre el mismo,
así como posibles mejoras que se podrían implementar en proyectos futuros.
5.1 Conclusiones
Tras el desarrollo del proyecto se deben de sacar algunas conclusiones.
La respuesta final del sistema está en consonancia con los objetivos marcados
desde el principio, llevando a cabo todas las tareas planificadas para la
consecución del mismo. El sistema es capaz de controlar el robot mediante dos
modos de funcionamiento. Uno manual, en el que se puede mover el robot en
cualquier dirección y con velocidades distintas (utilizando el acelerómetro del
móvil), y otro que consiste en que el robot es capaz de seguir una línea oscura
sobre un fondo claro.
Otra funcionalidad que se ha añadido al robot es que sea capaz de pararse si
choca contra un obstáculo y a su vez se active el vibrador del teléfono como
modo de alarma.
Además, el sistema puede leer los datos de los sensores de contacto, ultrasonidos
e iluminación integrados en el robot, y mostrarlos por pantalla en la aplicación.
Conclusions
After the project it is necessary to explain the conclusions.
The result is linked with the principle's objectives, thanks to tasks have been
planned to get the aims. The system is able to control the robot with two modes.
One is the manual mode; you can move the robot with the accelerometer of
the phone. The other way consist on the robot is able to follow a dark line on a
light background
Also, it is reading data from the contact sensors, ultrasonic and light sensor, and
it is be able to display them on screen in the application.
90
Conclusiones y líneas futuras
5.2 Mejoras futuras
En este proyecto se podrían hacer algunas mejoras.
Por un lado, que la aplicación funcionara correctamente con todas las versiones
de Android. En teoría, y según las opciones que te da Eclipse para crear un
proyecto nuevo, la aplicación debería funcionar a partir de la versión de Android
3.1 en adelante, cosa que no es así en la práctica. Una mejora sería hacer una
aplicación que englobara todas las versiones, tanto las anteriores a la versión 3.1
como las posteriores.
Añadir funcionalidades puede ser otro tema interesante. El teléfono móvil tiene,
una unidad de procesamiento potente, varios sensores, una interfaz gráfica y
varias posibilidades de conectividad. El caso es aumentar esas funcionalidades
utilizando los elementos que tiene el teléfono.
Como ejemplo, se podría dotar al robot de visión artificial. Consistiría en añadir
una actividad que procesara las imágenes de la cámara del teléfono con el fin de
detectar obstáculos o un objeto en concreto.
Otro ejemplo es utilizar las comunicaciones disponibles en el teléfono. Se podría
comunicar el dispositivo móvil incorporado en el robot con otro teléfono a
través de Wifi o bluetooth. De esta manera el robot se controlaría de forma
inalámbrica. Otra opción es contratar una tarifa de datos en el teléfono y
conectarlo a Internet. De esta manera se puede controlar el robot desde
prácticamente cualquier lugar del mundo.
91
Presupuesto
Capítulo 6
Presupuesto
En este capítulo, a la hora de calcular el presupuesto se tendrá en cuenta el coste del
material utilizado y el tiempo empleado en las distintas fases del TFG.
Fases/ Tareas. Coste personal
1. Fase de documentación
I.
II.
III.
IV.
V.
Estudio de cómo fucniona el ADK de Google, instalar software y
lebrerías necesarias (10 h).
Estudio del Arduino y del IDE de programación (15 h).
Búsqueda de información y tutoriales de Arduino (30 h).
Estudio de Android y de su entorno de programación Eclipse
(20 h).
Búsqueda de información y tutoriales de Android (30 h).
2. Fase de desarrollo del sistema propuesto
I.
II.
III.
IV.
Elaboración y pruebas de programas básicos(20 h).
Estudio del desarrollo de un servicio en Android (20 h).
Desarrollo del software definitivo del Arduino y la aplicación en
Android (60 h).
Pruebas y correcciones del sistema(50 h).
3. Fase de elaboración de la memoria
I.
II.
Redacción de la memoria(80 h).
Corrección y maquetación(5 h).
Fases
Documentación
Desarrollo del sistema
propuesto
Elaboración de la memoria
TOTAL
Horas
75
150
85
310
Tabla 23. Fases de la memoria
92
Presupuesto
Estimando que el ingeniero encargado del desarrollo del proyecto gane 45 €/ h,
el coste personal es el siguiente:
PERSONAL
COSTE(€/h)
HORAS TRABAJADAS
Ingeniero
45
310
13.950
TOTAL
Tabla 24. Coste mano de obra
Coste de materiales
Todo el software desarrollado en el TFG es “open source”, no es necesario realizar el
pago de ninguna licencia, y el alumnos disponía de un ordenador con “Microdoft
office”.
Software utilizado en el TFG
Microsoft Office 2010
Arduino 1.0.5
Eclipse con herramientas SDK
A continuación se muestra el coste del material que se ha empleado en el proyecto.
COSTE DE MATERIAL
Cantidad
Coste unitario(€)
1
44
1
120
Descripción
Arduino ADK Rev 3
Smartphone
Huawei Ascend Y300
Coste total de material
Importe total(€)
44.00
120
164
Tabla 25. Coste de material
93
Presupuesto
Coste del proyecto
RESUMEN PRESUPUESTO
Descripción
Importe total (€)
13.950
Coste personal
164
Coste de material
2.963,94
Impuestos (IVA 21 %)
17.080,94
Total presupuesto
Tabla 26. Coste total
“El presupuesto total del presente proyecto asciende a la cantidad de DIECISIETE
MIL OCHENTA EUROS CON NOVENTA Y CUATRO CENTIMOS DE EURO”
Leganés, 22 de septiembre de 2014
El ingeniero proyectista
Fdo. Javier Aldana Corchón
94
Anexos
Capítulo 7
Anexos
8.1 ANEXO I: Datasheet Arduino
95
Anexos
96
Anexos
8.2 ANEXO II: Códigos deArduino y Android
Código de Arduino
/////LIBRERÍAS//////
#include <Wire.h>
#include <Max3421e.h>
#include <Usb.h>
#include <AndroidAccessory.h>
#include<Servo.h>
//////VARIABLES//////
#define LIGHT_SENSOR A1
#define SERVO1 3
#define SERVO2 2
#define BUTTON1 A4
#define BUTTON2 A5
Servo servos[2];
//sensor de ultrasonidos
const int trigger = 8;
const int echo = 7;
const unsigned long timeOut = 5884;//Tiempo de espera máximo (para 100cm).
Cálculo: timeOut = ((distancia máxima(cm)/0.017)+1
float distancia_centimetros;
//
97
Anexos
unsigned long duracion_microsegundos;
byte b1,b2;
//variables globales para los servos
int posInDegrees_x;
int posInDegrees_y;
int rueda_der;
int rueda_izq;
//variables globales para los CNY70
int iriPin= 10;
int irdPin= 11;
int irderecho,irizquierdo;
//uint16_t val,val2;
//float value;
boolean contact;
AndroidAccessory acc("uPhyca",
"HelloADK",
"DemoKit Arduino Board",
"1.0",
"http://www.android.com",
"0000000012345678");
void setup();
void loop();
98
Anexos
//////FUNCIONES IMPLEMENTADAS//////
void init_buttons(){
pinMode(BUTTON1,INPUT);
pinMode(BUTTON2,INPUT);
//digitalWrite(BUTTON_1,HIGH);
b1=digitalRead(BUTTON1);
b2=digitalRead(BUTTON2);
}
void init_pins(){
pinMode(iriPin,INPUT);
pinMode(irdPin,INPUT);
}
//////INICIALIZACIÓN//////
void setup()
{
Serial.begin(115200); // 115200 bits por segundo
Serial.print("\r\nStart");
servos[0].attach(SERVO1);
servos[0].write(90);
servos[1].attach(SERVO2);
servos[1].write(90);
contact=false;
99
Anexos
pinMode(trigger,OUTPUT);
pinMode(echo,INPUT);
init_buttons();
init_pins();
acc.powerOn();
}
//////RUTINA PRINCIPAL//////
void loop()
{
byte msg[3];
static byte count = 0;
byte b,c;
if (acc.isConnected()) {
uint16_t val,val2;
float value;
int len = acc.read(msg, sizeof(msg), 1);
if (len > 0) {
if(contact){
100
Anexos
servos[0].write(90);
servos[1].write(90);
}
if(!contact ){
if(msg[0]==0x7){
if(msg[1]==0x1){
posInDegrees_x=((msg[2] & 0xFF) << 24)
+((msg[3] & 0xFF) << 16)
+((msg[4] & 0xFF) << 8)
+((msg[5] & 0xFF));
rueda_der=map(posInDegrees_x,-100,100,78,102);
rueda_izq=map(posInDegrees_x,-100,100,102,78);
}
if(msg[1]==0x2){
posInDegrees_y=((msg[2] & 0xFF) << 24)
+((msg[3] & 0xFF) << 16)
+((msg[4] & 0xFF) << 8)
+((msg[5] & 0xFF));
posInDegrees_y=map(posInDegrees_y,-100,100,78,102);
101
Anexos
}
//así giro el robot hacia la derecha
if(posInDegrees_y <= 80){
//paro rueda derecha
rueda_der=78;
//rueda izquierda al máximo
rueda_izq=90;
}
//giro el robot hacia la izquierda
if(posInDegrees_y >= 92){
//paro rueda izquierda
rueda_izq= 102;
//rueda derecha al máximo
rueda_der=90;
}
servos[0].write(rueda_der);
servos[1].write(rueda_izq);
}
if(msg[0]==0x1){
102
Anexos
irderecho=digitalRead(irdPin);
irizquierdo=digitalRead(iriPin);
if(irderecho==0 && irizquierdo==0){
rueda_der=78;
rueda_izq=102;
}
if(irderecho==1 && irizquierdo==1){
rueda_der=90;
rueda_izq=90;
}
if(irderecho==0 && irizquierdo==1){
rueda_der=90;
rueda_izq=102;
}
if(irderecho==1 && irizquierdo==0){
rueda_der=78;
rueda_izq=90;
}
servos[0].write(rueda_der);
servos[1].write(rueda_izq);
}
}
103
Anexos
contact=false;
}
b = digitalRead(BUTTON1);
//Serial.println(b);
if(b==0){
contact=true;
}
if (b != b1) {
msg[0] = 0x6;
msg[1] = b ? 0 : 1;
acc.write(msg, 3);
b1 = b;
}
c= digitalRead(BUTTON2);
if(c==0){
contact=true;
}
if(c!=b2){
msg[0]=0x9;
msg[1]=c ? 0: 1;
104
Anexos
acc.write(msg,3);
b2=c;
}
switch (count++ % 0x10) {
case 0:
val = analogRead(LIGHT_SENSOR);
msg[0] = 0x5;
msg[1] = val >> 8;
msg[2] = val & 0xff;
acc.write(msg, 3);
break;
case 0x4:
//digitalWrite(trigger,LOW);
//delayMicroseconds(3);//en principio estas dos lineas no hacen falta,
pero las ponemos por seguridad
digitalWrite(trigger,HIGH);
delayMicroseconds(10);//tiempo de activación de disparo mínimo del
trigger del HC-SR04 según fabricante
digitalWrite(trigger,LOW);
duracion_microsegundos = pulseIn(echo,HIGH,timeOut);
value= conversion(duracion_microsegundos);
//hago un cast, convierto value de float a uint16_t
val2=( uint16_t) value;
105
Anexos
//Serial.println(val2);
msg[0]=0x7;
msg[1]=val2>> 8;
msg[2]=val2 & 0xff;
acc.write(msg,3);
break;
}
} else{
servos[0].write(90);
servos[1].write(90);
delay(5);
}
}
/////IMPLEMENTACIÓN DE FUNCIONES//////
float conversion(unsigned long duracion){
float distancia;
distancia = duracion/58.2;// vel_sonido = 340 m/s = 0.034 cm/us -->
dist(cm)=(t/2)*0.034=t*0.017
return distancia;
}
106
Anexos
Código de la aplicaión en Android
Código fuente escrito en JAVA
La clase MyService
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service implements Runnable{
private static final String TAG = "HelloLED";
private static final String ACTION_USB_PERMISSION =
"com.uphyca.android.app.helloled.action.USB_PERMISSION";
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
private UsbManager mUsbManager;
private UsbAccessory mAccessory;
ParcelFileDescriptor mFileDescriptor;
FileInputStream mInputStream;
FileOutputStream mOutputStream;
107
Anexos
private static boolean isRunning = false;
private static final byte COMMAND_SERVO = 0x7;
private static final byte SERVO_ID_1 = 0x1;
private static final byte SERVO_ID_2=0x2;
private static final byte COMMAND_CONTACT=0x3;
private SensorManager sensorManager;
private Sensor accelerometer;
boolean servo=false;
boolean siguelineas=false;
byte contact;
boolean crash=false;
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent){
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)){
synchronized (this){
UsbAccessory accessory = (UsbAccessory)
intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED,
false)){
openAccessory(accessory);
}else{
Log.d(TAG, "permission denied for accessory " + accessory);
}
mPermissionRequestPending = false;
}
}else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)){
UsbAccessory accessory = (UsbAccessory)
intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null && accessory.equals(mAccessory)){
closeAccessory();
}
}
}
};
private int composeInt(byte hi, byte lo) {
int val = (int) hi & 0xff;
val *= 256;
val += (int) lo & 0xff;
return val;
}
ArrayList<Messenger> mClients = new ArrayList<Messenger>(); // Keeps track of all current
registered clients.
108
Anexos
int mValue = 0; // Holds last value set by a client.
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SET_BYTE_VALUE = 3;
static final int MSG_SERVO_1=4;
static final int MSG_SERVO_2=5;
static final int MSG_LIGHT=6;
static final int MSG_ULTRASONIC=7;
static final int MSG_RIGHT_CONTACT=8;
static final int MSG_LEFT_CONTACT=9;
static final int MSG_REGISTER_CLIENT2=10;
static final int MSG_UNREGISTER_CLIENT2=11;
static final int MSG_CONTACT_VALUE=12;
//6. Recibe el mensaje del client, y el mensaje lo manda al incomingHandler , para que haga
// con el lo que le de la gana
final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we
publish for clients to send messages to IncomingHandler.
// 4. Cuando presiono el botón "bind to the service, se manda una peticion a través de un intent
a
//esta función, onbin(). Esta devuelve una referencia a mMessenger y un dispath callback a la
funcion
//onServiceConnected() en el ServiceConnection para establecer la comunicacion a traves de
un Ibinder
// con el client que se conecte al Service.
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
//7.una vez que hemos recibido el mensaje del Client con esta clase decidimos qué hacemos
con él.
class IncomingHandler extends Handler { // Handler of incoming messages from clients.
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
servo=true;
break;
case MSG_REGISTER_CLIENT2:
mClients.add(msg.replyTo);
siguelineas=true;
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
servo=false;
break;
case MSG_UNREGISTER_CLIENT2:
mClients.remove(msg.replyTo);
siguelineas=false;
break;
109
Anexos
default:
super.handleMessage(msg);
}
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i("MyService", "Service Started.");
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new
Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver, filter);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//sendCommand(siguelineas);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Received start id " + startId + ": " + intent);
sensorManager.registerListener(sensorEventListener, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
//sendCommand(siguelineas);
if (mInputStream != null && mOutputStream != null){
return -1 ;
110
Anexos
}
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
UsbAccessory accessory = (accessories == null ? null : accessories[0]);
if (accessory != null){
if (mUsbManager.hasPermission(accessory)){
openAccessory(accessory);
}else{
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending){
mUsbManager.requestPermission(accessory, mPermissionIntent);
mPermissionRequestPending = true;
}
}
}
}else{
Log.d(TAG, "mAccessory is null");
}
//sendCommand(siguelineas);
return START_STICKY; // run until explicitly stopped.
}
@Override
public void onDestroy() {
closeAccessory();
sensorManager.unregisterListener(sensorEventListener);
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
private void openAccessory(UsbAccessory accessory){
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null){
mAccessory = accessory;
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);
Thread thread = new Thread(null, this, "DemoKit");
thread.start();
Log.d(TAG, "accessory opened");
//enableControls(true);
111
Anexos
}else{
Log.d(TAG, "accessory open fail");
}
}
private void closeAccessory(){
//enableControls(false);
try{
if (mFileDescriptor != null){
mFileDescriptor.close();
}
}catch (IOException e){
}finally{
mFileDescriptor = null;
mAccessory = null;
}
}
private static final int MESSAGE_LIGHT = 3;
private static final int MESSAGE_ULTRASONIC = 4;
private static final int MESSAGE_RIGHT_CONTACT=5;
private static final int MESSAGE_LEFT_CONTACT=6;
protected class LightMsg {
private int light;
public LightMsg(int light) {
this.light = light;
}
public int getLight() {
return light;
}
}
protected class UltrasonicMsg{
private int ultrasonic;
public UltrasonicMsg(int ultrasonic){
this.ultrasonic=ultrasonic;
}
public int getUltrasonic(){
return ultrasonic;
}
}
protected class LeftContactMsg{
private byte value;
public LeftContactMsg(byte value){
this.value = value;
}
public byte getValue(){
return value;
112
Anexos
}
}
protected class RightContactMsg{
private byte value;
public RightContactMsg(byte value){
this.value= value;
}
public byte getValue(){
return value;
}
}
@Override
public void run(){
int ret = 0;
byte[] buffer = new byte[16384];
int i;
while (ret >= 0){
try{
ret = mInputStream.read(buffer);
}catch(IOException e){
break;
}
i = 0;
while (i < ret){
int len = ret - i;
switch (buffer[i]){
case 0x5:
if (len >= 3) {
Message m =
Message.obtain(mHandler, MESSAGE_LIGHT);
m.obj = new
LightMsg(composeInt(buffer[i + 1],
buffer[i + 2]));
mHandler.sendMessage(m);
}
i += 3;
break;
case 0x7:
if(len >= 3){
Message m=Message.obtain(mHandler, MESSAGE_ULTRASONIC);
m.obj = new UltrasonicMsg(composeInt(buffer[i + 1],
113
Anexos
buffer[i + 2]));
mHandler.sendMessage(m);
}
i += 3;
break;
case 0x8:
if(len >= 3){
Message m=Message.obtain(mHandler,
MESSAGE_LEFT_CONTACT);
m.obj = new LeftContactMsg(buffer[i +1]);
mHandler.sendMessage(m);
}
i += 3;
break;
case 0x6:
if(len >= 3){
Message m=Message.obtain(mHandler,
MESSAGE_RIGHT_CONTACT);
m.obj = new RightContactMsg(buffer[i + 1]);
mHandler.sendMessage(m);
}
i += 3;
break;
case 0x9:
if(len >= 3){
Message m=Message.obtain(mHandler,
MESSAGE_LEFT_CONTACT);
m.obj = new LeftContactMsg(buffer[i + 1]);
mHandler.sendMessage(m);
}
i += 3;
break;
default:
Log.d(TAG, "unknown msg: " + buffer[i]);
i = len;
break;
}
}
}
}
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
switch (msg.what){
case MESSAGE_LIGHT:
114
Anexos
LightMsg l = (LightMsg) msg.obj;
//handleLightMessage(MSG_LIGHT,l.light);
handleLightMessage(MSG_LIGHT,l.getLight());
break;
case MESSAGE_ULTRASONIC:
UltrasonicMsg u = (UltrasonicMsg) msg.obj;
//handleLightMessage(MSG_LIGHT,l.light);
handleUltrasonicMessage(MSG_ULTRASONIC,u.getUltrasonic());
break;
case MESSAGE_LEFT_CONTACT:
LeftContactMsg left = (LeftContactMsg) msg.obj;
handleContactMessage(MSG_LEFT_CONTACT,left.getValue());
break;
case MESSAGE_RIGHT_CONTACT:
RightContactMsg right = (RightContactMsg)
msg.obj;
handleContactMessage(MSG_RIGHT_CONTACT,right.getValue());
break;
}
}
};
private void handleLightMessage(int ID,int value){
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain(null, ID, value, 0));
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list
from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
private void handleUltrasonicMessage(int ID,int value){
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain(null, ID, value, 0));
115
Anexos
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list
from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
private void handleContactMessage(int ID, byte value){
for(int i=mClients.size()-1; i>=0; i--){
try{
//send data as a byte
Bundle b= new Bundle();
b.putByte("b1", value);
Message msg=Message.obtain(null, ID);
msg.setData(b);
mClients.get(i).send(msg);
}catch (RemoteException e){
mClients.remove(i);
}
}
}
public static boolean isRunning()
{
return isRunning;
}
private final SensorEventListener sensorEventListener = new SensorEventListener(){
int x_acceleration;
int y_acceleration;
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy){
}
@Override
public void onSensorChanged(SensorEvent event){
x_acceleration = (int)(-event.values[0] * 10);
y_acceleration=(int)(-event.values[1]*10);
//mandar el mensaje al arduino del valor del servo
moveServoCommand(SERVO_ID_1, x_acceleration);
moveServoCommand(SERVO_ID_2, y_acceleration);
116
Anexos
//sendCommand(siguelineas);
//aqi hay q poner el codigo para mandar los valores a la actividad
handleMessageServo(MSG_SERVO_1,x_acceleration);
handleMessageServo(MSG_SERVO_2,y_acceleration);
}
};
public void moveServoCommand(byte target, int value){
byte[] buffer = new byte[6];
if(servo){
buffer[0] = COMMAND_SERVO;
}else if(siguelineas){
buffer[0]=0x1;
}
buffer[1] = target;
buffer[2] = (byte) (value >> 24);
buffer[3] = (byte) (value >> 16);
buffer[4] = (byte) (value >> 8);
buffer[5] = (byte) value;
if (mOutputStream != null){
try{
mOutputStream.write(buffer);
}catch(IOException e){
Log.e(TAG, "write failed", e);
}
}
}
private void handleMessageServo(int ID,int value_servo){
for (int i=mClients.size()-1; i>=0; i--) {
try {
// Send data as an Integer
mClients.get(i).send(Message.obtain(null, ID, value_servo, 0));
} catch (RemoteException e) {
// The client is dead. Remove it from the list; we are going through the list
from back to front so this is safe to do inside the loop.
mClients.remove(i);
}
}
}
117
Anexos
}
La clase MainActivity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button btnStart, btnStop, btnManual, btnLine;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//reconocimiento de los botones con el xml
btnStart = (Button)findViewById(R.id.start_service);
btnStop=(Button)findViewById(R.id.stop_service);
btnManual=(Button)findViewById(R.id.manual_mode);
btnLine=(Button)findViewById(R.id.line_mode);
//Invoco a los callbacks de los botones
btnStart.setOnClickListener(btnStartListener);
btnStop.setOnClickListener(btnStopListener);
btnManual.setOnClickListener(btnManualListener);
btnLine.setOnClickListener(btnLineListener);
}
private OnClickListener btnStartListener = new OnClickListener() {
public void onClick(View v){
startService(new Intent(MainActivity.this, MyService.class));
}
};
private OnClickListener btnStopListener = new OnClickListener() {
public void onClick(View v){
stopService(new Intent(MainActivity.this, MyService.class));
}
};
private OnClickListener btnManualListener= new OnClickListener(){
public void onClick(View v){
118
Anexos
//startActivity(new Intent(MainActivity.this, ManualActivity.class));
startActivity(new Intent(MainActivity.this, LineActivity.class));
}
};
private OnClickListener btnLineListener= new OnClickListener(){
public void onClick(View v){
//startActivity(new Intent(MainActivity.this, LineActivity.class));
startActivity(new Intent(MainActivity.this, ManualActivity.class));
}
};
@Override
public void onDestroy(){
//stopService(new Intent(MainActivity.this, MyService.class));
super.onDestroy();
}
}
La clase ManualActivity
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class ManualActivity extends Activity {
Button btnBind, btnUnbind;
TextView textRightContact, textLeftContact, textLight, textUltrasonic, textServo_x,
textServo_y;
Messenger mService = null;
boolean mIsBound;
119
Anexos
private Vibrator vibrator;
private boolean isVibrating=false;
//lo utilizo para comunicarme con el Service. Aqui recibo lo que el service me manda.
final Messenger mMessenger = new Messenger(new IncomingHandler());
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MyService.MSG_LIGHT:
//String light_value=Integer.toString(msg.getData().getInt("int1"));
textLight.setText("Iluminación: "+ msg.arg1);
break;
case MyService.MSG_ULTRASONIC:
textUltrasonic.setText("ultrasonidos: " + msg.arg1);
break;
case MyService.MSG_SERVO_1:
textServo_x.setText("Eje x : " + msg.arg1);
break;
case MyService.MSG_SERVO_2:
textServo_y.setText("Eje y : " + msg.arg1);
break;
case MyService.MSG_LEFT_CONTACT:
ContactMsg LeftContact=new ContactMsg( msg.getData().getByte("b1"));
textLeftContact.setText(LeftContact.isPressed());
LeftContact.isVibrate();
//sendMessageToService(LeftContact.value);
break;
case MyService.MSG_RIGHT_CONTACT:
//byte RightContactValue=msg.getData().getByte("b1");
ContactMsg RightContact= new ContactMsg(msg.getData().getByte("b1"));
textRightContact.setText(RightContact.isPressed());
RightContact.isVibrate();
//sendMessageToService(RightContact.value);
break;
default:
super.handleMessage(msg);
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
//5. Crea un Messenger y despues se lo asigna a un messenger para que lo envie al service
120
Anexos
public void onServiceConnected(ComponentName className, IBinder service) {
// mService es de tipo Messenger, para mandar mensajes al servicio
mService = new Messenger(service);
// textStatus.setText("Attached.");
try {
Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
//aqui mando el mensaje al Service. el mMessenger del servicio recibirá este mensaje
mService.send(msg);
} catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been unexpectedly disconnected process crashed.
mService = null;
//textStatus.setText("Disconnected.");
}
};
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manual);
btnBind=(Button)findViewById(R.id.btnBind);
btnUnbind=(Button)findViewById(R.id.btnUnbind);
textRightContact=(TextView)findViewById(R.id.right_contact);
textLeftContact=(TextView)findViewById(R.id.left_contact);
textLight=(TextView)findViewById(R.id.light_text);
textUltrasonic=(TextView)findViewById(R.id.ultrasonic_text);
textServo_x=(TextView)findViewById(R.id.x_text);
textServo_y=(TextView)findViewById(R.id.y_text);
vibrator = ((Vibrator) getSystemService(VIBRATOR_SERVICE));
// 3. Llamo a la funcion setOnclickListener() y le paso como referencia la función del paso 2.
btnBind.setOnClickListener(btnBindListener);
btnUnbind.setOnClickListener(btnUnbindListener);
CheckIfServiceIsRunning();
}
private void CheckIfServiceIsRunning() {
//If the service is running when the activity starts, we want to automatically bind to it.
if (MyService.isRunning()) {
doBindService();
}
}
121
Anexos
// 1. este callback se ejecuta cuando presiono el boton "bind to the Service". esta funcion la llamaré
// en onCreate().
private OnClickListener btnBindListener = new OnClickListener() {
public void onClick(View v){
doBindService();
}
};
private OnClickListener btnUnbindListener = new OnClickListener() {
public void onClick(View v){
doUnbindService();
}
};
// 2. esta funcion la utilizo para unirme al servicio. Además pongo una variable a "true"
void doBindService() {
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
//textStatus.setText("Binding.");
}
void doUnbindService() {
if (mIsBound) {
// If we have received the service, and hence registered with it, then now is the time to unregister.
if (mService != null) {
try {
Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
//textStatus.setText("Unbinding.");
}
}
/*
private void sendMessageToService(byte value) {
if (mIsBound) {
if (mService != null) {
try {
Bundle b = new Bundle();
b.putByte("b1",value);
Message msg = Message.obtain(null,MyService.MSG_CONTACT_VALUE) ;
msg.setData(b);
//mClients.get(i).send(msg);
//Message msg = Message.obtain(null, MyService.MSG_CONTACT_VALUE, value, 0);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
}
}
}
}
*/
122
Anexos
@Override
protected void onDestroy() {
super.onDestroy();
try {
doUnbindService();
stopVibrate();
} catch (Throwable t) {
Log.e("MainActivity", "Failed to unbind from the service", t);
}
}
protected class ContactMsg{
private byte value;
String pressed="choque";
String not_pressed="No hay contacto";
public ContactMsg(byte value){
this.value = value;
}
public String isPressed(){
if(value == 1){
return pressed;
}else{
return not_pressed;
}
}
public void isVibrate(){
if(value == 1){
startVibrate();
}else{
stopVibrate();
}
}
}
/*
protected class LeftContactMsg{
private byte value;
String pressed="choque";
String not_pressed="No hay contacto";
public LeftContactMsg(byte value){
this.value = value;
}
public String isPressed(){
if(value == 1){
return pressed;
}else{
return not_pressed;
}
}
public void isVibrate(){
if(value == 1){
startVibrate();
}else{
123
Anexos
stopVibrate();
}
}
}
*/
public void stopVibrate(){
if(vibrator!=null && isVibrating){
isVibrating=false;
vibrator.cancel();
}
}
public void startVibrate(){
if(vibrator!=null && !isVibrating){
isVibrating=true;
vibrator.vibrate(new long[]{0,100,250},0);
}
}
}
La clase LineActivity
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class LineActivity extends Activity {
Button btnBind, btnUnbind;
TextView textRightContact, textLeftContact, textLight, textUltrasonic, textServo_x,
textServo_y;
Messenger mService = null;
boolean mIsBound;
private Vibrator vibrator;
private boolean isVibrating=false;
124
Anexos
//lo utilizo para comunicarme con el Service. Aqui recibo lo que el service me manda.
final Messenger mMessenger = new Messenger(new IncomingHandler());
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MyService.MSG_LIGHT:
//String light_value=Integer.toString(msg.getData().getInt("int1"));
textLight.setText("Iluminación: "+ msg.arg1);
break;
case MyService.MSG_ULTRASONIC:
textUltrasonic.setText("ultrasonidos: " + msg.arg1);
break;
case MyService.MSG_SERVO_1:
textServo_x.setText("Eje x : " + msg.arg1);
break;
case MyService.MSG_SERVO_2:
textServo_y.setText("Eje y : " + msg.arg1);
break;
case MyService.MSG_LEFT_CONTACT:
LeftContactMsg LeftContact=new LeftContactMsg( msg.getData().getByte("b1"));
textLeftContact.setText(LeftContact.isPressed());
LeftContact.isVibrate();
break;
case MyService.MSG_RIGHT_CONTACT:
//byte RightContactValue=msg.getData().getByte("b1");
RightContactMsg RightContact= new RightContactMsg(msg.getData().getByte("b1"));
textRightContact.setText(RightContact.isPressed());
RightContact.isVibrate();
break;
default:
super.handleMessage(msg);
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
//5. Crea un Messenger y despues se lo asigna a un messenger para que lo envie al service
public void onServiceConnected(ComponentName className, IBinder service) {
// mService es de tipo Messenger, para mandar mensajes al servicio
mService = new Messenger(service);
// textStatus.setText("Attached.");
try {
125
Anexos
Message msg = Message.obtain(null, MyService.MSG_REGISTER_CLIENT2);
msg.replyTo = mMessenger;
//aqui mando el mensaje al Service. el mMessenger del servicio recibirá este mensaje
mService.send(msg);
} catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been unexpectedly disconnected process crashed.
mService = null;
//textStatus.setText("Disconnected.");
}
};
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_line);
btnBind=(Button)findViewById(R.id.btnBind);
btnUnbind=(Button)findViewById(R.id.btnUnbind);
textRightContact=(TextView)findViewById(R.id.right_contact);
textLeftContact=(TextView)findViewById(R.id.left_contact);
textLight=(TextView)findViewById(R.id.light_text);
textUltrasonic=(TextView)findViewById(R.id.ultrasonic_text);
textServo_x=(TextView)findViewById(R.id.x_text);
textServo_y=(TextView)findViewById(R.id.y_text);
vibrator = ((Vibrator) getSystemService(VIBRATOR_SERVICE));
// 3. Llamo a la funcion setOnclickListener() y le paso como referencia la función del paso 2.
btnBind.setOnClickListener(btnBindListener);
btnUnbind.setOnClickListener(btnUnbindListener);
CheckIfServiceIsRunning();
}
private void CheckIfServiceIsRunning() {
//If the service is running when the activity starts, we want to automatically bind to it.
if (MyService.isRunning()) {
doBindService();
}
}
// 1. este callback se ejecuta cuando presiono el boton "bind to the Service". esta funcion la llamaré
// en onCreate().
private OnClickListener btnBindListener = new OnClickListener() {
public void onClick(View v){
doBindService();
}
};
126
Anexos
private OnClickListener btnUnbindListener = new OnClickListener() {
public void onClick(View v){
doUnbindService();
}
};
// 2. esta funcion la utilizo para unirme al servicio. Además pongo una variable a "true"
void doBindService() {
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
//textStatus.setText("Binding.");
}
void doUnbindService() {
if (mIsBound) {
// If we have received the service, and hence registered with it, then now is the time to unregister.
if (mService != null) {
try {
Message msg = Message.obtain(null, MyService.MSG_UNREGISTER_CLIENT2);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
//textStatus.setText("Unbinding.");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
doUnbindService();
stopVibrate();
} catch (Throwable t) {
Log.e("MainActivity", "Failed to unbind from the service", t);
}
}
protected class RightContactMsg{
private byte value;
String pressed="choque";
String not_pressed="no hay contacto";
public RightContactMsg(byte value){
this.value = value;
}
public String isPressed(){
if(value == 1){
return pressed;
}else{
return not_pressed;
}
}
public void isVibrate(){
127
Anexos
if(value == 1){
startVibrate();
}else{
stopVibrate();
}
}
}
protected class LeftContactMsg{
private byte value;
String pressed="Hay contacto";
String not_pressed="No hay contacto";
public LeftContactMsg(byte value){
this.value = value;
}
public String isPressed(){
if(value == 1){
return pressed;
}else{
return not_pressed;
}
}
public void isVibrate(){
if(value == 1){
startVibrate();
}else{
stopVibrate();
}
}
}
public void stopVibrate(){
if(vibrator!=null && isVibrating){
isVibrating=false;
vibrator.cancel();
}
}
public void startVibrate(){
if(vibrator!=null && !isVibrating){
isVibrating=true;
vibrator.vibrate(new long[]{0,100,250},0);
}
}
}
Archivos.xml de la parte gráfica de las actividades
128
Anexos
Activity_line.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="@+id/btnBind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Bind to Service" />
<Button
android:id="@+id/btnUnbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_below="@+id/btnBind"
android:layout_marginTop="30dp"
android:text="Unbind from Service" />
<TextView
android:id="@+id/left_contact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/btnUnbind"
android:layout_marginTop="56dp"
android:text="left" />
<TextView
android:id="@+id/light_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="light" />
<TextView
android:id="@+id/ultrasonic_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/light_text"
android:layout_centerHorizontal="true"
android:layout_marginTop="46dp"
android:text="ultrasonic" />
<TextView
129
Anexos
android:id="@+id/x_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/y_text"
android:layout_alignBottom="@+id/y_text"
android:layout_alignParentLeft="true"
android:text="eje x" />
<TextView
android:id="@+id/y_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="42dp"
android:layout_toLeftOf="@+id/right_contact"
android:text="eje y" />
<TextView
android:id="@+id/right_contact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/left_contact"
android:layout_alignBottom="@+id/left_contact"
android:layout_alignParentRight="true"
android:layout_marginRight="26dp"
android:text="right" />
</RelativeLayout>
Activity_manual.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<Button
android:id="@+id/btnBind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Bind to Service" />
<Button
android:id="@+id/btnUnbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
130
Anexos
android:layout_alignParentRight="true"
android:layout_below="@+id/btnBind"
android:layout_marginTop="30dp"
android:text="Unbind from Service" />
<TextView
android:id="@+id/left_contact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/btnUnbind"
android:layout_marginTop="56dp"
android:text="left" />
<TextView
android:id="@+id/light_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="light" />
<TextView
android:id="@+id/ultrasonic_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/light_text"
android:layout_centerHorizontal="true"
android:layout_marginTop="46dp"
android:text="ultrasonic" />
<TextView
android:id="@+id/x_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/y_text"
android:layout_alignBottom="@+id/y_text"
android:layout_alignParentLeft="true"
android:text="eje x" />
<TextView
android:id="@+id/y_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="42dp"
android:layout_toLeftOf="@+id/right_contact"
android:text="eje y" />
<TextView
android:id="@+id/right_contact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/left_contact"
android:layout_alignBottom="@+id/left_contact"
android:layout_alignParentRight="true"
android:layout_marginRight="26dp"
android:text="right" />
131
Anexos
</RelativeLayout>
Activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:gravity="top" >
<Button
android:id="@+id/start_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="31dp"
android:text="start Service" />
<Button
android:id="@+id/stop_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/start_service"
android:layout_marginTop="48dp"
android:text="Stop Service" />
<Button
android:id="@+id/line_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Modo manual" />
<Button
android:id="@+id/manual_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/line_mode"
android:layout_marginTop="60dp"
android:text="Modo siguelíneas" />
</RelativeLayout>
AndroidManifiest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.adk_app"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="12"
132
Anexos
android:targetSdkVersion="16" />
<uses-feature android:name="android.hardware.usb.accessory" />
<uses-feature android:name="android.hardware.sensor.accelerometrer"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
<service android:name="com.example.adk_app.MyService">
</service>
<activity
android:name="com.example.adk_app.ManualActivity"
android:screenOrientation="portrait">
</activity>
<activity
android:name="com.example.adk_app.LineActivity"
android:screenOrientation="portrait">
</activity>
</application>
</manifest>
133
Bibliografía
Capítulo 8
Bibliografía
[1] Javier García Galón. “Aprenda JAVA como si estuviera en primero”.
Tecnun. Campus tecnológico de la universidad de Navarra. Enero 2000.
[2] Mario Bohmer. “Begining Android ADK with Arduino”. Technology in
Action.
[3] Wikipedia. http://es.wikipedia.org/wiki/Rob%C3%B3tica.
[4] Arduino official website. http://www.arduino.cc/.
[5] Foro Arduino. http://forum.arduino.cc/.
[6] Android developers official Website.
http://developer.android.com/index.html.
[7] Foro de programación. http://stackoverflow.com/.
[8] Sitio Web donde se aloja código. https://github.com/.
[9] Documentación sobre el ADK.
http://www.elecfreaks.com/wiki/index.php?title=ADK.
[10]
Arduteka. http://www.arduteka.com/.
[11]
Documentación sobre un BoundService.
http://www.javacodegeeks.com/.
[12]
Tutorial sobre Bound Services utilizano Messenger.
https://www.coursera.org/courses?search=android.
134
Bibliografía
[13]
Tutorial sobre Bound Services.
http://developer.xamarin.com/guides/android/application_fundamentals/s
ervices/part_2_-_bound_services/
[14]
Drivers del SmartPhone Huawei Ascend Y300.
http://singledrivers.blogspot.com.es/2014/01/huawei-ascend-y300-usbdriver-for.html.
[15]
Tutoriales de Android.
http://www.vogella.com/tutorials/android.html.
[16]
Tutorial sobre Bound Services.
http://www.techotopia.com/index.php/Android_Local_Bound_Services_
%E2%80%93_A_Worked_Example#Understanding_Bound_Services
[17]
Tutorial sobre Servicios en Android.
http://androideity.com/2011/11/08/creando-un-servicio-propio-enandroid/.
[18]
Web para descargar libros de Arduino.
http://ebookbrowsee.net/an/android-arduino#.VB9_H_l_vX5.
[19]
Código de Demokit, aplicación de Google.
https://code.google.com/p/android-sourcebrowsing/source/browse/?repo=device--google--accessory-demokit&name=jb-mr1.1-dev#git%2Fapp
[20]
Tutorial sobre el sensor CNY70.
http://www.comohacerturobot.com/Taller/taller-sensorOptico.htm
[21]
Jorge Agudo Martín. “Cronotermostato inteligente con
transmisión vía radio”. TFG. Septiembre 2013.
135