UNIVERSIDAD CARLOS III · siguelíneas y en modo manual, este último utilizando el acelerómetro...

135
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

Transcript of UNIVERSIDAD CARLOS III · siguelíneas y en modo manual, este último utilizando el acelerómetro...

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

6

Í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

Índice

7

Í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

Índice

8

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

Índice

9

Í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

Introducción

10

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

Introducción

11

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.

Introducción

12

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”.

Introducción

13

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

Figura 1. Estructura de la aplicación

Pantalla Modo Manual

Pantalla Modo Siguelíneas

Pantalla principal

Modo Manual

Modo Siguelíneas

Activar Modo Manual Activar Modo Siguelíneas

Datos de los sensores

Datos de los sensores

Introducción

14

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:

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:

Trabajo de Fin de Grado

Robótica

Arduino

Android

“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.

Introducción

15

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:

Figura 3. Ciencias y tecnologías en la robótica

“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

Mecánica

Electrónica

Inteligencia artificial

Informática

Ingeniería de control

Física

Introducción

16

Tabla 1. Ciencias y tecnologías en

Disciplina Definición Aplicaciones en un robot

Mecánica

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).

Electrónica

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.

Informática

Estudia métodos, procesos y técnicas con el fin de procesar y transmitir información y datos en forma digital.

• Programación del microprocesador en lenguajes de programación como C, C++, Java…

Inteligencia artificial

Á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.

Ingeniería de control

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.

Introducción

17

• 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 Descripción Ejemplo

Poliarticulados

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).

Móviles

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.

Disciplina

Definición Aplicaciones en un robot

Física

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.

Introducción

18

Tipo Descripción Ejemplo

Androides

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).

Zoomórficos

Imitan en forma y movimiento de diversos seres vivos.

Híbridos

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).

Industriales

Son artilugios mecánicos y electrónicos destinados a realizar de forma automática determinados procesos de fabricación o manipulación.

Seguridad y espacio

Relativos al uso de robots en tierra, mar y aire en misiones de seguridad civil o militar así como su uso en misiones espaciales.

De servicios

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

Introducción

19

Si atendemos a su evolución se clasifican de la siguiente manera:

Generación Descripción

1ª generación Sistema de control basado en “paradas fijas” mecánicamente (mecanismos de relojería que mueven las cajas musicales o los juguetes de cuerda).

2ª generación

El movimiento se controla a través de una secuencia numérica almacenada en disco o cinta magnética (industria automotriz).

3ª generación

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.

4ª generació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.

5ª generación

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:

Introducción

20

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:

Sensores

Motores Ruedas

Fuente de energía

Tarjeta de control

Introducción

21

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.

Estado Respuesta Los dos sensores están sobre la línea El robot acanza con las dos ruedas El sensor de la derecha ha salido de la línea.

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.

Los dos sensores están fuera de la línea. Ambas ruedas permanecen paradas.

Introducción

22

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.

Introducción

23

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

Introducción

24

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 Descripción

Gestor de superficies (surface Manager)

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.

OpenGL/SL y SGL.

Librerias graficas 3D y 2D

Las aplicaciones pueden combinar gráficos en 2 y 3 dimensiones.

Bibliotecas multimedia

Permiten tratar el contenido multimedia ( videos, audio, animaciones,etc).

Webkit.

Motor web utilizado por el navegador.

-SSL( Secure Sockets

Layer).

Protocolo para comunicarse de forma segura.

Freetype. Permite trabajar con fuentes tipográficas.

SQLite. Motor de bases de datos relacionales, disponible para todas las aplicaciones.

Biblioteca C de sistema(libc).

Incluye las cabeceras y funciones del lenguaje C.

Tabla 5. Bibliotecas de Android

Introducción

25

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 Descripción

Dalvik Diseñada para ejecutar aplicaciones que son propias de dispositivos móviles y no de JAVA.

JAVA Transforman en .dex donde los comprime para una mayor optimización.

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

Administrador de actividades

(Activity Manager).

Controla el ciclo de vida de las aplicaciones de Android.

Administrador de ventanas

(Windows Manager).

Gestiona las ventanas de las aplicaciones y utiliza la librería Surface 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.

Introducción

26

Bibliotecas Descripción

Administrador de telefonía (Telephone 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.

Administrador de recursos

(Resource Manager)

Proporciona acceso a todos los elementos propios de una aplicación que se incluyen directamente en el código.

Administrador de ubicaciones (Location Manager)

Determina la posición geográfica (GPS, mapas, etc).

Administrador de sensores

(sensor Manager)

Gestiona el acelerómetro, giróscopo,sensor de presión, etc).

