Em alguns projetos, pode ser interessante estabelecer uma comunicação I2C entre Raspberry Pi e Arduino. A potência de computação e as capacidades sem fios do Raspberry Pi, aliadas à capacidade de entrada e saída do Arduino, resultam num sistema de controle completo que permite pilotar qualquer projeto. Se a placa Raspberry Pi e a placa Arduino estiverem próximas, o barramento I2C é uma boa escolha como protocolo de comunicação. Isso também permite adicionar vários dispositivos no mesmo barramento e aumentar em dez vezes as capacidades do RaspberryPi.
Pré-requisitos: comunicação I2C com Arduino, Acesso remoto do Raspberry Pi com VNC
Material
- Computador
- Arduino UNO
- Raspberry Pi 3B+
- 3 Cabos jumper
Esquema de ligação
Para estabelecer a comunicação I2C entre Raspberry Pi e Arduino, é preciso ligar fisicamente o barramento que utiliza 3 pinos. A comunicação I2C se define por um barramento de dois fios (também chamado de TWI, Two Wire Interface) e um endereço. Os pinos utilizados para a comunicação I2C são normalmente fixados para cada dispositivo. Os dados (SDA Serial Data Line) são enviados para um pino e o relógio de sincronização (SLC Serial Clock Line), para o outro. As terras de ambas as placas devem estar conectadas para estabelecer uma referência comum de potencial.
- SDA BCM2(RPI) <-> SDA A4(Arduino)
- SCL BCM3(RPI) <-> SCL A5(Arduino)
- GND (RPI) <-> GND(Arduino)
Configuração do Raspberry Pi
Para utilizar a interface I2C do Raspberry Pi, deve-se ativá-la no menu de configuração. Para isso, introduza o seguinte comando num terminal:
sudo raspi-config
No menu, selecione “5 – Opções de Interface” e em seguida “P5 I2C”, então valide.
Uma vez efetuada a ligação, é possível verificar os dispositivos conectados ao barramento digitando o seguinte comando no terminal:
i2cdetect -y 1
O Raspberry Pi devolve a lista de endereços detectados no barramento.
pi@raspberrypi:~ $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 0b -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --
Vamos instalar a biblioteca smbus2, que permite gerenciar a comunicação I2C pelo lado do Raspberry Pi
pip3 install smbus2
Código
Código “Master” Python
Neste tutorial, vamos adotar a linguagem Python para o Raspberry Pi. A biblioteca utilizada para gerenciar a comunicação I2C é a smbus2.
#!/usr/bin/env python # -*- coding: utf-8 -*- # Raspberry Pi to Arduino I2C Communication #i2cdetect -y 1 #library import sys import smbus2 as smbus#,smbus2 import time # Slave Addresses I2C_SLAVE_ADDRESS = 11 #0x0b ou 11 I2C_SLAVE2_ADDRESS = 12 I2C_SLAVE3_ADDRESS = 13 # This function converts a string to an array of bytes. def ConvertStringsToBytes(src): converted = [] for b in src: converted.append(ord(b)) return converted def main(args): # Create the I2C bus I2Cbus = smbus.SMBus(1) with smbus.SMBus(1) as I2Cbus: slaveSelect = input("Which Arduino (1-3): ") cmd = input("Enter command: ") if slaveSelect == "1": slaveAddress = I2C_SLAVE_ADDRESS elif slaveSelect == "2": slaveAddress = I2C_SLAVE2_ADDRESS elif slaveSelect == "3": slaveAddress = I2C_SLAVE3_ADDRESS else: # quit if you messed up print(slaveSelect== "1") print(type(slaveSelect)) print("no slave selected") quit() BytesToSend = ConvertStringsToBytes(cmd) print("Sent " + str(slaveAddress) + " the " + str(cmd) + " command.") print(BytesToSend ) I2Cbus.write_i2c_block_data(slaveAddress, 0x00, BytesToSend) time.sleep(0.5) while True: try: data=I2Cbus.read_i2c_block_data(slaveAddress,0x00,16) print("recieve from slave:") print(data) except: print("remote i/o error") time.sleep(0.5) return 0 if __name__ == '__main__': try: main(sys.argv) except KeyboardInterrupt: print("program was stopped manually") input()
Código “Slave” Arduino
A biblioteca utilizada para gerir a comunicação I2C no lado Arduino é a Wire.h.
#include <Wire.h> # define I2C_SLAVE_ADDRESS 11 // 12 pour l'esclave 2 et ainsi de suite #define PAYLOAD_SIZE 2 void setup() { Wire.begin(I2C_SLAVE_ADDRESS); Serial.begin(9600); Serial.println("-------------------------------------I am Slave1"); delay(1000); Wire.onRequest(requestEvents); Wire.onReceive(receiveEvents); } void loop(){} int n = 0; void requestEvents() { Serial.println(F("---> recieved request")); Serial.print(F("sending value : ")); Serial.println(n); Wire.write(n); } void receiveEvents(int numBytes) { Serial.println(F("---> recieved events")); n = Wire.read(); Serial.print(numBytes); Serial.println(F("bytes recieved")); Serial.print(F("recieved value : ")); Serial.println(n); }
Resultado
O Raspberry Pi envia o comando “slave” ao Arduino e recebe um quadro de dados proveniente do Arduino.
O Arduino recebe o comando “slave” e envia dois valores atualizados assim que recebe um comando do Raspberry Pi
Aplicação
- Reconhecimento visual com Raspberry Pi; controle de servomotores e sensores com Arduino
Fontes
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie