principal

En esta nueva entrada del curso de programación con Protocoder veremos cómo obtener datos de los sensores de nuestro terminal móvil o tablet.

Sensores en el terminal

Los terminales móviles suelen tener ciertos sensores como, por ejemplo, acelerómetro, sensor de luz y de proximidad.

El acelerómetro mide la aceleración del terminal, normalmente la producida por la gravedad. La tecnología en la que se basa son pequeños condensadores que varían su capacidad dependiendo de la aceleración a la que se sometan. Si quieres aprender más a fondo cómo funciona un acelerómetro puedes visitar este link (Inglés).

En el caso del sensor de luz, se basan en un fotodiodo que genera una corriente según la cantidad de luz que incida sobre el sensor. A partir de la corriente generada, se “traduce” a una secuencia de bits que el terminal móvil es capaz de comprender. Si quieres aprender más sobre cómo funciona un fotodiodo, puedes visitar este enlace.

El sensor de proximidad se basa en un emisor y receptor infrarrojo. El emisor manda un pulso de luz infrarroja y si un objeto se encuentra suficientemente cerca para reflejar dicho pulso, el receptor “leerá” el pulso. Si no hay ningún objeto cerca que pueda reflejar la luz infrarroja, se “perderá”. De esta manera podemos determinar si hay un objeto cerca del sensor o no.

Si quieres conocer más sobre los usos de los sensores dentro de un terminal móvil, puedes visitar este enlace.

Utilizando un ejemplo como base

En este caso, vamos a utilizar el ejemplo sensors de Protocoder para ver cómo obtener datos de los sensores. A partir de este ejemplo, modificaremos el código para ajustarlo a nuestras necesidades.

Para acceder a los sensores, en primer lugar, se crean textos en los que se escriben los datos de los sensores. Para crear estos cuadros de texto se utiliza el siguiente código:

110

A continuación, se leen los datos de los sensores y se escribe el valor de la lectura en la variable anterior correspondiente:

Una vez que la aplicación se cierre, Protocoder parará automáticamente todos los sensores, pero éstos se podrían parar con la función:

Modificando el ejemplo

bq_Aquaris_E4_2

Comenzamos incluyendo la cabecera de los programas:

sensors

A continuación, modificamos los parámetros de las variables de texto para que incluyan las medidas de las variables. En este caso:

Si habéis probado el ejemplo de los sensores explicado en el punto anterior, muchos de los datos que aparecen tienen demasiada precisión y puede ser complejo leerlos, por lo que utilizaremos una función para bajar la precisión de los datos:

Esta función toma como parámetros el valor a ajustar y la precisión a la que queremos que se ajuste.

A continuación, utilizamos la función toFixed para hacer que los valores se impriman con dos decimales. Por ejemplo, el código relativo al acelerómetro, una vez aplicada la función es:

De la misma manera, aplicamos la función toFixed al resto de valores, menos al sensor de luz y al sensor de proximidad.

A continuación, creamos un botón que se encargará de “limpiar” la pantalla, cambiando la transparencia de los textos para evitar que se vean y mostrando un canvas en el que dibujaremos círculos de distintos colores y tamaño, que cambiarán de posición dependiendo de la lectura del acelerómetro. También tenemos que crear una variable con la que podamos conocer cuál es el estado del botón, por ejemplo se mostrarán los textos si la variable vale false, y el canvas si la variable es igual a true.

Play_button

A continuación, tenemos que programar el comportamiento del botón una vez que se ha pulsado, para lo que utilizaremos la variable state. Comprobaremos cuál es su valor, se ejecutarán las acciones correspondientes y, por último, cambiaremos el valor de la variable.

Una vez que se haya pulsado el botón, se modificarán las transparencias, se cambiará el valor del la variable state y el texto del botón cambiará. Además, cuando la variable state sea true, es decir, canvas esté “oculto”, borraremos la información que se haya dibujado y volveremos a poner el fondo negro.

bq_Aquaris_E4_(1)

Para crear el canvas utilizamos el siguiente código:

Las variables wCanvas y hCanvas determinarán el tamaño del canvas. Además, vamos a cambiar la transparencia del elemento para que no se muestre al iniciar el programa:

Para dibujar sobre el canvas, tenemos que utilizar la función loopDraw, que toma como parámetro el tiempo de actualización en milisegundos de la función, es decir, cada cuanto se ejecutará la función que está contenida dentro de loopDraw. En este caso, utilizamos la siguiente función:

