Post de minha autoria originalmente publicado no Embarcados.

No presente artigo irei apresentar como podemos criar um sistema Web com Raspberry Pi, que é uma SBC que roda Linux Embarcado e mais uma infinidade de aplicações, para funcionar em conjunto com o Arduino, nossa tão amada plaquinha para projetos eletrônicos. Tudo isso usando nada mais e nada menos do que… a porta USB! Nada de TX/RX, mexer em arquivos do sistema, etc…

Considerando o atual cenário em que tentamos deixar as coisas conectadas, é comum nos depararmos com uma situação em que tentamos deixar um projeto conectado à rede ou internet, propriamente, aliado a funcionalidades de controle de alguma aplicação específica, tal como acender um LED, ligar um relé, ler um sensor, etc. Isso envolve um aumento expressivo na complexidade da aplicação, ainda mais se a mesma for baremetal, ou seja, você está fazendo o código C na raça, lidando com requisições TCP/UDP, tratando eventos diversos e etc. Em suma, isso não fica bonito… E quando você pretende fazer sua página Web, há uma grande mistura de código C, da aplicação, com código HTML, de exibição da página. Menos bonito ainda 🙁

Quem já tentou fazer uma simples página do tipo “Apertar um botão e acender um LED” com Arduino e Shield Ethernet sabe do que estou falando..

Nada melhor do que… delegar funções! Ou seja, uma parte do sistema trata as coisas mais alto nível, mais complexas, tais como requisições Web, exibição de páginas, demais coisas. E outra parte do sistema trata das atividades de mais baixo nível, tais como leitura de sensores, controle de servos, etc. Mas… Como integrar essas duas partes?

Aí que reside a “sacada”. O Arduino (tradicional) é energizado e realiza comunicação pela porta USB.

Sistema Web com Raspberry Pi: Arduino e porta USB

Figura 1: Vista da porta de conexão USB Tipo-B do Arduino. Fonte: sparkfun.com

E as placas da família Raspberry Pi possui uma (Raspberry Pi A+) ou mais portas USB (Raspberry Pi B tem 2 portas, e os modelos Raspberry Pi B+ e Raspberry Pi 2 Model B têm 4 portas).

Sistema Web com Raspberry Pi: The Pi board Family

Figura 2: Modelos de Raspberry Pi – com legenda. Fonte: raspi.tv

Ou seja, plug-and-play! Porém… Nem tudo são flores… Pois algumas questões surgem:

  1. Como comunicar via USB – principalmente no lado da Raspberry Pi?
  2. Como desenvolver uma interface Web capaz de ler dados do Arduino e enviar comandos para o Arduino?
  3. Quais linguagens e plataformas usar?

Pois bem. Vamos responder essas questões e elaborar o artigo:

  1. Ao plugar a USB do Arduino na Raspberry Pi, será criado um device de comunicação serial, normalmente nomeado como ttyACM0. Com isso, basta realizar processo de leitura/escrita em serial com o baudrate configurado no Arduino também;
  2. É preciso ter uma base que seja capaz de realizar comunicação com devices do sistema e que também seja capaz de lidar com requisições Web. É preciso ter um Servidor Web em operação, ou uma aplicação que faça interface com requisições de rede. Em se tratando de servidores Web, temos as opções Apache, Lighttpd e Nginx, dentre os mais difundidos. Para comunicar com o Arduino, existem as seguintes opções:
    • Usar CGI: Você escreve um código no servidor, e o servidor Web faz uma ponte entre a requisição Web e seu código no servidor;
    • Aplicação com interface Web: Você escreve uma aplicação no servidor capaz de responder a requisições Web e gerar respostas específicas.
  3. Com relação às linguagens, temos as seguintes opções:
    • Exibição: HTML  – uma linguagem que formata o conteúdo Web, e CSS dá o “embelezamento” (fonte, cores, ajuste de texto, etc);
    • Código no Servidor Web com CGI: Você pode escrever aplicações nas seguintes linguagens, que irão interagir com o servidor Web quando houver requisições, gerando também respostas aos clientes Web:
    • Aplicação Nativa: É possível escrever uma Aplicação Nativa, capaz de responder a requisições Web, nas linguagens tais como Python, C, C++, JavaScript (Node.JS), dentre outros. Pesquise sobre a linguagem de seu interesse e bibliotecas que tornem possível sua integração com rede, respondendo em requisições TCP/UDP, por exemplo.

Para efeito de demonstração, o presente artigo fará uso de Lighttpd com PHP configurado com FastCGI, juntamente com uma biblioteca para PHP para comunicação com Serial TTY, de modo a demonstrar a integração da Raspberry Pi com Arduino na criação de uma interface Web capaz de controlar elementos de hardware.

Configuração da Raspberry Pi

