Cómo conectar Arduino y Raspberry Pi por comunicación Serial

En este pequeño tutorial veremos cómo conectar una tarjeta Arduino a una tarjeta Raspberry Pi por comunicación Serial, encontrarás códigos de programación para tus primeras pruebas.

La comunicación UART o comunicación serial se establece con 2 señales digitales, por cada dispositivo: «TX», que es la que transmite datos y «RX», que es la que recibe datos. Sin embargo es posible emular un puerto serie a través de una clase del protocolo USB, esto lo podemos ver implementado en la plataforma Arduino cuando desplegamos el monitor serie y visualizamos mensajes que llegan desde nuestro Arduino. Lo que sucede es que la computadora recibe la información del puerto serie a través del USB, es decir a través de un puerto serie emulado.

En este ejemplo aprovecharemos que tanto la tarjeta Arduino como las tarjetas Raspberry Pi tienen la capacidad de emular puertos serie a través del USB, de tal manera que el diagrama de conexiones se reducirá a conectar la tarjeta Arduino a la Raspberry Pi con el cable USB. No utilizaremos componentes adicionales a ambas tarjetas porque el objetivo será que podamos controlar, desde la Raspberry Pi, el led integrado en pin 13 de la tarjeta Arduino Uno.

El ejercicio consiste entonces en controlar el LED integrado al pin #13 del Arduino desde la Raspberry Pi. Para ello ejecutaremos un script de python3 que solicite al usuario insertar un comando para ser enviado al Arduino a través del puerto serie, éste su vez, estará programado para recibir todos los comandos respondiendo solo a 2: «on» para encender el LED y «off» para apagar el LED.

Componentes necesarios

  • Raspberry Pi, cualquier modelo
  • Arduino UNO

Conexiones

Raspberry Pi – Arduino Uno – Serial

Código de Arduino – Ardiuno Uno

Primero cargamos el siguiente código a nuestro Arduino. Una vez que nuestro Arduino esté programado, conectamos el Arduino a la Raspberry Pi con un cable USB de Arduino y procedemos a programar nuestra Raspberry Pi.


String inputString = "";      // Cadena para guardar el comando recibido
bool stringComplete = false;  // Bandera boleana que nos indica cuando el comando fue recibido y podemos compararlo con los 2 comandos válidos

void setup() {
  pinMode(13, OUTPUT);
  // initialize serial:
  Serial.begin(9600);
  // reserve 200 bytes for the inputString:
  inputString.reserve(200);
}

void loop() {

  if (stringComplete) {//El comando fue recibido, procedemos a compararlo
    
    if (inputString.equals("off") ){//Si el comando es "off"
      digitalWrite(13,0);
      Serial.println("Apagado");
    }
    else if (inputString.equals("on") ){//Si el comando es "on"
      digitalWrite(13,1);
      Serial.println("Encendido");
    }
    inputString = "";//Limpiamos la cadena para poder recibir el siguiente comando
    stringComplete = false;//Bajamos la bandera para no volver a ingresar a la comparación hasta que recibamos un nuevo comando
  }

}

void serialEvent() {
  
  while (Serial.available()) {//Mientras tengamos caracteres disponibles en el buffer
    char inChar = (char)Serial.read();//Leemos el siguiente caracter
    if (inChar == '\n') {//Si el caracter recibido corresponde a un salto de línea
      stringComplete = true;//Levantamos la bandera 
    }
    else{//Si el caracter recibido no corresponde a un salto de línea
      inputString += inChar;//Agregamos el caracter a la cadena 
    }
  }
}

Pasos previos a ejecutar el código de la Raspberry Pi

1.- Habilitar comunicación serial en la Raspberry Pi

Para que podamos ejecutar un programa que intercambie información por el puerto Serie en nuestra Raspberry Pi, debemos habilitar el hardware correspondiente en dicha tarjeta. Esto lo podemos hacer de manera sencilla con ayuda de la herramienta de configuración raspi-config, si no has utilizado esta herramienta antes da click aquí para ver el paso a paso. Una vez que termines regresa para ejecutar el código.

2.- Identificar el nombre asignado al puerto serie de Arduino en Raspbian

En raspbian los puertos seriales aparecen listados, junto con otros elementos, en el directorio «/dev/» del sistema. Utilizaremos 3 comandos en la terminal para conocer el nombre asignado al puerto serie de la tarjeta Arduino.

I.- Con este primer comando guardamos, en un documento de texto, la lista de todos los elementos que se encuentran en el directorio «/dev» cuando el Arduino no está conectado a la tarjeta Raspberry Pi. Por lo anterior es importante ejecutar el comando cuando el Arduino no está conectado a la Raspberry Pi.

[email protected]:~ $ ls -1 /dev > dev1.txt

II.- Con el segundo comando guardamos, en un documento de texto, la lista de todos los elementos que se encuentran en el directorio «/dev» cuando el Arduino si está conectado a la tarjeta Raspberry Pi. Por lo anterior es importante ejecutar el comando cuando el Arduino si está conectado a la Raspberry Pi.

[email protected]:~ $ ls -1 /dev > dev2.txt

III.- Por último ejecutamos un comando con el que comparamos los dos archivos, obteniendo como resultado los elementos que están en el segundo archivo pero no en el primero. En el resultado identificamos el elemento que comienza con «tty» y el nombre de nuestro puerto será entonces, el elemento identificado precedido de «/dev/» teniendo la forma: «/dev/tty…». En nuestro caso el nombre del puerto es «/dev/ttyACM0».

[email protected]:~ $ diff dev1.txt dev2.txt

Código de Python3 – Raspberry Pi

Copiamos el siguiente código a un script de python en nuestra Raspberry Pi y lo ejecutamos con Python3. Al ejecutarlo, el programa solicitará ingresar un comando, el comando será enviado al Arduino al oprimir la tecla «Enter». Con el comando «on» se enciende el led integrado del Arduino y con el comando «off» se apaga.


import time
import serial


ser = serial.Serial("/dev/ttyACM0", baudrate=9600) #Modificar el puerto serie de ser necesario

try:
    while True:
        comando = input("Ingresar comando (on/off): ")
        comando = comando + "\n"
        comandoBytes = comando.encode()
        ser.write(comandoBytes)
        time.sleep(0.1)
        read = ser.readline()
        print(read)

except KeyboardInterrupt:
    print("\nInterrupcion por teclado")
except ValueError as ve:
    print(ve)
    print("Otra interrupcion")
finally:
    ser.close()

¡Sigue explorando!