En este pequeño tutorial veremos cómo conectar una tarjeta Arduino a una tarjeta Raspberry Pi por comunicación I2C, encontrarás códigos de programación para tus primeras pruebas.
La comunicación I2C se implementa con 2 señales digitales, la señal de datos “SDA” y la señal de reloj “SCL”. Tanto la tarjeta Arduino Uno como las tarjetas Raspberry Pi cuentan con hardware integrado para implementar el protocolo. En el caso del Arduino, encontramos la señal SDA en el pin A5 y la señal SCL en el pin A4, y en las Raspberry Pi podemos encontrar las señales SDA y SCL en los GPIO2 y GPIO3 respectivamente.
El ejercicio que realizaremos en este tutorial consiste 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 protocolo I2C, éste a 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
- 2 Resistores de 4.7kohms cada uno
- Protoboard mini o chica
- Cables de conexion M-M y H-M
- Convertidor de nivel lógico bidireccional – 3.3V <-> 5V TTL
Conexiones
Utilizamos un convertidor de nivel lógico para conectar las señales de ambas tarjetas, esto es importante porque trabajan con distintos niveles lógicos de voltaje, el Arduino tienen un nivel lógico de 5V y la Raspberry Pi de 3.3V. Conectar las señales directamente podría resultar en un daño a la tarjeta con nivel lógico menor, es decir, la Raspberry Pi.

Código de Arduino – Ardiuno Uno
Cargamos el siguiente código a nuestra tarjeta Arduino Uno:
#include <Wire.h>
String inputString = ""; // Cadena de texto para guardar la cadena recibida por I2C
bool stringComplete = false; // Bandera booleana
int led = 13;
int direccion=31; //Dirección asignada al ARduino. Asegúrate de que utilices esta dirección en el código de la Raspberry Pi
void setup() {
pinMode(led, OUTPUT);
Wire.begin(direccion); // Nos unimos al bus i2c bus con la dirección asignada
Wire.onReceive(receiveEvent); // Registramos el evento de recepción de datos
Serial.begin(9600);
inputString.reserve(200);
}
void loop() {
if (stringComplete) {
Serial.println("Cadena recibida completa");
inputString.remove(0,1);//Removemos 1 carácter. El caracter con index 0, caracter adicional sin utilidad que está mandando Raspberry Pi
if (inputString.equals("off") ){
digitalWrite(13,0);
Serial.println("Apagado");
}
else if (inputString.equals("on") ){
digitalWrite(13,1);
Serial.println("Encendido");
}
Serial.println(" ");
inputString = "";
stringComplete = false;
}
}
void receiveEvent(int howMany) {
while(Wire.available()>0) // Mientras tengamos caracteres en el buffer
{
char inChar = (char)Wire.read();
Serial.print(inChar);
if (inChar == '\n') {
stringComplete = true;
}
else{
inputString += inChar;
}
}
}
Pasos previos a ejecutar el código de la Rapsberry Pi
1.- Habilitar comunicación I2C en la Raspberry Pi
Para que podamos ejecutar un programa que intercambie información a través del protocolo I2C 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 continuar con este tutorial.
2.- Instalar paquete de Python3
En este código hacemos uso del paquete de Python3 «smbus2». Para instalarlo ejecuta el siguiente comando en la terminal:
pi@raspberrypi:~$ sudo pip3 install smbus2
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.
from smbus2 import SMBus
import time
try:
while True:
with SMBus(1) as bus:
comando = input("Ingresar comando (on/off): ")
comando = comando + "\n"
comando = comando.encode()
bus.write_i2c_block_data(31, 0, comando)
time.sleep(0.1)
except KeyboardInterrupt:
print("\nInterrupcion por teclado")
except ValueError as ve:
print(ve)
print("Otra interrupcion")