Com relação à Raspberry Pi, vou tratar os seguintes itens tendo como base o sistema operacional Raspbian instalado. Caso você tenha a sua Raspberry Pi ou outro sistema, use os itens como referência para o seu modelo ou caso.

Aviso: Os seguintes passos demandam o acesso ao terminal (shell) do sistema Raspbian, o que pode ser feito tanto via SSH, como feito nativamente, caso você esteja usando sua Raspberry Pi ligada a um monitor, com teclado e mouse, ou até mesmo se você ligou um conector USB-TTL na UART da Raspberry Pi para acesso direto ao seu terminal. Além disso, tomarei por base que os comandos são realizados pelo usuário pi.

Tendo por base que a Raspberry Pi é um sistema embarcado, com recursos mais limitados de processamento e memória, é um tiro no pé a instalação tradicional do servidor Web Apache2, por mais intuitivo que seja. Ele consome muita memória, e isso vai deixar seu sistema pesado.

Dito isso, proceda com a instalação do Lighttpd e do PHP com o seguinte comando:

$ sudo apt-get install lighttpd php5

Muito provavelmente o comando também incorrerá na instalação do Apache2. Como não o queremos na Raspberry Pi, podemos desinstalá-lo com o seguinte comando:

sudo apt-get remove apache2.2-bin

Mesmo tendo instalado o Lighttpd e o PHP, a “ponte” entre os dois ainda não foi estabelecida. Ela é feita por meio do módulo FastCGI, e este módulo pode ser habilitado para o PHP com o seguinte comando:

$ sudo lighttpd-enable-mod fastcgi fastcgi-php

O que também pode ser feito com o comando abreviado “lighty-enable-mod”, já que Lighttpd é pronunciado como “lighty”:

$ sudo lighty-enable-mod fastcgi fastcgi-php

Feito isso, é preciso reiniciar o serviço do Lighttpd:

sudo service lighttpd force-reload

Se tudo correu certo até aqui, estamos com Lighttpd funcionando e PHP funcionando. Para ter certeza disso, vá até o diretório /var/www/, crie um arquivo PHP chamado teste.php e coloque o seguinte código neste arquivo:

<?php

echo phpinfo(); //a funcao phpinfo() exibe detalhes sobre o php instalado!

?>

Feche o arquivo. Veja qual é o endereço IP da sua Raspberry Pi por meio do comando “ifconfig” no console, tal como mostrado na figura adiante:

Sistema Web com Raspberry Pi: saída do ifconfig

Figura 3: Exibição do comando ifconfig em console na Raspberry Pi

Agora, abra uma janela do seu navegador de preferência (Chrome, Firefox, etc), e digite como endereço de página web uma URL composta pelo endereço IP retornado pelo comando ifconfig, acrescido de “/teste.php“. No meu caso, ficou  assim: http://192.168.1.18/teste.php. Se tudo correr bem, você verá no seu navegador uma tela parecida com a mostrada abaixo, indicando todo um relatório sobre o PHP instalado na Raspberry Pi, além de outras informações de sistema.

Sistema Web com Raspberry Pi: Tela de informações sobre o PHP em Execução

Figura 4: Tela de informações sobre o PHP em Execução.

Se você teve algum problema, ou seja, não apareceu a tela esperada, podem ser duas coisas:

  1. Os pacotes não foram apropriadamente instalados;
  2. Problemas de permissão no diretório www.

Caso algum pacote não tenha sido apropriadamente instalado, reinstale. Caso tenha problemas de permissão, realize os seguintes comandos abaixo:

sudo adduser pi www-data
sudo chown pi:www-data -R /var/www
sudo chmod 0755 -R /var/www
sudo chmod g+s -R /var/www

Estes comandos irão adicionar o usuário pi ao grupo www-data, que é o grupo que possui permissão no diretório /var/www/, onde devem ficar os arquivos da nossa interface Web. Além disso, é colocada a permissão 755 no diretório, além da permissão g+s, que garante a associação de permissão de grupo em futuros arquivos e subdiretórios.

Além disso, para que a nossa interface Web, executada pelo grupo www-data, consiga acessar devices do sistema Linux que façam comunicação via Serial TTY, é preciso adicionar o usuário dialout ao grupo www-data, pois este usuário é que possui permissão de acesso ao dispositivos /dev/tty* do Linux. O comando para realizar isso é mostrado adiante:

usermod -a -G dialout www-data

Apenas para garantir, reinicie o sistema da Raspberry Pi.

Estruturação do Modelo

Para o nosso presente caso, iremos tratar uma comunicação realizada entre o Arduino e a Raspberry Pi via USB. O Arduino irá tratar das tarefas de baixo nível, e a Raspberry Pi, das tarefas de alto nível, tais como interface com a Rede e Internet.