Cámara

Gestiona el sensor de la 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.

Introducción

27

• 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:

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.

Conector PC

USB HOST

Conector DC

Pines de señal PWM

Pines de comunicación

Serie

E/S digitales

Pines de alimentación

E/S analógicas

Microcontrolador

Atmega2560

Introducción

28

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.

Elementos del Sistema

29

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:

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:

POWER

MICRO

CON

TROLADO

R

E/S

E/S

E/S

Sensor iluminación

Batería

Sensor de contacto izquierdo

Sensor de ultrasonidos

Sensor de contacto derecho

Motor rueda izquierda

Motor rueda derecha

Sensor CNY70

izquierdo

Sensor CNY70 derecho

Elementos del Sistema

30

Figura 10. Incorporación del hardware del ADK

Sensor iluminación

Batería

Sensor de contacto izquierdo

Sensor de ultrasonidos

Sensor de contacto derecho

Motor rueda izquierda

Motor rueda derecha

Sensor CNY70

izquierdo

Sensor CNY70 derecho

Elementos del Sistema

31

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 con acondicionamiento

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

Figura 11. Funcionamiento CNY70

Fototransistor Led IR

Color blanco

Elementos del Sistema

32

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.

Elementos del Sistema

33

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

Elementos del Sistema

34

A continuación se muestra una tabla con las principales características:

Voltaje de operación 5 V DC Corrriente de operación 15 mA Frecuencia de emisión 40 KHz Rango máximo 70 cm Rango mínimo 2 cm Ángulo de medida 15 º Trigger input signal 10 microsegundos, señal TTL Echo output signal Input TTL Dimensiones 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.

Tabla 10. Sensor LDR

Símbolo Apariencia Respuesta espectral

Elementos del Sistema

35

Conexionado:

Figura 15. Sistema de acondicionamiento

La salida Vout se conecta a un pin analógico del Arduino configurado como entrada.

Servomotores Futaba S3003

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:

Especificaciones Apariencia Conexionado Voltaje: [4.8, 6] V Corriente máxima: 8 mA

Elementos del Sistema

36

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.

Elementos del Sistema

37

Sensor de contacto. Interruptor de fin de carrera RL6

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.

Especificaciones Conexionado Apariencia Voltaje máx: 250 V Corriente máxima: 16 A

Señal de medida

Señal de control

VCC GND

GND

VCC

Elementos del Sistema

38

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 salidas Total pines

Analógicas 1 para el sensor LDR

1

Dgitales

2 para los interruptores

2 señales PWM para los servos

6 1 para el “echo” del

sensor HC- SR04 1 para el “trigger” del

sensor HC- SR04 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:

Elementos del Sistema

39

Especificaciones

Microcontroller ATmega2560 Input Voltage (recommended) 5 V Input Voltage (limits) 7- 12 V Digital I/O Pins 54 (of which 15 provide PWM output) Analog Input Pins 16 DC Current per I/O Pin 40 mA DC Current for 3.3V Pin 50 mA Flash Memory 6 KB of which 8 KB used by bootloader SRAM 8 KB EEPROM 4 KB Clock Speed 16 MHz USB Host Chip MAX3421E

Tabla 14. Especificaciones Arduino

Figura 17. Esquema Arduino ADK

Conector PC

USB HOST

Conector Jack 2.1 mm

Pines de señal PWM

Pines de comunicación

Serie

E/S

dig

itale

s

Pines de alimentación

E/S analógicas

Microcontrolador

Atmega2560

Elementos del Sistema

40

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:

Elementos del Sistema

41

Especificaciones Modelo Huawei Ascend Y 300 Sistema operativo Android 4.1 (Jelly Bean) Banda UMTS: 900/2100 - EDGE:

850/900/1800/1900 - HSDPA DL 7.2Mbps / UL 5.76Mbps

Dimensiones 124,5 x 63,8 x 11,2mm Pantalla 4,0" TFT-LCD WVGA. Resolución:

800x480. 16M Colores. CORNING® GORILLA® GLASS 2

Batería Li-ion 1950 mAh Memoria interna ROM: 4GB, RAM: 512MB Memoria de expansión MicroSD hasta 32GB Conectividad Bluetooth 2.1 A2DP, Wi-Fi 802.11 b/g/n,

USB 2.0 High-Speed Cámara 5 MP AF, Cámara frontal: 0,3MP FF Peso 130g con batería Procesador Qualcomm MSM8225. 1,0 GHz Doble

Nucleo Otros 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

Diseño del Sistema

42

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.

