Cuaderno técnico 11: Utilización del puerto serie desde Python (Módulo Pyserial)




Introducción

La comunicación a través del puerto serie se sigue utilizando mucho para conectar el PC con otros dispositivos, como por ejemplo microcontroladores. Además de estar soportado en todos los ordenadores y dispositivos, la interfaz software es muy fácil de utilizar. Actualmente muchos ordenadores portátiles no vienen con puerto serie incorporado (no traen un conector DB9). Esto no es problema, ya que se pueden emplear conversores USB-serie.

Yo utilizo muchísimo el puerto serie para controlar los robots y comunicarme con los microcontroladores que uso. Así es como nació el proyecto stargate, en el que hay definidos unos protocolos muy sencillos para comunicar aplicaciones cliente desde el PC con pequeños servidores que corren en los microcontroladores (los stargates).

Un ejemplo es el robot Cube Revolutions que utiliza una tarjeta Skypic, basada en el microcontrolador PIC16F876A.

En este cuaderno técnico se muestran diferentes ejemplos de uso del puerto serie utilizando el lenguaje Python. Todos los ejemplos funcionan tanto en Linux como en Windows. Para las comunicaciones serie se ha utilizado la librería pyserial y muchos de los ejemplos son modificaciones de los ejemplos que hay en ella.

Los ejemplos que se muestran son:


Instalación en Debian GNU/Linux

Estos programas de ejemplo se han probado en una máquina con Debian/Etch. Hay que tener instalado python y el módulo python-serial:

# apt-get install python python-serial

Para probar los ejemplos descargar el paquete pyserial-ejemplos.zip y descomprimirlo en un directorio de trabajo.


Instalación en Windows

Es necesario tener instalados estos tres componentes:

Aquí están disponibles los enlaces a los instaladores para windows:

  1. Instalador de python 2.5 para Windows. (python-2.5.msi)

  2. Instalador de las extensiones de Python para Windows. (pywin32-210.win32-py2.5.exe)

  3. Instalador del módulo Pyserial. (pyserial-2.2.win32.exe).

Para probar los ejemplos descargar el paquete pyserial-ejemplos.zip y descomprimirlo en un directorio de trabajo.


Ejemplo “hola mundo” 1: Escaneo de los puertos serie (scan.py)

Programa: [scan.py]

Explicación:

Ejemplo que define una función de escaneo que devuelve una lista con los números y nombres de los puertos serie que se han abierto con éxito (y que por tanto existen en nuestro sistema y los podemos usar).

Observar que la librería pyserial utiliza los números del 0 al 255 para referirse a los puerto serie. Esto es así para que sea multiplataforma. También es posible abrir los puertos serie con los nombres típicos de cada sistema operativo (/dev/ttyX en Linux, COMx en Windows). Pero para que el programa sea multiplataforma y corra en ambos sistemas, hay que utilizar los números entre el 0 y 255.

Abrir el puerto serie es tan fácil como invocar a la clase Serial, indicando el número de puerto serie a abir:

#-- Abrir puerto serie
s = serial.Serial(i)

Si el puerto no existe, se produce una excepción, que en el ejemplo de scan.py se captura y no se hace nada, para seguir probando más puertos.

Si no ha ocurrido ningún error, se mete en la lista dispositivos_serie tanto el número del puerto encontrado como su nombre:

#-- Si no hay errores, anadir el numero y nombre a la lista
dispositivos_serie.append( (i, s.portstr))

El programa principal simplemente invoca a la función scan() y muestra los resultados por pantalla. Se pueden emplear dos parámetros opcionales. Uno es el número de puertos seriea a probar. Por defecto se prueban los 20 primeros. El otro es el modo “verbose”, también activado por defecto, que muestra información sobre los puertos que se van escanenando.

Ejemplo de utilización:

python scan.py

En linux se pueden poner permisos de ejecución y teclear directamente ./scan.py para ejecutarlo.

Ejemplo de funcionamiento en GNU/Linux:

Ejemplo de funcionamiento en Windows:

Notas sobre el puerto serie en Linux:

La librería pyserial asocia los números de puerto serie 0, 1, 2, etc a los dispositivos /dev/ttyS0, /dev/ttyS1, /dev/ttyS2, etc, respectivamente. Sin embargo, cuando se utiliza un conversor USB-serie, los dispositivos que aparecen son /dev/ttyUSB0, /dev/ttyUSB1, etc...

Para hacer que estos nuevos dispositivos se puedan usar con pyserial se pueden hacer dos cosas:

  1. Abrir directamente el puerto serie especificando el dispositivo. Ejemplo: s = serial.Serial(“/dev/ttyUSB0”). El problema de esto es que no es multiplataforma. Si se ejecuta en Windows se producirá un error.

  2. Hacer un link entre el dispositivo /dev/ttyUSBx y un /dev/ttySz que no se esté usando. En mi caso utilizo los nombres /dev/ttyS10, /dev/ttyS11... para asignarlos a los /dev/ttyUSB0, /dev/ttyUSB1... respectivamente. Por ejemplo:

$ sudo ln -s /dev/ttyUSB0 /dev/ttyS10

De esta forma al ejecutar scan() se detectará que está disponible el dispositivo con número 10 (es lo que se muestra en el pantallazo de Linux)




Ejemplo “hola mundo” 2: Prueba de “eco” 1 (sg-eco1.py)