Sistema Web com Raspberry Pi e Arduino: Estruturação do Modelo Arduino + Raspberry Pi

Figura 5: Estruturação do Modelo Arduino + Raspberry Pi

No nosso humilde exemplo, iremos conectar um LED ao Arduino, o qual será controlado pela nossa página Web armazenada na Raspberry Pi. E no Arduino também iremos conectar um botão do tipo “pushbutton”, cujo estado será mostrado na mesma página armazenada na Raspberry Pi.

Porém… Como iremos tratar a comunicação entre ambos, via USB? Temos que bolar um PROTOCOLO!

Um protocolo é uma regra que estabelece como a comunicação deverá ser realizada entre ambas as partes, para que ambos consigam se entender. De certa forma, você e eu usamos o “protocolo” que é a língua portuguesa para nos entendermos.

Dentre os vários modelos que existem, nos quais podemos nos basear, o meu favorito é o NMEA. Ele foi criado como base para os receptores de GPS, e, em suma, consiste em sentenças ASCII cujas informações são separadas por vírgula.

O fato de você separar as informações por vírgula facilita muito o processo, pois quem irá receber a informação precisará separas as informações pelas vírgulas, e saber precisamente a ordem com que estas informações foram enviadas.

Para o nosso modelo, vamos trabalhar da seguinte forma:

  • Arduino: Irá enviar mensagens com a seguinte forma: “$STS,botaoStatus,ledStatus,\n” – Ou seja, a primeira informação pode indicar do que se trata a mensagem, no caso, eu uso $STS como mnemônico para Status, e depois manda-se a informação de botaoStatus (que pode ser 0 ou 1) e ledStatus (que pode ser 0 ou 1). Ou seja, sabemos o que virá em cada campo separado por vírgula;
  • Raspberry Pi: Irá enviar o caractere ‘a’ para acender um LED ligado no Arduino, e ‘d’ para apagar o LED ligado no Arduino. E receberá as respostas geradas pelo Arduino.

Código Arduino e Configuração do Arduino

Com base no que foi projetado anteriormente, vamos partir para a codificação do Arduino, de modo que o mesmo faça o controle do LED e a leitura do botão, assim como também receber comandos da Raspberry Pi pela Serial e informar o status dos componentes pela Serial. Segue adiante o código desenvolvido para esta atividade.

int LED = 10;
int BOTAO = 7;
boolean botaoStatus = false;
boolean ledStatus = false;
char leituraSerial;

void setup() {
  Serial.begin(9600); //Inicia serial 
  pinMode(BOTAO, INPUT_PULLUP); //entrada do botao com pull-up acionado
  pinMode(LED, OUTPUT); //led como saida
}

void loop() {
  //Se chegar dado da serial, avaliamos e comandamos.
  if(Serial.available() > 0){
    leituraSerial = (char) Serial.read();
    //Foi a letra 'a'? Acende o led.
    if(leituraSerial == 'a'){
      digitalWrite(LED,HIGH);
      ledStatus = true;
    }
    //Foi a letra 'd'? Apaga o led.
    if(leituraSerial == 'd'){
      digitalWrite(LED,LOW);
      ledStatus = false;
    }
  }
  //No loop, faremos a leitura do botao. Se estiver em 0, pelo pull-up,esta pressionado
  if(digitalRead(BOTAO) == 0){
    botaoStatus = true;
  } else {
    botaoStatus = false;
  }
  //Ao termino do processo, enviamos via Serial para Raspberry Pi um status, indicando
  //como estao os elementos. As informacoes sao separadas por virgula. Delay de 250ms.
  Serial.print("$STS,");
  Serial.print(botaoStatus);
  Serial.print(",");
  Serial.print(ledStatus);
  Serial.print(",");
  Serial.println();
  delay(250);
}

Como exemplo de como fiz as ligações dos componentes em protoboard, segue o esquemático da minha montagem em Fritzing:

Sistema Web com Raspberry Pi: Esquema de conexões com Arduino - Ligações com LED e Botão

Figura 6: Esquema de conexões com Arduino – Ligações com LED e Botão.

Após programado, é necessário colocar um capacitor de 10uF entre os sinais GND e Reset do Arduino para evitar que o mesmo seja reiniciado a cada conexão USB. Caso contrário, a cada vez que a Raspberry Pi for iniciar uma comunicação, todo o programa em execução no Arduino entrará em reset. Veja na figura abaixo como ficará a ligação do capacitor, tendo como base o Arduino UNO:

Sistema Web com Raspberry Pi: Arduino schematic + capacitor

Figura 7: Arduino com Capacitor de 10uF entre GND e Reset. Fonte: CreativeApplications.net

Código PHP

