Site icon AranaCorp

Comunicação serial entre Raspberry Pi e Arduino

Em alguns projetos, pode ser interessante estabelecer uma comunicação serial entre o Raspberry Pi e o Arduino. Com isso, aliamos a capacidade de processamento e a interface sem fios do Raspberry Pi com as entradas e saídas e a coleção de módulos do Arduino. O primeiro exemplo que vem em mente é uma aplicação domótica em que o Raspberry Pi oferece a interface de controle e a inteligência e o Arduino funciona como um autômato programável, agindo sobre os componentes no final da cadeia (luzes, radiador, ventilador, sensores, etc.).

Veremos agora como estabelecer uma comunicação serial entre Raspberry Pi e Arduino via entrada USB. Neste tutorial, utilizamos a placa Arduino UNO, mas ele pode ser adaptado a outros tipos de placa com ligação serial (Nano, Mega, Feather, EPS32, ESP8266, etc.).

Pré-requisitos: Comunicação serial com o Arduino, Acesso remoto ao Raspberry Pi com VNC

Material

Esquema de ligação

Para estabelecer a comunicação serial entre Raspberry Pi e Arduino, basta ligá-los com um cabo USB adequado. No nosso caso, utilizamos um Raspberry Pi 3B+ e um Arduino UNO. Precisamos portanto de um cabo USBA Macho para USB B Macho.

Neste tutorial, vamos focar na ligação USB, mas também é possível criar uma comunicação serial utilizando os pinos Rx/Tx de ambos os componentes.

Configuração do Raspberry Pi

Recordamos que, para utilizar o seu Raspberry Pi sem monitor ou teclado, é preciso configurar a conexão remota VNC.

Para utilizar a interface serial do Raspberry Pi, ela deve ser ativada 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 depois “P6 Serial” e confirme.

Efetuada a conexão, pode verificar os dispositivos ligados à porta serial digitando o seguinte comando no terminal:

lsusb

O Raspberry Pi devolve uma lista de dispositivos conectados às entradas USB.

pi@raspberrypi:~ $ lsusb
Bus 001 Device 002: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Para encontrar o nome da entrada onde o Arduino está conectado, usamos o comando:

dmesg | grep "tty"

Esse comando devolve as mensagens do sistema relativas à porta serial. O nome da porta deve aparecer entre as últimas mensagens. No nosso caso, o nome é ttyACM0.

pi@raspberrypi:~ $ dmesg | grep "tty"
[    0.000000] Kernel command line: coherent_pool=1M 8250.nr_uarts=1 bcm2708_fb.fbwidth=1824 bcm2708_fb.fbheight=984 bcm2708_fb.fbswap=1 smsc95xx.macaddr=B8:27:EB:23:CF:07 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000  console=ttyS0,115200 console=tty1 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
[    0.000636] console [tty1] enabled
[    0.951553] 20201000.serial: ttyAMA0 at MMIO 0x20201000 (irq = 81, base_baud = 0) is a PL011 rev2
[    0.954393] console [ttyS0] disabled
[    0.954466] 20215040.serial: ttyS0 at MMIO 0x0 (irq = 53, base_baud = 31250000) is a 16550
[    0.954570] console [ttyS0] enabled
[    5.378641] systemd[1]: Created slice system-serial\x2dgetty.slice.
[ 1455.402071] cdc_acm 1-1:1.0: ttyACM0: USB ACM device
[ 1581.980257] cdc_acm 1-1:1.0: ttyACM0: USB ACM device

Instalação da IDE do Arduino no Raspberry Pi

A melhor maneira de instalar a IDE do Arduino no Raspberry é utilizando o terminal. Basta introduzir as seguintes linhas de código:

mkdir ~/Applications
cd ~/Applications
wget https://downloads.arduino.cc/arduino-1.8.9-linuxarm.tar.xz
tar xvJf arduino-1.8.9-linuxarm.tar.xz
cd arduino-1.8.9/
 ./install.sh
rm ../arduino-1.8.9-linuxarm.tar.xz

Isso permitirá programar o Arduino diretamente a partir do Raspberry Pi.

Código

Código Arduino

A biblioteca utilizada para a comunicação serial do lado Arduino é a mesma usada para comunicar com o monitor serial: a Serial.h, que já conhecemos bem. Verifique se a velocidade de comunicação é a mesma para ambos os dispositivos (baudrate=9600), caso contrário a comunicação não funcionará.

String nom = "Arduino";
String msg;

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

