Arte conceptual de Toby Shelton para la película Cómo entrenar a tu dragón de DreamWorks Animation. |
Opciones para programar al Arduino
Partimos primero del supuesto de que tenemos una computadora anfitriona (con Windows, Linux o MacOS) conectada a un Arduino a través de un cable USB tipo A-B (como el que usamos comúnmente para conectar una computadora a una impresora), tal como se muestra en la siguiente figura:Arduino conectado a la computadora anfitriona a través del cable USB. |
A partir de esta configuración, hay dos lugares en donde un programa puede ser ejecutado:
- Directamente en el Arduino.
- En la computadora anfitriona.
En la opción 2, por otro lado, se instala en el Arduino un firmware que permite que un programa corriendo en la computadora anfitriona controle las acciones del Arduino a través del intercambio de datos vía la conexión USB. El firmware que usualmente se utiliza con este fin se llama Firmata.
Para la opción 1 comúnmente se utiliza el lenguaje de programación C++ junto con el ambiente de desarrollo integrado (IDE) de Arduino. Una ventaja de este esquema es que, una vez cargado el programa en el Arduino, es posible retirar la computadora anfitriona por completo. Dado que la conexión USB sirve también como fuente de alimentación, es necesario suplir al Arduino de una fuente alterna. Por ejemplo, es posible conectar al Arduino a una pila de nueve voltios.
Arduino con pila de 9V como fuente de alimentación y sin conexión a la computadora anfitriona. |
En cuanto a la opción 2, ésta tiene la desventaja fundamental de que nunca podemos retirar la computadora anfitriona; sin embargo, tiene dos ventajas significativas:
- Ya que nuestros programas corren en la computadora anfitriona y no directamente en el Arduino, no estamos restringidos a tener que usar C++. Podemos usar cualquier lenguaje de programación en la que exista una interfaz con Firmata: Processing, Pascal, Perl, C#, PHP, Java, JavaScript, Clojure, Ruby y por su puesto Python, por mencionar algunos.
- El código de nuestros programas no está limitado al tamaño de la memoria flash del microcontrolador, sino al tamaño de la memoria de la computadora anfitriona (kilobytes vs. gigabytes).
Instalación del software
Hay que seguir estos tres pasos:- Descargar e instalar el software de Arduino, según el sistema operativo de la computadora anfitriona, tal como se describe en la página Comienza a usar Arduino. Al momento de configurar el IDE, hay que anotar el puerto serie (serial port) al que se conecta el Arduino, ya que más adelante haremos referencia a éste. Según el sistema operativo, el puerto serie puede ser algo así como
COM3
(Windows),/dev/ttyACM0
(Linux) o/dev/tty.usbserial
(MacOS). - Descargar Firmata en el Arduino. En el IDE de Arduino seleccionar
File
del menú principal. De ahí seleccionar:Examples/Firmata/StandardFirmata
.
Posteriormente, presionarCtrl-U
para compilar y copiar el código de Firmata al Arduino. Después de un momento debe aparecer el texto “Done uploading” en la barra de mensajes del IDE. - Descargar e instalar la biblioteca pyFirmata en la computadora anfitriona. Esta biblioteca permite que un programa de Python, corriendo en una computadora anfitriona, se comunique vía USB con un Arduino corriendo Firmata. Desde una terminal (posiblemente con privilegios de administrador), teclear:
pip install pyfirmata
Si el sistema de administración de paquetes de Pythonpip
no está instalado, referirse a la siguiente liga: http://pip.readthedocs.org/en/latest/installing.html. En algunos sistemas en necesario usar el comandopip3
en lugar depip
para instalar bibliotecas de Python 3.
Resumen del API de pyFirmata
NOTA: Todo el código presentado aquí fue probado con Python 3.4.Para comenzar a usar pyFirmata debemos importar el paquete correspondiente al inicio de nuestro programa:
import pyfirmata
Podemos determinar qué versión de pyFirmata estamos usando:
print('pyFirmata version:', pyfirmata.__version__)A continuación creamos un objeto que representa nuestra placa (board) de Arduino. Para ello necesitamos indicar como cadena de caracteres el puerto serie que anotamos durante la configuración del IDE (
'/dev/ttyACM0'
en mi caso, ya que estoy usando Linux):
placa = pyfirmata.Arduino('/dev/ttyACM0')
Con el objeto referido por la variable placa
podemos determinar la versión de Firmata que está usando nuestro Arduino. El método get_firmata_version()
devuelve una tupla con dos valores: la versión mayor y la versión menor. Podemos utilizar una asignación paralela para extraer los valores de la tupla en dos variables:
v_mayor, v_menor = placa.get_firmata_version() print('Firmata version mayor:', v_mayor) print('Firmata version menor:', v_menor)Al correr estas instrucciones, la salida en mi sistema me indica que la versión mayor es 2 y la versión menor es 3, por lo que el número completo de versión es 2.3.
El método
get_pin()
sirve para activar un pin en el Arduino, configurándolo según la cadena que se le envía como argumento. Dicha cadena está compuesta de a
o d
(para indicar que el pin es analógico o digital), el número de pin, y el modo (i
para entrada, o
para salida, p
para PWM). Estos tres elementos se separan entre sí usando un carácter de dos punto (:
). Por ejemplo d:12:o
indica que el pin 12 es una salida digital. Este es un ejemplo de cómo se utiliza el método:
salida = placa.get_pin('d:12:o')
El siguiente ejemplo activa el pin 8 del Arduino como una entrada digital.
entrada = placa.get_pin('d:8:i')
enable_reporting()
sobre el objeto que representa el pin de entrada para poder leer las señales recibidas:
entrada.enable_reporting()Si se utilizan uno o más pines de entrada es necesario crear un thread iterador, de lo contrario la placa puede seguir enviando datos por la conexión serial hasta producir un desbordamiento. Para crear dicho thread usamos la siguiente instrucción:
pyfirmata.util.Iterator(placa).start()Para escribir a un pin de salida digital, usamos el método
write()
enviando como argumento False
(0V) o True
(5V), según la cantidad de voltaje que deseemos producir como salida. Ejemplo:
salida.write(True)
En lugar de False
y True
se puede usar 0
y 1
, respectivamente.Usamos el método
read()
para leer de un pin de entrada digital. Este método devuelve 0
si el voltaje de entrada es menor a 2.5V, o 1
si es mayor a 2.5V. Por ejemplo:
x = entrada.read()Posteriormente, podemos usar la variable
x
en una instrucción condicional (if
) para determinar qué valor efectivamente se leyó.Para pausar nuestro programa por una cierta cantidad de tiempo se recomienda usar el método
pass_time()
sobre el objeto que representa nuestra placa de Arduino. Se le envía como argumento el número de segundos que deseamos que dure la pausa. La siguiente porción de código detiene el programa en curso durante medio segundo:
placa.pass_time(0.5)
Por último, para terminar nuestro programa de manera limpia, se debe invocar el método exit()
así:
placa.exit()
Un ejemplo completo
Realicemos ahora un pequeño proyecto que nos permita integrar todo lo que describimos en la sección anterior. Vamos a usar un botón para controlar el prendido y apagado de un LED.Además del Arduino Uno conectado vía USB a la computadora anfitriona, vamos a requerir el siguiente hardware:
- Un protoboard.
- Un botón o pulsador (push button).
- Un LED (diodo emisor de luz).
- Una resistencia de 330Ω (bandas naranja, naranja, café).
- Una resistencia de 10KΩ (bandas café, negro, naranja).
- Cinco cables conectores.
Vista de protoboard Fritzing para el LED controlado por un botón. |
Usando un par de cables, conectamos un pin de tierra (GND) y un de pin de 5V del Arduino a los buses respectivos de alimentación negativa (línea azul) y positiva (línea roja) del protoboard.
El ánodo del LED (la patita larga) se conecta al pin 12 del Arduino, mientras que el cátodo (la patita corta) se conecta a la resistencia de 330Ω. El otro extremo de esta resistencia se conecta a tierra (bus negativo).
El push button se coloca de tal forma que un par de patitas quede a la izquierda y el otro par a la derecha del canal central del protoboard. Conectamos una de las patitas inferiores del botón al bus positivo. Una de las patitas superiores del botón se conecta a una resistencia de 10KΩ, mientras el otro extremo de la resistencia se conecta a tierra (bus negativo). La patita superior que queda del botón se conecta al pin 8 del Arduino. Dada esta disposición, se dice que la resistencia es de tipo pull-down. En términos prácticos esto significa que el valor que va leer el pin 8 por omisión (cuando el botón no está presionado) es 0V, y 5V cuando el botón está presionado.
Físicamente las conexiones de nuestros componentes electrónicos se ven como se muestra en la siguiente foto:
Vista física del LED controlado por un botón. |
El programa completo en Python 3.4 se muestra a continuación:
# Archivo: led_boton.py import pyfirmata placa = pyfirmata.Arduino('/dev/ttyACM0') print('Firmata version: %d.%d' % placa.get_firmata_version()) print('pyFirmata version:', pyfirmata.__version__) pyfirmata.util.Iterator(placa).start() entrada = placa.get_pin('d:8:i') entrada.enable_reporting() salida = placa.get_pin('d:12:o') try: encendido = False while True: if entrada.read(): encendido = not encendido salida.write(encendido) placa.pass_time(0.2) finally: salida.write(False) placa.exit()Para correr el programa, requerimos ejecutar el siguiente comando desde una terminal en el mismo directorio donde radica el archivo
led_boton.py
:
python3 led_boton.pyCuando corremos el programa, el LED se prende cuando presionamos el botón y se apaga cuando lo volvemos a presionar, y así indefinidamente hasta que presionemos Ctrl-C para terminar el programa.
Más información
- La documentación de pyFirmata: http://pyfirmata.readthedocs.org/en/latest/index.html
- Siete ejemplos completos de cómo usar PyFirmata: https://bitbucket.org/fab/pyfirmata/src/96116e877527/examples/
- Lista de lenguajes de programación que se pueden usar con Firmata: http://firmata.org/wiki/Download