domingo, 8 de maio de 2016

Integrando o Arduíno com Raspberry PI via Interface Serial

Nesse artigo, iremos mostrar como integrar um Arduíno com o Raspberry PI 2 através da interface serial, fazendo o LED do pino 13 do Arduíno piscar baseado em um comando enviado pelo Raspberry PI.

Segue abaixo a lista de materiais utilizados:

  • Raspberry PI 2 - clique aqui ver a especificação oficial;
  • Arduíno UNO;
  • 2 Resistores de 10K;
  • Protoboard;
  • Alguns fios.

Foto do projeto montado


No Raspberry utilizado, foi instalada a última versão do sistema operacional disponibilizado pelo NOOBS(clique aqui) - Raspibian, que até a escrita desse artigo estava na Versão 1.9.0 de 18/03/2016. Não iremos abordar a instalação e configuração do Raspberry.

Raspberry PI 2

Esquema elétrico

A Serial do Raspberry está definida nos pinos 14 - TX e 15 - RX, figura abaixo, e iremos utilizar além desses o Ground (qualquer um deles). 

A documentação completa dos pinos pode ser encontrada aqui.


No Arduíno, iremos utilizar também os pinos TX, RX e Ground, que estão definidos na própria placa.



De maneira resumida, no padrão RS-232 (para mais informações sobre a interface serial e protocolo RS-232, clique aqui), os dispositivos que irão conversar devem ter um pino TX e um RX. Onde o TX é o pino emissor e o RX é o pino receptor. Partindo desse princípio, bastaria ligar o TX do Raspberry no RX do Arduíno e ligar o TX do Arduíno no RX do Raspberry. 

Mas, há um porém.O Arduíno trabalha a 5V e o Raspberry a 3,3V. Se ligarmos o TX do Arduíno no RX do Raspberry, poderemos queimar o pino, pois o Arduíno irá enviar 5V e o Raspberry espera até 3,3V. O contrário, não é problema (TX do Raspberry com RX do Arduíno). Pois o Arduíno espera até até 5V e o Raspberry irá enviar até 3,3V.

Para resolver esse problema utilizaremos um circuito divisor de tensão bem simples com dois resistores de 10K entre a ligação do TX do Arduíno com o RX do Raspberry.


Dessa forma, a tensão que vier do Arduíno, será divida entre o Raspberry e o GND(Ground).

Segue abaixo o diagrama completo:

Programação

O programa do Arduíno é bem simples. Temos um loop que enquanto a serial estiver disponível, esperará o caractere "L" pela serial. A cada "L", ele altera o estado do LED de acordo com a variável "state" e responde pela serial o estado do LED (LED Ligado ou Desligado). O programa foi compilado e embarcado usando a IDE oficial do Arduíno.

Fonte para o Arduíno

       
#define PIN_LED 13
char buff;
char state = 1;
 
void setup()
{
  pinMode(PIN_LED, OUTPUT);//Inicializa o Pino 13 como saida
  Serial.begin(115200);//Inicializando a serial em 115200
}
 
void loop()
{
  while (Serial.available() > 0)//loop de leitura/escrita da serial
  {
    buff = Serial.read();
    if (buff == 'L')// se caractere 'L' (LED) vindo na serial
    {
      // Liga/Desliga o LED com base no state ( 0 - LOW, 1 - HIGH)
      digitalWrite(PIN_LED, state);
      // Avisa o receptor do status de LED
      Serial.print("Led: ");
      if (state)
      {
        Serial.println("Ligado");
      }
      else
        Serial.println("Desligado");
    }
    state = !state;
  }
}
 
 

No Raspberry, criaremos um programa em C que inicializa a serial, envia infinitamente o caractere "L" a cada segundo, logando basicamente o estado do LED pelo console (informado pelo Arduíno).

Fonte em C para o Raspberry

       
#include ‹unistd.h› //Usado na serial
#include ‹fcntl.h› //Usado na serial
#include ‹termios.h› //Usado na serial

int uart = -1;
int main(){

 //Abrindo a Serial do raspberry para leitura e escrita
 uart = open("/dev/ttyAMA0",O_RDWR|O_NOCTTY|O_NDELAY);
 if(uart == -1)
  printf("Erro ao abrir UART\n");

 //setup da serial 
 struct termios options;
 options.c_cflag= B115200|CS8|CLOCAL|CREAD;
 options.c_iflag= IGNPAR;
 options.c_oflag= 0;
 options.c_lflag= 0;
 tcflush(uart,TCIFLUSH);
 tcsetattr(uart,TCSANOW,&options);

 unsigned char tx_buff[1];//buffer de envio 
 tx_buff[0] = 'L'; 
        unsigned char rx_buff[256];//buffer de leitura
 int rx_len = 0;

  while(1)//loop infinito
        {
  printf("preparando para escrever\n");
                if(uart != -1 )//send bytes
                {
                        int count = write(uart,&tx_buff[0],1);//escrevendo na serial

                        if(count < 0) 
    printf("Erro de escrita\n");
   else 
    printf("mensagem enviada\n");

                        rx_len = read(uart,(void*)rx_buff,255);//lendo da serial, até 255 bytes

          if(rx_len > 0 )
   {
    rx_buff[rx_len] = '\0';
    printf("Recebido - %s\n",rx_buff);
   }

                }
  else{
   printf("Erro ao escrever na serial");
  }
  sleep(1);//pausa a cada 1 segundo
        }
 close(uart);
 printf("fim\n");
 return 0;
}


Para mai detalhes sobre a inicialização da Serial(UART) em C no Raspberry, clique aqui.

O programa foi compilado usando o compilador G++ nativo da instalação do Raspberry, com a linha de comando abaixo:

       
g++ Serial.cpp -o ardSerial


e executado com a linha:

       
./ardSerial


Segue abaixo um print do console:

Um detalhe importante. Por default, a Serial do Raspberry vem configurada para ficar logando informações para um console. O programa acima irá falhar na abertura da Serial se essa funcionalidade não for desabilitada.

O passo-a-passo de como desabilitar a o console Serial no Raspberry pode ser encontrado aqui.

O programa para o Raspberry pode ser escrito em qualquer outra linguagem, como python, por exemplo.



Sem comentários:

Enviar um comentário