void loop() {
  readSerialPort();

  if (msg != "") {
    sendData();
  }
  delay(500);
}

void readSerialPort() {
  msg = "";
  if (Serial.available()) {
    delay(10);
    while (Serial.available() > 0) {
      msg += (char)Serial.read();
    }
    Serial.flush();
  }
}

void sendData() {
  //write data
  Serial.print(nom);
  Serial.print(" received : ");
  Serial.print(msg);
}


Código Python

Neste tutorial, adotamos a linguagem Python no lado do Raspberry Pi. A biblioteca utilizada para gerir a comunicação serial é a serial.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# lsusb to check device name
#dmesg | grep "tty" to find port name

import serial,time


if __name__ == '__main__':
	
	print('Running. Press CTRL-C to exit.')
	with serial.Serial("/dev/ttyACM0", 9600, timeout=1) as arduino:
		time.sleep(0.1) #wait for serial to open
		if arduino.isOpen():
			print("{} connected!".format(arduino.port))
			try:
				while True:
					cmd=input("Enter command : ")
					arduino.write(cmd.encode())
					#time.sleep(0.1) #wait for arduino to answer
					while arduino.inWaiting()==0: pass
					if  arduino.inWaiting()>0: 
						answer=arduino.readline()
						print(answer)
						arduino.flushInput() #remove data after reading
			except KeyboardInterrupt:
				print("KeyboardInterrupt has been caught.")

Resultado

O Raspberry Pi envia o comando “Hello Arduino” ao Arduino, e este responde com o seu nome e o comando recebido.

Exemplo prático

Estabelecida a comunicação entre o Raspberry Pi e o Arduino, o interessante é poder controlar as entradas e saídas do Arduino e obter os valores dos sensores. Neste exemplo, vamos definir diferentes comandos:

Código Arduino

O Arduino envia dados ao receber o comando “data” e acende e apaga o LED ligado ao pino 13 de acordo com os comandos “led0” e “led1”.

const int ledPin=13;
String nom = "Arduino";
String msg;

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

void loop() {
  readSerialPort();

  if (msg == "data") {
    sendData();
  }else if(msg=="led0"){
    digitalWrite(ledPin,LOW);
    Serial.print(" Arduino set led to LOW");
  }else if(msg=="led1"){
    digitalWrite(ledPin,HIGH);
    Serial.print(" Arduino set led to HIGH");
  }
  delay(500);
}

void readSerialPort() {
  msg = "";
  if (Serial.available()) {
    delay(10);
    while (Serial.available() > 0) {
      msg += (char)Serial.read();
    }
    Serial.flush();
  }
}

void sendData() {
  //write data ledState x sensor1 x sensor2
  Serial.print(digitalRead(ledPin));
  Serial.print("x");
  Serial.print(analogRead(A0));
  Serial.print("x");
  Serial.print(analogRead(A1));
}


Código Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# lsusb to check device name
#dmesg | grep "tty" to find port name

import serial,time


if __name__ == '__main__':
	print('Running. Press CTRL-C to exit.')
	with serial.Serial("/dev/ttyACM0", 9600, timeout=1) as arduino:
		time.sleep(0.1) #wait for serial to open
		if arduino.isOpen():
			print("{} connected!".format(arduino.port))
			try:
				while True:
					cmd=input("Enter command (data,led0 or led1): ")
					arduino.write(cmd.encode())
					#time.sleep(0.1) #wait for arduino to answer
					
					while arduino.inWaiting()==0: pass
					if  arduino.inWaiting()>0: 
						answer=str(arduino.readline())
						print("---> {}".format(answer))
						if cmd=="data":
							dataList=answer.split("x")
							print("led state : {}".format(dataList[0]))
							print("Analog input A0 : {}".format(dataList[1]))
							print("Analog input A1: {}".format(dataList[2]))
							
							arduino.flushInput() #remove data after reading
							
			except KeyboardInterrupt:
				print("KeyboardInterrupt has been caught.")

Uma vez carregados e lançados os dois códigos, observamos que, ao introduzir o comando “data” no terminal, o Arduino retorna bytes contendo os valores dos sensores. É possível dividir esta resposta numa lista usando a função split() e o carectere “x”, e assim obter os valores dos sensores e o estado do LED. Com este código, podemos controlar o estado do LED no pino 13.

Este código pode ser modificado para controlar e visualizar qualquer entrada ou saída do Arduino no Raspberry Pi.

Aplicação

Fontes

Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

Exit mobile version