Para fazer o código PHP de controle da Serial, foi usada a Biblioteca PhpSerial. Para usar essa biblioteca, basta realizar o download do arquivo “PhpSerial.php” no diretório /var/www, de modo que o mesmo seja encontrado pelo nosso próprio arquivo PHP.

Há um pequeno problema nessa biblioteca, na parte em que trata se há uma serial no ambiente Linux, precisamente na linha 50:

if ($this->_exec("stty") === 0) {

Este código não vai funcionar, e gerará uma mensagem de erro quando você tentar usar. Troque para:

if ($this->_exec("which stty") === 0) {

Feita a modificação, salve e feche o arquivo PHP da biblioteca PhpSerial.php.

Após isso, vamos então escrever o código da nossa página de controle. Para o meu exemplo, chamei a minha página de serial.php, e coloquei o código no arquivo da página. Observe que está precisamente comentado, incluindo as partes que lidam com comunicação Serial usando a biblioteca PHP citada.

<?php
//rotinas para habilitar a exibicao de erros na pagina. Tire se nao quiser.
error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE);
ini_set('display_errors', '1');

include "PhpSerial.php"; //import da biblioteca de serial com php
$read = "";

$serial = new phpSerial(); //Cria um novo objeto para comunicacao serial
$serial->deviceSet("/dev/ttyACM0"); //associa esse objeto com a serial do Arduino
$serial->confBaudRate(9600); //configura baudrate em 9600
$serial->confParity("none"); //sem paridade
$serial->confCharacterLength(8); //8 bits de mensagem
$serial->confStopBits(1); //1 bit de parada
$serial->confFlowControl("none"); //sem controle de fluxo
$serial->deviceOpen(); //abre o dispositivo serial para comunicacao

//Se receber 'a' via GET na Pagina
if(isset($_GET['a'])){
	//sleep(2);
	$serial->sendMessage("a"); //envia o caractere 'a' via Serial pro Arduino
	sleep(1); //delay para o Arduino enviar a resposta.
	$read = $serial->readPort(); //faz a leitura da resposta na variavel $read
	echo $read; //echo para mostrar a resposta recebida do Arduino
}

//Se receber 'd' via GET na pagina
if(isset($_GET['d'])){
	//sleep(2);
	$serial->sendMessage("d"); //envia o caractere 'd' via Serial pro Arduino
	sleep(1); //delay para o Arduino enviar a resposta
	$read = $serial->readPort(); //faz a leitura da resposta na variavel $read
	echo $read; //echo para mostrar a resposta recebida do Arduino
}
$serial->deviceClose(); //encerra a conexao serial

?>


<html>
<head></head>

<body>
<h1> Raspi + Arduino </h1>

<input type="button" 
	onclick="location.href='/serial.php?a=1'"
	value="Acende LED" />

<input type="button"
	onclick="location.href='/serial.php?d=1'"
	value="Apaga LED" />
	
<? 
$resultado = explode(",",$read);
echo "<p> Estado do botao: " . $resultado[1] . "</p>";
echo "<p> Estado do LED: " . $resultado[2] . "</p>";
?>

</body>
</html>

Execução

Para a boa execução da Serial pelo PHP, ainda fica faltando mais uma coisa. É preciso digitar o seguinte comando abaixo para garantir que o dispositivo serial /dev/ttyACM0, usado pelo Arduino, opere corretamente.

$ sudo stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts

Feito isso, digite o caminho da sua página PHP em seu navegador de preferência, e veja o resultado da página. Clique no botão “Acende LED”, e verá o LED acender. Clique no botão “Apaga LED”, e verá o LED apagar.  E no momento em que você apertar nos botões, a resposta que virá da Raspberry Pi também informará o status do botão. Mas isso é porque este modelo foi arquitetado assim.

Veja como ficou o meu exemplo abaixo. Eu cliquei no botão “Acende LED”, e no mesmo momento eu também estava pressionando o botão conectado ao Arduino.

Sistema Web com Raspberry Pi: página web

Figura 8: Página Web da Integração Raspberry Pi com Arduino

Sistema Web com Raspberry Pi: Sistema running!

Figura 9: Foto da correspondente ação no mundo real 🙂

É normal ocorrer alguns problemas, chegarem alguns caracteres “zoados”. Quer resolver? Trabalhe em cima da “temporização” da comunicação. Trate o recebimento de caracteres até a quebra de linha, dentre outras coisas.

Achou super interessante? Veja mais sobre a linguagem PHP no CodeAcademy, e estude mais sobre HTML também no CodeAcademy, assim você pode ficar craque na parte de Web, aprender como fazer uma página Web ser atualizada automaticamente, usar recursos JavaScript e embelezar a página com CSS. Além, é claro, de toda a funcionalidade por trás dos bastidores!

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather