Introdução
Este artigo apresentará o desenvolvimento de um projeto prático explicativo sobre como se desenvolver a montagem e firmware para se realizar a comunicação serial utilizando protocolo UART (Universal asynchronous receiver/transmitter) entre a Raspberry PI e a a placa de Arduino.
O desenvolvimento será baseado no projeto do termômetro digital apresentado no artigo anterior, sendo os dados obtidos via módulo sensor AM2302 e transmitidos por seu barramento de dados à Raspberry PI. Esta recebe os dados, os processa gerando um protocolo que transmite as informações de temperatura e umidade juntos no mesmo bloco de dados através porta serial. O Arduino recebe este bloco de dados e realiza o processamento reverso separando as duas informações e as apresentando no display de LCD.
Por sugestão, para maior entendimento sobre como trabalhar o módulo sensor AM2303 deve ser estudo o artigo anterior.
Ao final da leitura deste artigo, aplicando os conceitos teóricos e práticos apresentados sobre a comunicação serial sobre o protocolo UART, o leitor saberá como configurar, realizar a montagem e a transmissão dos dados entre a Raspberry Pi e o Arduino. E em posse desses conhecimentos, será capaz de realizar os seus próprios projetos e aplicações.
Este artigo dá continuidade à série de artigos sobre Raspberry PI publicados por Cleiton Bueno e por mim, Roniere Rezende.
Comunicação Serial – UART (Universal asynchronous receiver/transmitter)
O protocolo de comunicação UART, em português significa Transmissor/Receptor Universal Assíncrono. É como o próprio nome diz, assíncrono, ou seja, não existe um sinal de clock para sincronizar o sinal transmitido com o sinal recebido. A UART é um protocolo de comunicação full-duplex, ou seja, a comunicação é realizada ao mesmo tempo de um dispositivo para o outro, pois os dados trafegam por meios diferentes, como pode ser visto na Figura 1.
Para os bits serem transmitidos e recebidos, transmissor e receptor devem estar configurados com o mesmo valor de baudrate, dado em bits por segundo, que é a taxa de transmissão de dados entre um dispositivo a outro.
De acordo com o protocolo UART, quando não há dados no barramento ele é colocado em estado Bus Idle, mantido em lógico alto. Quando um dispositivo possui dados para serem transmitidos, primeiro ele envia um bit de inicialização chamado Start Bit, esse bit está em nível lógico baixo. Logo em seguida envia um byte, ou seja, 8 bits de informação. Para finalizar o envio dos dados, envia um bit chamado de Stop Bit que possui nível lógico alto. Esta descrição do protocolo UART pode ser visto na Figura 2.
Configurando a Raspberry PI
Para que a Raspberry Pi consiga realizar a comunicação serial via protocolo UART é necessário configurar o pino 8 como porta transmissora (TX) e o pino 10 como porta receptora (RX).
Todos os comandos de configuração e para abrir arquivos serão realizados no “LX Terminal” mostrado na Figura 3.
Para configurar a serial é preciso editar o arquivo “inittab”, localizado em “/etc/inittab”. Para habilitar a serial deve-se comentar a linha “T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100”. Para abrir este arquivo digite o seguinte comando no LX Terminal:
$ sudo leafpad /etc/inittab
Caso não se consiga encontrar este arquivo no sistema operacional da sua Raspberry PI, que foi o meu caso, deve-se realizar o seguinte comando:
$ sudo leafpad /boot/config.txt
Quando abrir este arquivo acrescente no final a seguinte linha “enable_uart=1” como mostrado na Figura 4.
Em seguida desabilite a serial com os seguintes comandos:
$ sudo systemctl stop serial-getty@ttyS0.service $ sudo systemctl disable serial-getty@ttyS0.service
Em seguida execute o comando abaixo:
$ sudo leafpad /boot/cmdline.txt
E remova a linha “console=serial0,115200”, salve o arquivo e realize o “Reboot” da Raspberry PI.
O arquivo deve ficar configurado como na Figura 5.
Pronto, a Raspberry PI está configurada e pronta para se utilizar as portas seriais com protocolo UART.
Em caso de dúvidas, este artigo pode também ajudar “Configuring The GPIO Serial Port On Raspbian Jessie Including Pi 3”.
Comandos
Raspberry PI – Python
Os comandos Python utilizados para realizar a comunicação serial na Raspberry Pi fazem parte da biblioteca “serial” da linguagem e devemos usar o comando import para utilizá-lo nos nossos códigos. Como utilizar o comando import é demonstrado na seção “Código”.
serial.Serial(): É uma classe usada para configurar a porta serial. Cria uma instância para essa classe, no projeto ela recebe o nome de “ser”, mas poderia receber qualquer outro nome.
Sintaxe:
ser = serial.Serial(Port, Baudrate)
Parâmetros:
- Port: nome da porta serial, no projeto é usado “/dev/ttyS0”.
- Baudrate: taxa de baudrate tais como 9600, 38400 e 115200.
Exemplo:
ser = serial.Serial(“dev/ttyS0”, 9600)
read(): Essa função é usada para ler os dados na porta serial.
Sintaxe:
received_data = ser.read(Size)
Parâmetros:
- Size: número de bytes a serem lidos. O tamanho padrão 1.
Retorno:
Bytes lidos da porta serial.
inWaiting(): Verifica se ainda há bytes restantes no buffer de recepção da porta serial.
Sintaxe:
data_left = ser.inWainting()
Retorno:
Retorna os bytes armazenados no buffer.
write(): Essa função é usada para transmitir/enviar dados da porta serial.
Sintaxe:
ser.write(Data)
Parâmetros:
- Data: são os dados a serem enviados pela porta serial.
Retorno:
Número de bytes escritos/enviados.
close(): Finaliza a transmissão serial.
Arduino – Wiring
Porta Serial
As funções a seguir utilizadas para estabelecer e realizar a comunicação serial UART no Arduino.
begin(): Configura a taxa de transmissão em bits por segundo (baudrate).
Sintaxe:
Serial.begin (Speed)
Serial.begin (Speed, Config)
Parâmetros:
- Speed: a velocidade em bits por segundo (baudrate);
- Config: configura a quantidade de bits, paridade e o bit de parada.
available(): Retorna a quantidade de bytes disponíveis para se ler no buffer.
Sintaxe:
Serial.availabre()
Retorno:
Retorna uma variável inteira com a quantidade de bytes disponíveis no buffer para serem lidos.
read( ): Lê o último byte apontado no buffer da entrada serial.
Sintaxe:
Serial.read()
Retorno:
Retorna o primeiro byte disponível no buffer serial.
print(): Escreve na serial um texto em formato ASCII.
Sintaxe:
Serial.print (Value)
Serial.print (Value, Format)
Parâmetros:
- Value: valor a ser escrito na serial, pode ser de qualquer tipo.
- Format: BIN (Binário, base 2), OCT (Octal, base 8), HEX (Hexa, base 16) e DEC (decimal, base 10).
Retorno:
Escreve no terminal serial os bytes escritos em “Value”.
println(): É similar ao Serial.print(), a única diferença é que a função adiciona ao final da mensagem o caracter retornado e um caracter de nova linha.
Sintaxe:
Serial.println (Value)
Serial.println (Value, Format)
Parâmetros:
- Value: valor a ser escrito na serial, pode ser de qualquer tipo.
- Format: BIN (Binário, base 2), OCT (Octal, base 8), HEX (Hexa, base 16) e DEC (decimal, base 10).
Retorno:
Escreve no terminal serial os bytes escritos em “Value”.
write(): Escreve e transmite um byte na porta serial.
Sintaxe:
Serial.write(Value)
Serial.write(Str)
Serial.write(Buffer, Len)
Parâmetros:
- Value: valor a ser enviado em um único byte.
- Str: uma string a ser enviada como uma sequência de bytes.
- Buffer: um array a ser enviado como uma série de bytes.
- Len: o comprimento do buffer a ser enviado.
Retorno:
Retorna a quantidade de bytes escritos na porta serial.
Display de LCD
Como o escopo deste artigo não é abordar o tema sobre o display LCD, irei descrever somente as funções que foram utilizadas no código fonte. Para maiores informações sobre as demais funções recomendo que o leitor pesquisa neste link, que aborda todas as funções utilizadas no Arduino para configurar e manipular o display de LCD.
LiquidChrystal(): Cria uma variável do tipo cristal líquido.
Sintaxe:
LiquidCrystal(rs, Enable, d4, d5, d6, d7);
Example:
LiquidCrystal(8, 9,4, 5, 6, 7);
begin(): Inicializa a interface o tela do LCD e especifica a dimensão do display. Necessita ser chamada antes de qualquer outro comando da biblioteca do LCD.
Sintaxe:
lcd.begin(Column, Rows)
Parâmetros:
- Column: número de colunas.
- Rows: número de linhas.
serCursor(): Define a posição do cursor do LCD.
Sintaxe:
lcd.setCursor(Column, row)
Parâmetros:
- Column: a coluna em que o cursor será posicionado.
- Row: a linha em que o cursor será posicionado.
write(): Escreve um caractere no LCD.
Sintaxe:
lcd.write(Data)
Parâmetros:
- Data: o caractere que será escrito no display.
print(): Escreve um texto no LCD.
Sintaxe:
lcd.print(Data)
lcd.print(Data, BASE)
Parâmetros:
- Data: os dados que serão escritos no LDC (char, byte, int, long ou string).
- BASE: (opcional) A base em que são escritos os dados. BIN (Binário, base 2), OCT (Octal, base 8), HEX (Hexa, base 16) e DEC (decimal, base 10).
createChar(): Cria um caractere personalizado para ser utilizado no LCD.
Sintaxe:
lcd.createChar(Number, Data)
Parâmetros:
- Number: o código do caractere a ser criado.
- Data: o nome da matriz de pixel do caractere a ser criado.
Circuito
Esquema Elétrico
Montagem
A montagem a ser realizada para o desenvolvimento do projeto para comunicação serial utilizando o protocolo UART entre a Raspberry Pi e o Arduino é relativamente simples. Para desenvolver a montagem são necessários os seguintes componentes:
- Raspberry PI;
- Arduino Uno;
- Shield LCD;
- Módulo Sensor AM2302;
- Jumpers.
Primeiramente, deve-se acoplar o shield LCD ao Arduino. Realizada essa conexão, todas próximas ligações serão realizadas nele.
Deve-se conectar o GND do shield LCD com o da Raspberry Pi juntamente com o terminal GND do módulo sensor. A fonte de 5V, pino 2, da Raspberry Pi deve ser conectado ao VIN do Shield LCD.
O pino 8, o terminal transmissor (TX), da Raspberry Pi deve ser ligada ao pino 1, terminal receptor (RX), do Shield LCD.
O módulo sensor deve ser alimentado com um tensão de 3,3 V fornecido pela própria Raspberry Pi para evitar que se danifique a porta receptora (RX) do sinal de dados de temperatura e umidade. O terminal de recepção de sinal (RX) é o pino 10 e dever ser conectado ao pino 2, terminal de dados, do módulo sensor AM2302.
Entre os terminais de VCC e GND do módulo sensor AM2302, e o mais próximo possível deles, deve ser conectado um capacitor de 100nF para filtrar ruídos que possam interferir na medição dos dados. Entre o VCC e terminal de dados deve ser conectado um resistor de 10 kΩ para quando não houver dados a serem transmitidos se manter o terminal de dados em nível lógico alto.
Vídeo
Este vídeo ilustra o funcionamento do projeto de comunicação serial com o protocolo UART entre a Raspberry Pi e o Arduino apresentado neste artigo.
Códigos
No desenvolvimento da comunicação serial utilizando protocolo UART é necessário criar dois códigos, um para para a Raspberry Pi, desenvolvido em Python, e outro para o Arduino, desenvolvido em Wiring.
Os códigos também estão disponíveis na minha página no GitHub, neste link.
Código em Python
# Declara-se as bibliotecas que serão utilizadas no código
import RPi.GPIO as GPIO
import time
import serial
import Adafruit_DHT
#Define a GPIO que irá receber os dados do módulo sensor
DHT_IN = 15
#Configura o uso do terminal serial e da taxa de transmissão de dados
ser = serial.Serial("/dev/ttyS0", 9600)
#Define um objeto para a classe Adafruit_DHT, que habilita o módulo sensor
sensor = Adafruit_DHT.DHT22
#Configuração inicial dos terminais GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(DHT_IN, GPIO.IN)
while True:
# Armazena e converte os dados do tipo “int” em tipo “string”
umid, temp = Adafruit_DHT.read_retry(sensor, DHT_IN)
temp_st = str("%.1f" % temp)
umid_st = str("%.1f" % umid)
# Avalia se os dados enviado pelo módulo sensor são válidos
if umid is not None and temp is not None:
#Define um protocolo e transmite os dados via terminal serial
ser.write(temp_st+umid_st)
else:
#Informa que os dados gerados não serão válidos
ser.write("Error")
time.sleep(0.5)
time.sleep(1)
Código em Wiring
// Declara a biblioteca das funções do LCD
#include <LiquidCrystal.h>
//Declara as variáveis que receberam os dados de temperatura, umidade e
// buffer de dados da serial
char temp = '0';
char humid = '0';
char buff[8] = {};
// Configura as conexões do com o shield LCD
LiquidCrystal lcd(8,9,4,5,6,7);
// Cria o caracter especial “°” para ser mostrado no display LCD
byte degree[8] = {
B00000,
B01110,
B01010,
B01110,
B00000,
B00000,
B00000,
B00000
};
void setup() {
// Defini que se utilizará a porta serial com taxa de 9600 bits por segundo.
Serial.begin(9600);
// Define que o display de LCD é de 16 colunas por 2 linhas
lcd.begin(16,2);
// Configura e insere na tela do LCD para as palavras “Temp” e “Humid”
lcd.setCursor(0,0);
lcd.print("Temp:");
lcd.setCursor(11,0);
lcd.print("C");
lcd.setCursor(0,1);
lcd.print("Humid:");
lcd.setCursor(11,1);
lcd.print("%");
// Configura a posição e insere na tela do LCD o caracter especial “°”
lcd.createChar(0, degree);
lcd.setCursor(10,0);
lcd.write((byte)0);
}
void loop() {
// Inicializa as variáveis utilizadas na interpretação dos dados recebidos
int i = 0;
int column_T = 6;
int column_H = 6;
// Avalia se há dados disponíveis no buffer da porta serial
if (Serial.available()){
for(i = 0; i < 8; i++ ){
buff[i] = Serial.read();
}
// Interpretação dos dados da porta serial
for(i = 0; i < 8; i++ ){
// Interpreta os dados de temperatura e mostra na tela do LCD
if(i < 4){
lcd.setCursor(column_T,0);
lcd.print(buff[i]);
column_T++;
}
// Interpreta os dados de temperatura e mostra na tela do LCD
if(i>=4 && i<8){
lcd.setCursor(column_H,1);
lcd.print(buff[i]);
column_H++;
}
}
}
delay(100);
}
Conclusão
Com o desenvolvimento do projeto de comunicação serial (UART) entre a Raspberry Pi e Arduino, o leitor pode adquirir conhecimentos técnicos e práticos sobre como realizar e desenvolver este tipo de comunicação. Observou-se que a configuração e programação utilizando o protocolo UART é bem simples de ser realizado. Novamente, neste artigo foi utilizado o módulo sensor AM2302 e pode-se observar outra aplicação para ele, a transmissão dos seus dados remotos.
Com as informações em mãos, o leitor, utilizando de sua criatividade, poderá desenvolver projetos simples e mais complexos utilizando o protocolo UART e a Raspberry com Arduino.
E por último, gostaria de agradecer ao engenheiro eletricista Ronaldo Nunez pela sua colaboração na realização deste artigo.
Referências
Como comunicar o Arduino com Raspberry Pi
Video – Arduino e Raspberry Pi troca de Dados via Porta Serial
Biblioteca Display LCD do Arduino
Configuring The GPIO Serial Port On Raspbian Jessie Including Pi 3












Eu estou tentando instalar um gps e gprs em minha raspberry e não consigo. Fiz os procedimentos de adicionar a linha em config.txt, excluí a parte do código em cmdline.txt, mas não roda de jeito algum. Você poderia me ajudar?