Diseño del Sistema

43

Sensor iluminación

Batería

Sensor de contacto izquierdo

Sensor de ultrasonidos

Sensor de contacto derecho

Motor rueda izquierda

Motor rueda derecha

Sensor CNY70

izquierdo

Sensor CNY70 derecho

App Android

Programa Arduino

Com

unic

ació

n U

SB

Diseño del Sistema

44

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

Diseño del Sistema

45

Una vez hecho esto, se pasará a mostrar los diferentes elementos que componen el IDE de Arduino:

Figura 20. Entorno 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

Guardar el sketch

SKETCH

Cuadro de mensajes. Aquí se muestran los errores de programación, warnings, modificaciones…

Número de línea donde se encuentra el cursor

Puerto del Arduino en el que se cargará el sketch

Abre el monitor serie que muestra los datos por pantalla enviados desde Arduino. También permite enviarle datos

Diseño del Sistema

46

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.

Diseño del Sistema

47

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:

Diseño del Sistema

48

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.

Diseño del Sistema

49

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:

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:

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

Diseño del Sistema

50

Figura 24. Flujograma del programa en Arduino

Diseño del Sistema

51

• 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.

Diseño del Sistema

52

• Protocolo de mensajes 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:

Figura 25. Contenido del mensaje

Posición Descripción Dato

[0] Posee el modo de operación del robot.

0x7. Modo Manual.

0x1. Modo Siguelíneas.

[1]

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.

0x1. El dato es la inclinación del eje X. 0x2. El dato es la inclinación del eje Y.

De [2] a [5]

El dato medido por el acelerómetro en cualquiera de los dos ejes. Sólo es necesario si estamos en Modo Manual.

Tabla 16. Protocolo del mensaje

[0] [1] [2] [3] [4] [5]

Mod

o de

ope

raci

ón

Eje

del

ace

leró

met

ro

Dat

o

Diseño del Sistema

53

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.

Diseño del Sistema

54

- 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:

Diseño del Sistema

55

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.

Diseño del Sistema

56

• 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’.

Diseño del Sistema

57

- 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:

Diseño del Sistema

58

Como se aprecia en el código, el protocolo de mensajes es el siguiente:

Posición Descripción Dato

[0] Identificación del sensor. 0x5. Sensor de

iluminación. 0x7. Sensor de ultrasonidos.

De [1] a [2]

Dato del sensor. El dato tiene 16 bits.

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.

Diseño del Sistema

59

A continuación se presenta la apariencia con los elementos que componen el entorno Eclipse:

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:

Estructura de Elementos

De la aplicación

Barra de herramientas

Editor de archivos

Ventana de ejecución

Ventana de Breakpoints

y

depuración de errores

Diseño del Sistema

60

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.

Diseño del Sistema

61

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.

Diseño del Sistema

62

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

Diseño del Sistema

63

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:

Diseño del Sistema

64

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.

Diseño del Sistema

65

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.

Figura 31. Esquema general de la aplicación

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 Modo

Manual •Utilizar el servicio.

• Dejar de utilizar el servicio.

Actividad Modo

Siguelíneas

• Utilizar el servicio.

•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.

Actividad principal

•Ejecutar el servicio

• Parar el servicio.

•Abrir actividad Modo Manual.

• Abrir actividad Modo Siguelíneas.

Diseño del Sistema

66

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:

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

Botones

Relative Layout

Diseño del Sistema

67

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:

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:

El código de los otros tres botones es igual

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

Diseño del Sistema

68

Figura 33. Ciclo de vida de una actividad

Diseño del Sistema

69

A continuación se hace una descripción de estos métodos:

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

Método Descripción

onCreate() 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().

Diseño del Sistema

70

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:

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

Callback de un botón:

Llamada en onCreate():

Diseño del Sistema

71

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

Diseño del Sistema

72

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.

Diseño del Sistema

73

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.

Diseño del Sistema

74

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:

USB Host

Usb

Hos

t Shi

eld

And

roid

Acc

esso

ry

Usb

Man

ager

And

roid

Acc

esso

ry

C/ C

++

And

roid

Diseño del Sistema

75

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

SISTEMA

ANDROID

BROADCAST

RECEIVER

NTENTI FILTER

DESCRIPTOR

THREAT Y RUNNABLE

A

P

L

I

C

A

C

I

Ó

N

OpenAccessory()

RegisterAccessory()

INPUT STREAM OUTPUT STREAM

Registro para el evento de USB

Notificación cuando un evento en

USB ocurre

Diseño del Sistema

76

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.

Diseño del Sistema

77

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

