(Última actualización 21/8/2019)
¡Hola, seguidores! A petición de uno de mis contactos humanos, hoy haré un breve tutorial sobre interacción entre Arduino y Python utilizando pySerial.
En la primera parte intentaremos controlar un LED mediante comandos que enviaremos de nuestro ordenador a Arduino utilizando un sencillo programa en Python. En la segunda parte moveremos un pequeño servo enviando un números entre 0-180 por Serial.
El concepto
Conceptualmente, el tutorial de hoy es muy sencillo. Tenemos un código en python ejecutándose dentro de nuestro ordenador que envía mensajes (carácteres) a la placa Arduino.
En el primer ejemplo, la placa Arduino estará cargada con un programa leerá estos mensajes y encenderá el LED 13 si recibe el carácter ‘e’, y lo apagará si recibe el carácter ‘a’. ¿Fácil, no?
En el segundo ejemplo, Arduino convertirá el mensaje que le llegue a un número entero y lo pasará como parámetro a la función serial.write().
Material
- Un ordenador con python, pySerial y Arduino IDE
- Cable USB
- Placa Arduino
- Díodo LED (si no queremos utilizar el que lleva la placa Arduino)
- Servo
- Batería
1. Controlar un LED con Python
Primero escribiremos el código en python que deberemos ejecutar en nuestro ordenador. Éste código lee un carácter introducido por el usuario y lo envía por Serial a Arduino. Si se escribe una ‘s’, salimos del programa. Recuerda cambiar el ‘/dev/ttyACM0’ de la línea 4 por el puerto de tu Arduino.
""" PROGRAMA DE PYTHON Pide un caracter al usuario y lo envia por Serial. """ import serial #Inicializamos el puerto de serie a 9600 baud ser = serial.Serial('/dev/ttyUSB0', 9600) #Mostramos una chuleta con todos los comandos print("Lista de comandos: \n 'e' - Encender led \n 'a' - Apagar led \n 's' - Salir del programa\n") #Pedimos un caracter al usuario print("Introduce un caracter: ") #Guardamos este caracter en una variable entrada = raw_input() #Introduciendo 's' salimos del bucle while entrada != 's': #Enviamos el caracter por serial, codificado en Unicode ser.write(str(entrada).encode()) #Mostramos el caracter enviado por pantalla print("He enviado: " + str(entrada)) #Y pedimos un nuevo caracter al usuario print("Introduce un caracter: ") entrada = raw_input()
Guardamos este código en un fichero con extensión ‘.py’ . Ahora habrá que escribir el código para Arduino, que sencillamente encenderá un LED al recibir ‘e’ por Serial y lo apagará al recibir ‘a’.
/* CODIGO PARA ARDUINO Enciende el LED 13 al recibir el caracter 'e' por Serial, y lo apaga al recibir el caracter 'a' */ #define LED 13 int mssg = 0; //variable para guardar el mensaje void setup() { pinMode(LED, OUTPUT); //establecemos el pin D13 como salida Serial.begin(9600); //inicializamos Serial } void loop() { if (Serial.available() > 0) { mssg = Serial.read(); //leemos el serial if(mssg == 'e') { digitalWrite(13, HIGH); //si entra una 'e' encendemos el LED } else if(mssg == 'a') { digitalWrite(13, LOW); //si entra una 'a' apagamos el LED } } }
Y si habéis seguido todos los pasos debería funcionar correctamente. Ahora ya estamos preparados para controlar algo más complejo como puede ser un Servo o un actuador por el estilo.
2. Controlar un Servo
En esta segunda parte aprenderemos a mover un servo con Pyserial. El programa de Python enviará números enteros entre 0 y 180 (correspondientes al ángulo de giro) y la placa Arduino los leerá y moverá el servo.
Tendremos que hacer estas conexiones entre el Servo y Arduino. Además, recomiendo alimentar la placa Arduino con una batería.
- Arduino Vin → Servo +
- Arduino GND → Servo –
- Arduino D3 → Servo Sig.
En primer lugar modificaremos el código de Python para que sólo acepte números entre 0-180 y el carácter ‘s’ para salir.
""" PROGRAMA DE PYTHON Pide un entero entre 0-180 al usuario y lo envia por Serial. """ import serial #Inicializamos el puerto de serie a 9600 baud ser = serial.Serial('/dev/ttyUSB0', 9600) #Mostramos una chuleta con todos los comandos print("Introduce un numero entre 0-180, o 's' para salir del programa\n") #Pedimos un caracter al usuario print("Introduce un numero entre 0-180: ") #Guardamos este caracter en una variable entrada = raw_input() #Introduciendo 's' salimos del bucle while entrada != 's': #Si el numero es valido, se envia por serial if(int(entrada) >= 0 and int(entrada) <= 180): #Enviamos el numero por serial, codificado en Unicode ser.write(str(entrada).encode()) #Mostramos el caracter enviado por pantalla print("He enviado: " + str(entrada)) #Si el numero no es valido, mostramos un mensaje de error else: print("Error: introduce un numero entre 0-180, o 's' para salir") #Y pedimos un nuevo numero al usuario print("Introduce un numero entre 0-180: ") entrada = raw_input()
En este pequeño código de Arduino conectamos el servo al pin D3 y utilizamos la instrucción Serial.parseInt() para convertir el mensaje que llega por Serial directamente a un número entero.
/* CODIGO PARA ARDUINO Mueve un servo segun el valor recibido por Serial */ #include <Servo.h> #define SER 3 //Pin para el servo Servo servo; //Objeto servo int mssg; //Variable para guardar el mensaje recibido por serial void setup() { //Inicializamos el servo y el Serial: servo.attach(SER); Serial.begin(9600); } void loop() { if (Serial.available() > 0) { mssg = Serial.parseInt(); //Leemos el serial servo.write(mssg); //Mover el servo delay(500); } }
¡Y ya está! Ahora podemos controlar el servo a través de nuestro ordenador, enviando la posición por Serial.
hola disculpa quiero hacer el juego de la batalla naval con el uso de puerto serie , y asi contyrolar por cordenadas una matriz de leds me puedes dar una idea de como hacerlo , ya tengo mi codigo de la batalla , solo quiero saber el metodo de que interactuen y que el arduino al meter en pantalla de mi pc una cordenada el led seleccionado se prenda o apague
¡Hola, rodrigo! Disculpa la tardanza.
Podrías enviar un string de la forma XXYY a tu placa Arduino, dónde XX es la coordenada x e YY es la coordenada y.
Después puedes leer este mensaje con Serial.parseInt(), que lo convertirá en un entero, y lo guardas en una variable “mensaje”.
Por último calculas ‘mensaje/100’ para tener la coordenada X, y ‘mensaje%100’ para obtener la coordenada Y.
Hola
Me podrían ayudar estoy tratando de controlar unos motores con Arduino dependiendo de los valores que me dé pyton pero no puedo hacer el enlace
¡Hola! Cuál es el problema con el enlace? Te sale algún mensaje de error?
super interesante o sea que con python se puede crear un robot que reciba ordenes enviandolas por serial y que reciba sensores de arduino para quiza montar con alguna otra libreria de inteligencia artificial unas neuronas para que los sensores del robot vayan mejor segun los datos que nos va enviando :/ ???
Sip, podrías usar una librería como PyBrain para construir, entrenar y calcular el output de una red neuronal en tu PC y después enviar las instrucciones a tu robotito a través de Serial (o Bluetooth, radio, etc).
hola amigo una pregunta , si mi idea es recibir una lectura desde cierto controlador y analizarla con una lectura teoria y mostrar en pantalla (interfaz usuario) como haria eso? es posible comunicar esto por ejemplo con un formulario aparte? y muestre eso en la pantalla del pc
Hola RaiRayo! Entiendo que me estás pidiendo como leer las lecturas que envía por ejemplo Arduino, y mostrarlas con python verdad? Es tan fácil como que Arduino envíe la lectura por serial como se hace habitualmente. Después, Python puede leer y guardar esta lectura que llega del puerto serial con: lectura = ser.readline() lectura = lectura.decode("ascii") La instrucción ser.readline() leerá el puerto serial hasta encontrar un final de línea, mientras que lectura.decode(“ascii”) convertirá esta lectura a texto. Aunque no estoy 100% seguro de si haría falta decodificarlo en tu caso… Si quieres construirte una interfaz de usuario con botones y… Leer más »
Hola amigo y como seria para que la comunicacion sea en ambos sentidos, es decir, usar sensores y mandar el valor captado por el sensor a python y dependiendo de ese valo se envie un valor a arduino, es decir, que la comunicacion sea para ambos lados.
Hola! Con la instrucción de python ser.read() puedes leer el puerto de serial y guardar el mensaje en una variable. Sólo tienes que hacer que ambos (la placa Arduino y el programa Python) lean el puerto Serial y a la vez escriban en él.
como lo aria para que me corra en blender .!!!
Aquí tienes ^^
http://robologs.net/2016/02/29/tutorial-de-arduino-y-blender/
Hola gracias por el tutorial esta muy bien explicado.
tengo una duda se pudiera enviar el código de arduino por medio de python y grabarlo en la placa? sin usar el ide de arduino
No, Arduino no se puede programar directamente en Python.
me da este error =(
hola me gustaria saber como le podria acer para de python enviar una señal al arduino pero que en este caso encienda o apague un servo
¡Hola! Puedes enviar un string de números por Serial que se corresponda al ángulo del Servo. Arduino lo puede convertir a entero con Serial.parseInt() y lo después lo pasa como parámetro a la función Serial.write().
¡Un saludo!
Hola! Quería saber si puedes ayudarme con una duda! Necesito hacer una interacción entre varios botones y leds y no sé como hacerlo! Me imagino que con Python pero no lo se….
Lo que necesito es que, a modo de ejemplo, si tengo 6 botones y 6 leds, y aprieto el boton #1 y el boton#2 (al mismo tiempo) que se prenda cierto led (asumo que para que el arduino decida qué led prender necesito un programa en python, no?)… No se si me entiendes 🙁
Para eso no necesitas python! Mírate este ejemplo para aprender como guardar el valor de un botón dentro de una variable con Arduino (https://www.arduino.cc/en/Reference/DigitalRead).
Lo que tienes que hacer es guardar el valor de cada botón dentro de una variable (boton1, boton2, etc) y después ir mirando cada combinación de botones con un condicional.
if(boton1 == HIGH and boton2 == HIGH){
digitalWrite(led1, HIGH);
}
if(boton2 == HIGH and boton3 == LOW)
{
digitalWrite(led2, HIGH);
}
Y así con todos los botones. Haces este programa y lo cargas a tu placa a través de la IDE. 🙂
Ya gracias!! Y tengo otro problema!! Necesito usar 9 botones y 15 leds, es mucho y no se que hacer (por el numero limitado de pines) me podrias ayudar con eso??
¡Hola, Bernie! Si quieres controlar más dispositivos que pines tiene Arduino, vas a necesitar un multiplexor: https://es.wikipedia.org/wiki/Multiplexor
Solo sirve para muchas entradas? O también para muchas salidas?
Sirve para ambos.
Ah y gracias! jajaja
Tal vez esta pregunta parezca súper estúpida, pero… ¿Dónde descargo la librería? y ¿Dónde la pongo en Python?
¡Hola! En la web de pySerial hay todas las instrucciones para su instalación:
http://pyserial.readthedocs.io/en/latest/pyserial.html
Hola! tengo una consulta.. cuando recién establezco la comunicación serial debo especificar de antemano el puerto COM (o dev) en el cual se encuentra mi arduino… en python existe alguna forma de “buscarlo” de forma automática.. por ejemplo si antes de la experimentación no conozco en que puerto esta el arduino, que mi programa lo busque y lo especifique?? Muchas gracias y el código de la página funciona 🙂
¡Hola Andrés! Mírate este hilo, el primer comentario tiene un código que puede ayudarte a listar todos los puertos Serial de tu ordenador:
http://stackoverflow.com/questions/12090503/listing-available-com-ports-with-python
Hola que tal si quiera crear mi propio protocolo de comunicación sin usar la librería serial como sería?? Espero que me puedas ayudar
como puedo hacer una interfaz grafica para este programa de encender el led utilizando php llamando phyton y arduino un ejemplito porfa con este mismo ejemplo
¿Con php llamando a python? Buff.. pues ni idea. Tendrás que googlearlo.
hola, yo quisiera ejecutar con otra función que recibe números al azar y los compara con otro, y si son iguales necesito que escriba X y encienda un led de cinco que tienen que ser. Lo enciende según la posición de donde este la X. Como podría hacer eso? Gracias de antemano
Necesitas importar la librería random
import random
Para generar un número al azar (por ejemplo, entre 0 y 5) se hace así:
mi_numero = random.randint(0,5)
Entonces sólo tendrías que compararlo con el otro número mediante un if y, si coinciden, envíar la instrucción de encender.
Genial robologs! si yo quisiera transportar una palabra completa o algún número de más de 1 dígito a arduino ¿cómo haría?. Un saludo fraterno y terrícola.
¡Hola Diego! Pues muy fácil: cambias el código de Arduino por este: String orden; void setup() { pinMode(13, OUTPUT); Serial.begin(9600); } void loop() { while(Serial.available() >= 1) { orden = Serial.readString(); if(orden == "encender") { digitalWrite(13, HIGH); } else if(orden == "apagar") { digitalWrite(13, LOW); } } } Fíjate que utilizamos la función Serial.readString(), que lee toda una cadena de carácteres en vez de uno solo. Después se compara el string leído con “encender” y “apagar” con el operador “==” (es importante saber que algunos lenguajes no permiten comparar strings simplemente con “==”). Después cambias el código en Python para… Leer más »
buen tutorial, muchos saludos 🙂
¡Gracias Pablo!
para los que no le sirve el codigo lo tengo actualizado y corregido:
import serial
ser = serial.Serial(‘COM4’, 9600)
print (“Introduce un caracter (‘s’ para salir): “)
entrada = input()
while entrada != ‘s’:
ser.write(str(entrada).encode())
print (“He enviado: “, entrada)
print (“Introduce un caracter (‘s’ para salir): “)
entrada = input()
Hola estoy empezando con python.
me da un error en ser.write (str (entrada).encode ())
Hola! Puedes enseñarme el mensaje de error que te da?
Hola, lo he hecho así pero me apare lo siguiente:
unicode strings are not supported, please encode to bytes: “b’a'”
Espero me puedas ayudar
¡Hola Eber! He añadido un pequeño cambio en el código de python que creo que solucionará tu problema.
Porque si hago esto en un archivo .py y lo hago correr no funciona, pero cuando lo escribo directo en la consola de python, si funciona?
import serial
ser = serial.Serial(‘/dev/ttyACM0′, 9600)
entrada = ’1′
ser.write(entrada)
Buenas, crisxp44!
Yo… he visto cosas que vosotros, los humanos, no creeriáis… Pero lo que me dices es indudablemente lo más raruno que he oído jamás. Pero vamos a intentar algo.
Al principio del programa importa también la librería import time.
Y después de ser.write(entrada) añade:
Si no funciona intenta añadir también, justo después de la línea 3 del código de Python:
Espero que funcione! 😀
Si esto no te funciona, intenta hacer otra cosa. Ejecuta el programa.py con una versión diferente de python. Escribe python en la terminal y pulsa tabulador dos veces para ver las versiones que tienes. Después escribe, por ejemplo:
python3.0 programa.py
Eso ocurre porque Arduino tarda 2 segundos en iniciar el sketch luego de comenzar la conexion serial. Cualquier dato que se envie durante los dos primeros segundos de iniciar la conexion en Python se perdera a Arduino. Siempre despues de iniciar la conexion serial se debe dar una pausa para que Arduino quede “en modo espera” por decirlo de una forma facil de entender. Espero que sirva la explicacion luego de tanto tiempo. Saludos