C++ & Python: comunicando la Raspberry Pi y Arduino por el puerto USB

Conectando Arduino y Raspberry Pi con un cable USB..

Para algunas cosas va muy bien una Raspberry Pi, para otras va muy bien Arduino, con lo que combinarlos es una buena idea.. 🤔 Es decir, en un proyecto en donde haya que tener capacidad de procesamiento, red, hacer programas con bastante lógica, bases de datos, etc.. conviene tener disponible un sistema completo o parcialmente completo similar a un ordenador, la Raspberry Pi. Por otro lado, para trabajar manejando sensores y actuadores, señales analógicas, señales digitales moduladas en pulso o sin modular.. conviene tener disponible un microcontrolador, Arduino 😜

Se puede siempre tratar de prototipar todo con una Raspberry, o todo con Arduino, pero no es la mejor idea. Dependerá de las funcionalidades del proyecto que será más sencillo construir con una cosa, con otra, o con las dos.

Este post es un howto sobre cómo hacer que hablen una Raspberry Pi y un Arduino. Simplemente en el siguiente codekata Arduino se pone a la escucha en espera de acciones en el puerto USB. Por el otro lado Raspberry Pi, o un dispositivo compatible con GNU/Linux, conectado al mismo USB, y mediante Python, le envía los mensajes.

Al grano, el código fuente en C++ para Arduino

El punto de partida en Arduino, es la configuración del puerto serie USB y nos ponemos a la escucha:

void setup() {
    Serial.begin(9600);
}

void loop() {
    String request;
  
    while(Serial.available()) {
        request = Serial.readStringUntil("\n");
        delay(1000);
    }
}

Éste código anterior simplemente inicializa el puerto serie USB a 9600 baudios. Luego en el bucle principal del microcontrolador simplemente comprueba si hay algo disponible para leer en el puerto serie USB. En éste caso, lee los datos hasta el final de línea y espera 1000 milisegundos antes de continuar.

Desarrollando un poco más el código fuente anterior podemos llegar a algo como lo siguiente. El siguiente código inicializa el pin 13 que es el led que viene incorporado en la tarjeta. En el arranque hará que parpadee el led, y escribe en el puerto serie USB ‘Arduino>> I’m ready!’. Acto seguido se pone a la escucha repitiendo el bucle contínuamente en el microcontrolador ATmega328:

void setup() {
    Serial.begin(9600);
    pinMode(13, OUTPUT);

    ledBlink(50);
    Serial.println("Arduino>> I'm ready!");
}

void ledBlink(int timeDelay) {
    for(int i=0; i<=9; i++) {
        digitalWrite(13 , HIGH);
        delay(timeDelay);
        digitalWrite(13 , LOW);
        delay(timeDelay);
    }
}

void loop() {
    String request, response;
  
    while(Serial.available()) {
        // Read the serial port USB..
        request = Serial.readStringUntil("\n");
      
        // Generate the response..
        response = "Arduino>> Hello! Message received!";
        Serial.println(response);
        
        ledBlink(100);
        delay(2000);
    }
}

Cada vez que recibe un mensaje, en vez de realizar lo que queramos lo que va a hacer de momento es simplemente responder en el puerto USB la frase ‘Arduino>> Hello! Message received!’ y hacer que el led parpadee para saber nosotros que le ha llegado un mensaje.

Esto lo cargamos en Arduino, y ya podemos recibir mensajes de la Raspberry Pi. Así podremos disparar las acciones en Arduino, y devolver las respuestas a la Raspberry Pi. Puede ser interesante aquí tener una serie de sensores de temperatura, humedad, niveles de agua, de fuego, detectores de movimiento, etc.. todos estos sensores son muy fáciles de leer desde Arduino, y podremos devolverle los resultados en mensajes a la Raspberry Pi y que los guarde o que haga otras cosas. No sé, por ejemplo, que la Raspberry nos diga por los altavoces la temperatura actual..

El código fuente para Raspberry Pi en Python

En el otro lado, mediante Python es sencillo usar el puerto serie USB. Un código básico para empezar puede ser el siguiente:

import serial
import time
import sys

ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.5)
ser.flush()
print("Configed for " + ser.name)

print('Sending something to Arduino..')
ser.write(b"Linux>> Hi!\n")
print('Sent! Now waiting..')
time.sleep(1)

print('Reading from USB..')
line = ser.readline().decode('utf-8').rstrip()
print(line)
print('Closing serial USB..')
ser.close()

Entonces, si todo ha ido bien, en el apartado anterior hemos cargado en Arduino el programa anterior. Ahora podemos desde línea de comandos en nuestro PC, o ya directamente en la Raspberry Pi, lanzar este script en Python para lanzarle mensajes a Arduino. Este programa en Python siempre envía el mensaje ‘Linux>> Hi!\n’. Ya a partir de aquí el sistema básico de comunicación por USB está montado.

Ponemos el script en Python en un fichero y desde línea de comandos podemos lanzarlo tal que así:

python3 sendSMSArduinoUSB.py

Debemos de tener instalado en Python3 el módulo Pyserial. Lo podemos instalar así si no lo hemos hecho:

pip3 install pyserial

Unas pocas explicaciones

Si todo ha ido bien, simplemente nos tiene que devolver respuestas como las siguientes:

Mira que la primera vez leemos la primera línea que es la que envió Arduino al puerto USB diciendo ‘Arduino>> I’m ready!’. En la segunda ejecución le puse la línea ‘ser.flush()’ en el programa en Python para vaciar de datos el puerto USB antes de empezar la comunicación.

Es confuso a veces que puede pasar que se envíen varios mensajes y no se reciban. Entonces quedan ahí en el puerto USB en espera. O también puede pasar que sólo leemos la primera línea, con lo que el resto de líneas quedan pendientes de lectura.. ya a partir de aquí, tendremos que definir el protocolo de comunicación que queramos según lo que queremos hacer, no hay una norma fija a la que atenerse 🤔 si llegas a esto puedes resetear, desenchufar el cable, y volver a empezar de cero la comunicación..

Terminando

Sólo me queda decir que estoy subiendo los códigos a Github:
https://github.com/jaimenj/playing-with-arduino
https://github.com/jaimenj/playing-with-raspberrypi

Otro día más.. ¡Un saludo!

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

2 ideas sobre “C++ & Python: comunicando la Raspberry Pi y Arduino por el puerto USB”