Diseño del Sistema

78

Flujograma de la Clase Servicio

Diseño del Sistema

79

Diseño del Sistema

80

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:

Figura 41. Apariencia de la Actividad Cliente

A continuación se muestra la clase Cliente:

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)

Diseño del Sistema

81

Diagrama de la Clase cliente

Figura 42. Diagrama de la Clase Cliente

Diseño del Sistema

82

Flujograma de la Clase Cliente

Pruebas y evaluación

83

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

Pruebas y evaluación

84

• 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

Tabla 20. Características del Huawei Ascend Y300

Características Descripción Apariencia SO Android OS,

v4.1 (Jelly Bean)

CPU Dual-core 1 GHz Cortex-A5

Versión USB 2.0 Se utiliza en todas las pruebas a lo largo del desarrollo de la aplicación. Además irá incorporado en el robot.

Pruebas y evaluación

85

BQ Aquaris 5.7

Tabla 21. Características del Smartphone BQ Aquaris 5.7

• Robot utilizado

Tabla 22. Robot del laboratorio

Características Descripción Apariencia SO Android 4.2

Jelly Bean

CPU Quad Core Cortex A7 7 up to 1.5 GHz

Versión USB 2.0 Sólo es utilizado para estudiar la compatibilidad con otras plataformas.

Componentes Apariencia Placa Arduino ADK

Placa Protoboard Sensor de ultrasonidos Sensor de iluminación

Sensor de contacto

Sensor detector de línea

Pruebas y evaluación

86

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.

Pruebas y evaluación

87

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.

Pruebas y evaluación

88

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).

Pruebas y evaluación

89

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.

Conclusiones y líneas futuras

90

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.

Conclusiones y líneas futuras

91

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.

Presupuesto

92

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. Estudio de cómo fucniona el ADK de Google, instalar software y lebrerías necesarias (10 h).

II. Estudio del Arduino y del IDE de programación (15 h). III. Búsqueda de información y tutoriales de Arduino (30 h). IV. Estudio de Android y de su entorno de programación Eclipse

(20 h). V. Búsqueda de información y tutoriales de Android (30 h).

2. Fase de desarrollo del sistema propuesto

I. Elaboración y pruebas de programas básicos(20 h).

II. Estudio del desarrollo de un servicio en Android (20 h). III. Desarrollo del software definitivo del Arduino y la aplicación en

Android (60 h). IV. Pruebas y correcciones del sistema(50 h).

3. Fase de elaboración de la memoria

I. Redacción de la memoria(80 h).

II. Corrección y maquetación(5 h).

Tabla 23. Fases de la memoria

Fases Horas Documentación 75 Desarrollo del sistema propuesto

150

Elaboración de la memoria 85 TOTAL 310

Presupuesto

93

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 TOTAL 13.950

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 Descripción Cantidad Coste unitario(€) Importe total(€)

Arduino ADK Rev 3 1 44 44.00 Smartphone

Huawei Ascend Y300 1 120 120

Coste total de material 164

Tabla 25. Coste de material

Presupuesto

94

Coste del proyecto

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

RESUMEN PRESUPUESTO Descripción Importe total (€)

Coste personal 13.950 Coste de material 164

Impuestos (IVA 21 %) 2.963,94 Total presupuesto 17.080,94

Anexos

95

Capítulo 7

Anexos

8.1 ANEXO I: Datasheet Arduino

Anexos

96

Anexos

97

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;

//

Anexos

98

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();

Anexos

99

//////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;

Anexos

100

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){

Anexos

101

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);

Anexos

102

}

//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){

Anexos

103

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);

}

}

Anexos

104

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;

Anexos

105

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;

Anexos

106

//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;

}

Anexos

107

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;

Anexos

108

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.

Anexos

109

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;

Anexos

110

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 ;

Anexos

111

} 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);

Anexos

112

}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;

Anexos

113

} } 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],

Anexos

114

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:

Anexos

115

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));

Anexos

116

} 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);

Anexos

117

//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); } } }

Anexos

118

}

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){

Anexos

119

//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;

Anexos

120

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

Anexos

121

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(); } }

Anexos

122

// 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) { } } } } */

Anexos

123

@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{

Anexos

124

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;

Anexos

125

//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 {

Anexos

126

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(); } };

Anexos

127

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(){

Anexos

128

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

Anexos

129

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

Anexos

130

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"

Anexos

131

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" />

Anexos

132

</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"

Anexos

133

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>

Bibliografía

134

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.

Bibliografía

135

[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-usb-

driver-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-en-

android/.

[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-source-

browsing/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.