Archivo de la etiqueta: puerto serie

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.