Comunicación entre Raspberry PI y Arduino por USB

Blog   /   18 Comentarios Standard Post

Raspberry Pi es una plataforma a tener en cuenta para el desarrollo de aplicaciones domóticas y de control. Sin embargo, Raspberry PI tiene una pequeña limitación en cuanto al número de entradas/salidas disponibles así como problemas relacionados con los tiempos de respuestas que se consiguen programando en python.

Una posible solución a esta limitación puede ser combinar el Raspberry Pi con Arduino y relegar todo el control hardware al Arduino y utilizar el Raspberry como controlador maestro. En esta entrada voy a hacer un simple ejemplo en que conecto mi Raspberry Pi con un Arduino a través de USB y mi Raspberry controla los puertos de salida del Arduino a través de comunicación serie.

Para ello, lo primero que vamos a hacer es crear un programa para nuestro Arduino que simplemente lee información del puerto serie y en función de la información leída actúa sobre los puertos (9 – 13) del Arduino poniendo a nivel alto o a nivel bajo. El programa que utilizamos se muestra a continuación.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
char incomingData;
String receivedCommand;
 
int stringToNumber(String thisString) 
{
   int i, value, length;
   length = thisString.length();
   char blah[(length+1)];
   for(i=0; i<length; i++)     {       blah[i] = thisString.charAt(i);    }    blah[i]=0;    value = atoi(blah);    return value; } void setup() {    Serial.begin(9600);    Serial.println("Arduino Ready");    pinMode(13, OUTPUT);    pinMode(12, OUTPUT);    pinMode(11, OUTPUT);    pinMode(10, OUTPUT);    pinMode(9, OUTPUT); } void loop() {    if (Serial.available() > 0) 
   {
       incomingData = Serial.read();
       receivedCommand+=incomingData;
       if (receivedCommand.length()==3)
       {
         digitalWrite(stringToNumber(receivedCommand.substring(0,2)),(receivedCommand[2]=='0')?LOW:HIGH);
         Serial.print("pin: ");
         Serial.print(receivedCommand.substring(0,2));
         Serial.print(" at level: ");
         Serial.println((receivedCommand[2]=='0')?"LOW":"HIGH");
         receivedCommand="";
       }
   }  
}

Veamos en detalle que hace este código. Primero declaramos algunas variables globales (líneas 1-2) luego nos encontramos con una función para convertir de String a int (lineas 4-16). Esta función la he conseguido desde este hilo. Luego llegamos a la función de configuración de Arduino donde inicializamos el puerto serie y configuramos los puertos del 9 al 13 como salidas digitales (Lineas 18-27). Finalmente llegamos a la función loop (Lineas 29-45).

La función loop escucha continuamente al puerto serie, y espera hasta recibir 3 caracteres. Una vez recibidos 3 caracteres simplemente divide la cadena de la siguiente forma: Los dos primeros caracteres codifican el puerto sobre el que quieres actuar y el tercer carácter codifica el estado que quieres fijar a ese puerto. Por ejemplo “121” sería poner el puerto 12 a nivel alto y por ejemplo “090” seria forzar un nivel bajo en el puerto 9.

Con esto ya terminamos el trabajo en el lado del Arduino. vamos ahora a trabajar en el lado del Raspberry. En este caso lo primero que tenemos que hacer es instalar las librerías para el control del puerto serie desde python. Para ellos ejecutamos el siguiente comando desde consola en nuestro Raspberry Pi:

1
sudo apt-get install python-serial

Con esto ya tenemos listo nuestro Raspberry Pi para trabajar con el puerto serie desde python. Lo único que nos queda es determinar que puerto utiliza nuestro Arduino cuando esta conectado al Raspberry Pi. Para ello antes de conectar el Arduino ejecutamos el siguiente comando

2
ls /dev/tty*

Y veremos que nos proporciona un listado de diferentes dispositivos. Luego simplemente conectamos el Arduino, volvemos a ejecutar el comando y veremos como aparecerá un dispositivo adicional. Nuestro Arduino!! En mi caso mi arduino aparece como: /dev/ttyACM0.

Con nuestro arduino identificado solamente tenemos que irnos a python y escribir el programa para controlar nuestro Arduino. en mi caso he hecho un ejemplo muy sencillo, mi código simplemente enciende y apaga el pin 9 cada segundo y a su vez también lee la información de realimentación que proporciona Arduino cuando cambia el estado del pin:

1
2
3
4
5
6
7
8
9
import serial
import time
ser=serial.Serial('/dev/ttyACM0',9600)
while 1:
        print(ser.readline())
        ser.write('091')
        time.sleep(1)
        ser.write('090')
        time.sleep(1)

Como resultado si todo funciona correctamente podemos obtener algo como la siguiente imagen en la consola de nuestro Raspberry Pi.

ScreenShot

Con estos sencillos pasos ya tenemos los dos dispositivos conectados y compartiendo información entre ellos. Llegados a este punto todavía podemos ir más allá y hacer que nuestro Raspberry pueda ser controlado a través de internet y de esa forma poder acceder a nuestro Arduino de forma totalmente remota, pero eso será ya el tema de otra entrada.