Programa: [sg-eco1.py]

Explicación:

Para realizar pruebas con el puerto serie, lo más recomendable es comenzar utilizando un hardware que haga “eco” de todo lo que se le envía. Se puede realizar de dos maneras:

  1. Utilizar un cable para unir los pines 2 y 3 (RX y TX) del conector DB9 del puerto serie. De esta manera todo lo que el PC envía hacia el exterior es automáticamente recibido

  2. Conectar un hardware con un microprocesador que tenga grabado un firmware para implementar la funcionalidad de eco. Por ejemplo, utilizando una tarjeta Skypic, (que usa un micro PIC16F876A) con el servidor de eco grabado.

El programa sg-eco1.py abre el puerto serie, y si no se produce ningún error, envía la cadena de prueba “Hola como estas” . Para ello se utiliza el método write():

#-- Enviar la cadena de pruebas
print "ENVIADO : " + Cadena
s.write(Cadena);

La cadena sale por el puerto serie y el hardware hace “eco”. El programa se queda esperando hasta recibir tantos bytes como los que tiene la cadena que ha sido enviada. Para ellos se invoca al método read() pasando como argumentos el número de bytes que se quiere recibir.

#-- Esperar hasta recibir la cadena enviada...
#-- O hasta que haya un timeout
recibido = s.read(len(Cadena));

Ahora pueden ocurrir dos cosas. Bien que la cadena llegue correctamente (se reciben tantos bytes como los que se han enviado) o bien que no lleguen todos, produciéndose un timeout.

Ejemplo de utilización:

python sg-eco1.py

En linux se pueden poner permisos de ejecución y teclear directamente ./sg-eco1.py para ejecutarlo.

Los pantallazos para Linux y Windows se muestran con el ejemplo sg-eco2.py, que son similares a sg-eco1.py.

Si todo ha ido bien, lo que aparecerá en pantalla será:

Pruebas del puerto serie
Puerto (0): /dev/ttyS0
ENVIADO : Hola como estas
RECIBIDO: Hola como estas
OK!

En windows aparecerá COM1 donde pone /dev/ttyS0

Si se quiere utilizar otro puerto serie diferente del 0, hay que modificar la variable Puerto.


Ejemplo “hola mundo” 3: Prueba de “eco” 2 (sg-eco2.py)

Programa: [sg-eco2.py]

Explicación:

Este ejemplo hace exactamente lo mismo que sg-eco1.py, pero ahora se le pasa como argumento el número de puerto serie a emplear. Se ha divido en dos ejemplos para separar la parte de comunicaciones serie con la de análisis de los argumentos, para que quede más claro. Pero funcionalmente son equivalentes.

Ejemplo de utilización:

Se invoca el programa pasando como argumento -p x, donde x es el número o nombre del puerto serie a utilizar.

python sg-eco2.py -p 0

En linux se pueden poner permisos de ejecución y teclear directamente ./sg-eco2 -p 0 para ejecutarlo.

Ejemplo de funcionamiento en GNU/Linux:

Se está utilizando el puerto /dev/ttyS10 que es un conversor USB-serie (/dev/ttyUSB0). Se ha hecho un link simbólico al dispositivo /dev/ttyS10 para que pyserial lo reconozca.

Ejemplo de funcionamiento en Windows:

Se está utilizando el puerto COM1 que está asociado al número 0.



Ejemplo “hola mundo” 4: Mini-terminal (miniterm.py)

Programa: [miniterm.py]

Explicación:

Miniterminal de comunicaciones para hacer pruebas rápidas. Todo lo que se teclea se envía por el puerto serie y todo lo que se recibe se imprime en la pantalla. Se utiliza un hilo (thread) para leer del puerto serie y mostrar en pantalla. El hilo principal está pendiente de enviar todo lo que el usuario teclea.

Se utiliza el módulo pyconsola_io para leer las teclas.

Ejemplo de utilización:

Se invoca de la siguiente manera:

python miniterm.py -p 0

Ejemplo de funcionamiento en GNU/Linux:

Ejemplo de funcionamiento en Windows:


La librería USPP

Existen otras librerías de acceso al puerto serie en Python. Una de ellas es la librería USPP desarrollada por Isaac Barona. Soporta las plataformas Linux, Windows y MacOS. La razón por la que he hecho estos ejemplos utilizando pyserial en vez de USPP es que desconocía su existencia hasta hace apenas dos días antes de la publicación de esta documentación. Tiene la ventaja de que permite realizar comunicaciones usando la norma RS-485, que es half-duplex. En este modo se gestiona automáticamente la dirección de la transferencia usando la línea RTS.

También es muy fácilmente portable a otras plataformas. ¡Impresionante trabajo Isaac! Gracias por tu trabajo y por liberarlo para que todos lo podamos usar. ;-)


Download

Para descargar

pyserial-ejemplos.zip

Todos los ejemplos: scan.py, sg-eco1.py, sg-eco2.py y miniterm.py



Documentación


Autores


Licencia


Creative Commons License This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 Spain License

Este proyecto tiene una licencia libre. Se permite su copia, modificación y distribución, bajo los términos de la licencia Creative commons.

Todo el software tiene licencia GPL.




Créditos:


Agradecimientos


Noticias


[Índice de cuadernos técnicos]

Juan González

IEAROBOTICS