Archivo de la categoría: Programación

Clase BarraInfo para Processing

He creado una clase llamada BarraInfo para que podais añadir a vuestros proyectos de Processing. La clase sirve para crear barras de información, como las que habeis visto en la telemetría para mostrar el PWM de los motores o el nivel de la batería.

La ventaja de usar esta clase (y cualquier otra) es que os evitais tener que crear el código de cero porque ya está hecho, podeis usarla en todos los proyectos de Processing que hagais, podeis tener varias barras de información en la pantalla y se puede configurar a medida.

A continuación os pongo el código fuente de la clase:

Para usarla os voy a poner un ejemplo de cómo mostrar el PWM asignado a un motor.

Lo primero es copiar el código fuente que he puesto más arriba en vuestro proyecto, preferentemente al final.

Lo segundo es crear una variable global del tipo BarraInfo.

Lo tercero es instanciar la clase para crear un objeto en el método setup de vuestro sketch.

Después, y dentro del mismo método setup inicializamos las variables de la clase. Dado que las variables de las clases de Processing son públicas y no se admiten variables de tipo privado, he preferido acceder a ellas directamente sin métodos get/set:

Establecemos el valor de inicio y final que podrá tener la barra, en el PWM es de 0 a 255, en una batería Lipo sería de 0 a 8,4.

Establecemos el color de las lineas (que comprende las muescas y el texto asociado a ellas) y el color de la barra.

Establecemos la posición x e y de nuestra ventana donde se mostrará la barra de información.

Establecemos la anchura de las muescas y de la barra (cada una) y la altura del conjunto.

Establecemos cada cuantos píxeles se dibuja una muesca y cada cuantos píxeles se muestra un número de referencia.

Establecemos la fuente que previamente habremos creado en el menú Tools/Create Font… de Processing y la desplazamos en su eje x e y para que encaje bien en las muescas.

Establecemos el número mínimo de enteros que apareceran (rellenando con ceros por la izquierda si no llega) y el número de decimales (-1 si no queremos que salgan) de los números de referencia.

Finalmente en el método draw se debe establecer el valor que debe tener la barra y pintarlo. He puesto un random para que pueda apreciar el movimiento.

Así es como quedaría el código fuente:

Y así el resultado:

Processing y el puerto serie

Processing es un software de programación de representaciónes gráficas y animaciones. Está basado en java y debido a ello es multiplataforma. Es software libre y tiene una comunidad muy extensa de desarrolladores y de usuarios.

El objetivo de este artículo es tratar de dar una idea de cómo hacer que Processing pueda interactuar con un puerto serie: cómo recibir y enviar datos, cómo mostrarlos en un gráfico y/o guardarlos en un fichero.

Como Processing puede usar librerías al estilo de java, hay una que necesitaremos para la programación del puerto serie, esta es processing.serial y se puede importar desde un sketch de la siguiente manera:

A continuación se debe crear una variable global del tipo Serial (o varias si vamos a tratar con más de un puerto serie).

Después hay que instanciarlo en el método Setup.

Lo que estamos haciendo es crear un objeto Serial. El constructor de la clase Serial tiene varias sobrecargas:

Serial(padre)
Serial(padre, velocidad)
Serial(padre, puerto)
Serial(padre, puerto, velocidad)
Serial(padre, puerto, velocidad, paridad, palabra, parada)

Los parámetros son:

padre: Se suele usar this siempre.
velocidad: La velocidad en b.p.s. a la que se quiere enviar y recibir datos: 9600 es la que toma por defecto si no se le indica otra cosa.
puerto: Nombre del puerto de comunicaciones. «COM1» es el que toma por defecto, pero puede ser otro de windows. En linux o mac suele ser /dev/tty*
paridad: ‘N’ para ninguna, ‘E’ para paridad par, ‘O’ para paridad impar. ‘N’ es la que se toma por defecto.
palabra: Número de bits que conforman una unidad de datos. 8 es el que se toma por defecto.
parada: Número de bits de parada (stop). Puede ser 1.0, 1.5, or 2.0, siempre en formato float. 1.0 es el que se toma por defecto.

Si no sabemos a priori qué puertos serie tenemos en nuestro ordenador, podemos imprimir un listado de los disponibles.

Como se trata simplemente de un array de cadenas, podemos acceder al valor de cualquier de ellas y pasárselo como argumento al constructor de Serial, tal y como he expuesto lineas atrás en la creación del objeto.

A partir de aquí, y si el puerto se ha podido abrir sin problemas, podemos enviar y recibir los datos.

Para enviar datos desde Processing al puerto serie hay que usar el método write del objeto que hayamos creado.

Se puede enviar tipos byte, char, int, array de bytes o cadenas.

Para recibir los datos tenemos dos posibilidades.

1) Comprobar dentro del método Draw si hay datos disponibles para su lectura, leerlos y procesarlos:

El método available nos devuelve el número de bytes que hay pendientes por leer en el buffer. El método read nos devuelve un valor de 0 a 255 del primer byte de la cola FIFO del buffer, o -1 si no hay dato disponible. Además de read hay otros métodos para recuperar los datos: readChar, readBytes, readBytesUntil, readString, readStringUntil.

2) Definir en el método Setup cuantos bytes queremos leer cada vez, esperar a que se active el evento serialEvent, y dentro de este leer los bytes.

En Setup:

En el cuerpo principal del sketch:

Esta técnica es mucho más optima que la primera. El rendimiento del método Draw para leer los datos del puerto serie y dibujarlos será menor que si el método Draw sólo se centra en leer las variables y dibujar en consecuencia, dejando al evento serialEvent que se encargue de poblar las variables con los datos recibidos por el puerto serie. Para que funcione esta técnica, se debe informar al objeto Serial de cuantos bytes se deben leer antes de que se dispare el evento serialEvent, esto se hace usando el método buffer indicando los bytes a leer. Dentro del evento serialEvent se deben leer tantos bytes como se especificaron con el método buffer. Si se está trabajando con más de un puerto serie se puede usar el único parámetro del evento serialEvent para distinguir desde qué puerto serie se han recibido los bytes.

Si se desea escribir los datos que se reciben a un fichero se debe crear una variable global del tipo PrintWriter.

Luego en el método Setup debemos crear el objeto PrintWriter indicando en qué fichero guardar los datos.

Finalmente, ya sea dentro del método Draw o del evento serialEvent (recomendado) se escriben los datos al fichero:

Es importante ejecutar el método flush para garantizar que se están guardando los datos y no se quedan en buffers intermedios, ya que cuando cerremos la ejecución de nuestro sketch todo lo que no haya sido físicamente escrito al disco se pierde.