18 Comentarios en esta entrada

  1. Laury Llata dice:

    Hola Roberto,

    Me ha gustado mucho tu post pero no se como conectar a nivel de cableado ambos dispositivos.

    No me gustaria fundir alguno de los dos dispositivos, me puedes echar una mano????

    Mil gracias por tu ayuda

    • admin dice:

      Hola!!

      La conexión entre el Raspberry y el arduino no tiene problemas, simplemente conecta enciende el raspberry y conecta el Arduino al USB del raspberry.

      El Único cableado extraño que hay que realizar, es el de poner un condensardor para evitar que se reinicie el arduino cada vez que se envía un nuevo dato desde el raspberry. En este enlace esta explicado de forma detallada donde colocar el condensador http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

      Si tienes cualquier duda, pregunta sin problemas!!

      Saludos,
      Roberto.

  2. Miguel Angel dice:

    Al compilar tu codigo me da un error:

    Arduino: 1.5.4 (Mac OS X), Board: “Arduino Uno”

    sketch_mar22a.ino: In function ‘int stringToNumber(String)’:
    sketch_mar22a:9: error: ‘lt’ was not declared in this scope
    sketch_mar22a:9: error: expected `)’ before ‘;’ token
    sketch_mar22a:9: error: expected `;’ before ‘)’ token
    sketch_mar22a.ino: In function ‘void loop()’:
    sketch_mar22a:29: error: ‘gt’ was not declared in this scope
    sketch_mar22a:29: error: expected `)’ before ‘;’ token
    sketch_mar22a:29: error: expected `;’ before ‘)’ token
    sketch_mar22a:43: error: expected `}’ at end of input

    This report would have more information with
    “Show verbose output during compilation”
    enabled in File > Preferences.

    solo he copiado y pegado tu codigo, hace falta alguna libreria?

  3. CARLOS dice:

    Hola Roberto

    Muchas gracias por tu aporte me ha servido de mucho y he logrado hacer la aplicación que expusiste.

    Tengo una pregunta, es posible recibir datos del arduino y almacenar esos datos en la raspberry?? como por ejemplo medición de temperatura por arduino y esos datos almacenarlos en algún archivo en la raspberry.

    No se si me hago explicar

    muchas gracias por este gran aporte, espero que puedas responder mi pregunta

    • admin dice:

      Hola Carlos,

      por su puesto que se puede hacer lo que dices. Tendrías que modificar el script en python y al recibir la información desde el arduino guardar la información por ejemplo en un archivo de texto. En esta página ejemplos de como implementarlo: http://www.tutorialspoint.com/python/python_files_io.htm

      Básicamente sería modificar el script con algo similar a esto (No lo he probado pero sería algo muy silimar):

      datosRecibidos=ser.readline()
      print(datosRecibidos)
      fo = open(“logMedida.txt”, “wb”)
      fo.write();
      fo.close()
      … Continua el çódigo….

      Espero que esto te ayude en algo.

      Saludos.

  4. Rafa dice:

    Roberto. Tengo conectado el arduino y la raspberry a través de los pines TX y RX con unas resistencias para salvar el problema de la diferencia de voltaje (3.3 V. 5 V.)

    Realmente no es el puerto USB pero, ¿tu programa debería funcionar con esta conexción?.

    Por otro lado, cuando ejecuto el programa en Python me dice que acceso denegado a /dev/ttyACM0. ¿eso es porque no se están comunicando?.
    Gracias

  5. rafael dice:

    Roberto, he conectado el arduino a la RPi a través de los pines RX y TX poniendo unas resistencias para solucionar el problema de las diferencias de voltaje. He ejecutado
    ls /dev/tty* antes y despues de conectar el arduino y me sale la misma información, es decir, no aparece como un nuevo dispositivo conectado ¿Por qué puede ser?.

    Gracias.

    Saludos

    • admin dice:

      Hola Rafael,

      Creo que el método que usé para conectar el raspberry y el arduino es diferente al que estas usando. Tal y como lo hice yo el arduino aparece en los tty devs porque el arduino al conectarlo por usb se encarga de identificarse en el sistema operativo del raspberry.

      Supongo que en tu caso, esta conectando los pines trx y rx del arduino al gpio del raspberry. Si no me equivoco en teoría podría funcionar pero creo que tendrías que implementar la comunicacion manualmente desde el raspberry. Creo que este blog podría servirte de ayuda: http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/

      Saludos.

  6. Caul seria la libreria para java?

  7. luis dice:

    hola Carlos. la configuracion que usas aqui para el raspberry sirve para comunicarse por los pines TX , RX de uart? necesito conectar la raspberry a un microprocesador de la microchip por medio de UART. saludos

  8. Carlos Vida dice:

    Hola, muchas gracias, esto va perfecto. Es un buen principio, ahora se trata de interactuar con arduino via web. un saludo.

  9. Templaries dice:

    Un tutorial muy sencillo y bien explicado, me gustaria preguntarte si esto puede ser la base para empezar un proyecto casero de robot que utilice servos de movimiento continuo conectados al arduirno para hacer ruedas.

    La idea es enviar comandos para mover las ruedas desde la raspberry.

  10. yesid dice:

    Buen dia, excelente aporte gracias por el tiempo dedicado para su elaboracion y la publicacion…me gusto mucho el proyecto gracias….

  11. Hola Roberto!!!

    acabo de comenzar a aprender a cerca de Iot. Quería preguntarte si conoces alguna forma de establecer comunicación entre un arduino uno y una raspberry pi via wireless o bluetooth

  1. […] la última entrada comenté como llevar a cabo la conexión entre el Raspberry Pi y Arduino. Una vez completada la conexión entre ambos dispositivos a través de USB, en esta entrada vamos a […]

Deja un comentario

    Sobre este Sitio

    Definir en pocas palabras de que va esta web es un poco complicado. En esta página encontrarás un poco de todos los temas que me interesan e inquietan tanto a nivel personal como profesional. Seguramente encontrarás bastante contenido relacionado con tecnología y alguna que otra entrada relacionada con música y fotografía.