En primer lugar, con la orden canvas.fill indicamos de qué color se “pintarán” los elementos siguientes, es decir, en primer lugar definimos el color y a continuación dibujamos. Si se quiere dibujar diferentes objetos en diferentes colores, tendremos que utilizar la orden canvas.fill antes de cada uno de ellos.

La variable size almacenará el valor devuelto de la función randomSize, que podrá obtener como máximo la mitad del tamaño del canvas.

Finalmente, aplicamos un factor de conversión entre la posición X y el ancho del canvas y entre la posición Y y el alto de la pantalla teniendo en cuenta el módulo de la aceleración de la gravedad.

Las funciones randomColor, randomSize, posX y posY son funciones que hemos realizado para generar un color RGB aleatorio, un tamaño aleatorio y “traducir” la posición X e Y desde las lecturas del acelerómetro, respectivamente. Estas funciones son:

6 comentarios

  1. Buenas,
    He utilizado vuestro código y para hacerlo funcionar he tenido que añadir la declaración de dos variables globales acelX y acelY ya que no están definidas en ningún lugar y se utilizan en el canvas.ellipse.
    De tal forma que he añadido esta declaración al principio junto con el resto de variables:

    ui.toolbar.title(“Sensors”);
    ui.toolbar.bgColor(55, 155, 155, 255);
    ui.toolbar.show(true);
    //ui.screenMode(“fullscreen”);
    ui.screenOrientation(“portrait”);
    ui.allowScroll(false);

    var margin = 10;
    var w = ui.screenWidth – 2*margin;
    var h = 150;
    var y = h + margin;
    var acelX, acetyl; // Estas son la variables añadidas

    y también las he añadido en la función del acelerometro para que vayan actualizando su valor.

    sensors.accelerometer.onChange(function(x, y, z) {

    accelerometer.setText(“acc: “+ toFixed(x,2)+ “, ” +toFixed(y,2)+ “, ” + toFixed(z,2));
    acelX = toFixed(x,2); //Añadido para el valor x del acelerometro
    acelY = toFixed(y,2); //Añadido para el valor y del acelerometro
    });

    De esta forma me funciona correctamente por si alguien se encuentra con el mismo problema, añada estas variables para solucionar el problema.
    Espero haber podido ayudar.
    Un saludo,
    Diego Herrero

    1. Luis Díaz

      Hola Diego,

      Gracias por tu comentario. En la entrada no se explica la creación de variables, ya que se ha visto en otras entradas y además, al explicar tan solo el código necesario para el funcionamiento clave, considero que se comprende mejor el concepto que se trata de explicar.

      Por otra parte, dentro de las descargas se encuentra el código completo y listo para utilizar.

      Además, intentaré ser más explicito con lo que deje fuera del código para que sea más claro y fácil de entender.

      De nuevo, gracias por tu comentario y un saludo.

  2. Hola Luis,

    ¿Como puedo aumentar o disminuir la velocidad de muestreo de los sensores en especial el acelerómetro y el giroscopio?

    1. Enrique Heredia

      Hola Guillermo,
      La toma de datos se hace por eventos, cuando se produce algún cambio. Para aumentar el tiempo de muestreo podrías probar a meter una espera dentro de las funciones, aunque es una solución poco óptima. ¿Qué es lo que quieres hacer?
      Un saludo

      1. Hola Enrique,

        Gracias por tu respuesta, tengo una placa IOIO OTG y tiempo atrás durante un proyecto de investigación construí un prototipo de un “solar tracker” (yep… another one) en lazo cerrado utilizando un algoritmo desarrollado por Roberto Grena para el calculo de la posición del sol.

        En ese entonces la placa se comunicaba a mi laptop mediante bluetooth, tuve que realizar una traducción de C++ a Java de algunos de los drivers de Arduino tales como el BMP180.

        Ahora con Protocoder veo la posibilidad de refactorizar y añadir funcionalidad a este proyecto.
        Ej:
        – Utilizar el móvil y consultar el estado mediante mi laptop.
        – Remplazar el sensor BMP180 por el incorporado en el móvil.

        Por el momento estoy explorando y consultando en foros (en espera de la documentación oficial)

        1. Enrique Heredia

          Hola Guillermo,
          Parece un proyecto interesante. En este caso te recomendaría que, si quieres reducir la velocidad de muestreo, lo hagas variando la frecuencia con que envías los datos desde el móvil, en vez de intentar variar la velocidad con que los obtienes. Desde la placa el resultado será el mismo.
          Un saludo

Los comentarios están cerrados.