Berry·E Mini Robô com Câmera e Raspberry Pi Zero W

Mini Robô

Introdução

Temos visto nos últimos anos uma crescente em computadores embarcados com conectividade Wi-Fi e Bluetooth. Podemos encontrá-los tanto no mundo maker e educacional como industrial. Um exemplo da indústria é a Toradex que no início deste ano anunciou seu primeiro módulo Colibri com conectividade Wi-Fi e Bluetooth.

Já os amantes do mundo maker e educacional ficaram muito animados no início deste ano, com a chegada do computador Raspberry Pi Zero W, que trouxe a mesma possibilidade de conexão usando Wi-Fi e Bluetooth, de sua irmã maior, a Raspberry Pi 3.

Este artigo tem por objetivo mostrar como tomar proveito da conectividade wireless da Raspberry Pi Zero W para desenvolver um pequeno robô que, além de ser controlado via aplicativo de smartphone, faz streaming de vídeo em tempo real para a tela do aplicativo. Veremos conceitos sobre Webserver com Node.js, troca de dados cliente/servidor em tempo real com socket.io, streaming com MJPG-streamer dentre outros temas.

Mini Robô

Estrutura Mecânica do Robô

O robô foi montado utilizando uma estrutura da Pololu. É um chassi tipo esteira de tamanho compacto e com possibilidade de customização. É feito de plástico ABS, possui compartimento para 4 pilhas AA e furação para fixação de diversos tipos de shield e acessórios.

Mini Robô
Figura 1 – Chassi do Robô

Foram utilizados dois motores DC, que encaixam perfeitamente no chassi, com redução em engrenagens de metal. Funcionam com até 12VDC.

Mini Robô
Figura 2 – Motor DC

Para acomodar a eletrônica e outros componentes, foi projetada uma estrutura no software Fusion 360 e impressa em 3D.

Mini Robô
Figura 3 – Estrutura Impressão 3D

Principais Componentes Eletrônicos

Raspberry Pi Zero W

A placa principal, o cérebro do robô, consiste de uma Raspberry Pi zero W com processador Cortex ARM e conectividade Wi-Fi e Bluetooth. Por se tratar de uma placa que roda sistema operacional Linux, é possível desenvolver em C/C++, Python, Node.js dentre outras linguagens. Para este robô foi utilizado Node.js pois é uma linguagem que facilita o uso de recursos Web.

Mini Robô
Figura 4 – Raspberry Pi Zero W

Driver Motor L293D Hat para Raspberry Pi

Uma placa desenvolvida especialmente para ser usada juntamente com os modelos da Raspberry Pi 2, 3 e Zero. É possível controlar até 4 motores DC. É um projeto open hardware e você pode apoiá-lo contribuindo no GitHub ou adquirindo uma unidade aqui.

Mini Robô
Figura 5 – Driver L293D para Raspberry Pi

Veja o manual da placa disponível aqui, com instruções de montagem, funcionamento e exemplos de programação em Python, C e Node.js.

Câmera Raspberry Pi

Foi utilizado um módulo de câmera genérico mas que tem o mesmo conector para Raspberry Pi. Com essa câmera é possível tirar fotos e gravar vídeo.

Mini Robô
Figura 6 – Câmera Raspberry Pi

Funcionamento do sistema

Mini Robô
Figura 7 – Funcionamento do sistema
  • Aplicativo Web no Smartphone

O usuário utiliza um aplicativo Web no smartphone para o controle do robô. No aplicativo temos um joystick virtual com o qual se controla o robô enviando os comandos via WiFi. Além do joystick é possível visualizar o vídeo da câmera embarcada no robô em tempo real através do MJPG-Streamer. Esse aplicativo é escrito em HTML e javascript e é executado no navegador do smartphone.

  • MJPG-Streamer

MJPG-streamer faz streaming de vídeo da câmera, através do protocolo HTTP, para a aplicação web no navegador do celular. O streaming poderá ser visto em qualquer navegador acessando o IP da Raspberry Pi.

  • Web server Node.js executando na Raspberry Pi

Um web server escrito em Node.js é responsável por “servir” a aplicação Web ao cliente(navegador web no smartphone). É responsável também por receber os comandos do aplicativo do celular e convertê-los em comandos para o driver de motor. Essa troca de dados é feita em tempo real usando socket.io.

  • Driver motor L293D para Raspberry Pi

A Raspberry Pi envia os comandos para determinados pinos GPIO que por sua vez controlam os motores através do driver L293D.

A seguir podemos ver mais detalhadamente o funcionamento de cada parte do sistema.

Aplicativo Web

A aplicação web executada no smartphone é escrita em HTML e javascript. A aplicação exibe um streaming de vídeo em tela cheia e também um joystick virtual para controle do robô. Veja abaixo o código completo do arquivo index.html da aplicação web.

<!DOCTYPE html>
<html>
   <head>
       <meta charset="UTF-8">
       <title>Berry-E Robot</title>
       <link rel="stylesheet" type="text/css" href="css/style.css">
       <link rel="manifest" href="manifest.json">
       <script src="nipplejs/dist/nipplejs.min.js"></script>
       <script src="/socket.io/socket.io.js"></script>
   </head>   
   <body>  
       <div id="dynamic" style="position: absolute; width:100%; height:100%">
           <img id="video" width="100%" height="100%" src="https://192.168.0.55:8080/?action=stream" style="position: fixed;">
       </div>
       <script>
           var socket = io();
           var dynamic = nipplejs.create({
               zone: document.getElementById('dynamic'),
               color: 'black',
               size: 200
           });
           dynamic.on('plain:up plain:down plain:left plain:right', function (evt, data) {
                   socket.emit('joystickData', data.direction.angle);
           }).on('end', function (evt, data) {
                   socket.emit('joystickReleased',evt.type);
           });
       </script>           
   </body>
</html>

O vídeo é carregado através de uma tag <img> buscando o streaming de vídeo no IP da Raspberry Pi.

" ><img id="video" width="100%" height="100%" src="https://192.168.0.55:8080/?action=stream" style="position: fixed;">

O josytick utilizado foi o nippleJS. É um joystick virtual escrito em javascript que pode ser usado em telas touch. No trecho seguinte de código é declarado o joystick do tipo dinâmico, na cor preta e de tamanho 200.

var dynamic = nipplejs.create({
    zone: document.getElementById('dynamic'),
    color: 'black',
    size: 200
});

Em seguida monitoramos os eventos up, down, left e right e end. Os dados de posicionamento do joystick são enviados ao servidor em tempo real usando socket.io através de socket.emit. Esses eventos serão tratados posteriormente pelo servidor Node.js.

dynamic.on('plain:up plain:down plain:left plain:right', function (evt, data) {
                   socket.emit('joystickData', data.direction.angle);
}).on('end', function (evt, data) {
                   socket.emit('joystickReleased',evt.type);
});
Mini Robô
Figura 8 – Posições Joystick NippleJS

O nippleJS pode ser customizado de muitas formas. Veja sua documentação completa aqui.

Para que a aplicação tenha um “feeling” de aplicação nativa, foi utilizado um arquivo chamado manifest.json. Com este arquivo é possível definir um nome a aplicação, ícone, modo de exibição na tela e etc. O manifest.json também fornece a capacidade de salvar um site marcado como favorito na tela inicial de um dispositivo. Mais informações sobre essa técnica aqui.

{
 "short_name": "Berry-E Robot",
 "name": "Berry-E Robot",
 "icons": [
   {
     "src": "/images/robot-icon.png",
     "sizes": "192x192",
     "type": "image/png"
   }
 ],
 "start_url": "/index.html",
 "display": "fullscreen",
 "orientation": "landscape"
}
Mini Robô
Figura 9 – Ícone do Aplicativo
Mini Robô
Figura 10 – Aplicativo no Celular

MJPG-Streamer na Raspberry Pi

A instalação do MJPG-streamer na Raspberry Pi é bem simples. Os passos são mostrados a seguir.

Clone o repositório em uma pasta do sistema:

cd /home/pi
git clone https://github.com/jacksonliam/mjpg-streamer.git

Instale os seguintes programas necessários para compilação do MJPG-streamer.

sudo apt-get install cmake libjpeg8-dev

Então inicie a compilação.

cd mjpg-streamer/mjpg-streamer-experimental
make
sudo make install

Após a compilação você deve notar que temos um binário chamado mjpg_streamer e também alguns plugins .so dentre eles o input_raspicam.so e output_http.so.

Antes de executar o MJPG-streamer, certifique-se de que sua Raspberry está conectada a uma rede Wi-Fi e que a interface de câmera está configurada no raspi-config. Para executar o MJPG-streamer com a câmera da Raspberry Pi utilize os comandos abaixo.

export LD_LIBRARY_PATH=.
./mjpg_streamer -o "output_http.so -w ./www" -i "input_raspicam.so"

Se tudo ocorrer bem você poderá acessar o stream na URL seguinte:

https://<IP-raspberry>:8080/?action=stream

Note que usamos a mesma URL no código HTML da aplicação web.

Web Server Node.js

O programa escrito em Node.js utiliza o Express para “servir” o arquivo index.html, que é a nossa aplicação web, para qualquer cliente que se conecte no IP da Raspberry Pi. Assim que os dados de posicionamento do joystick começam a ser enviados do lado cliente, o servidor recebe esses dados e os converte para controlar o driver de motor. Essa comunicação é feita em tempo real utilizando socket.io. Veja o código completo do servidor abaixo:

var express = require('express');
var app = express();
var path = require('path');
var server = require('http').Server(app);
var io = require('socket.io')(server);
var rpio = require('rpio');

app.use(express.static(path.join(__dirname, '/public')));

// declaracao dos GPIOs motor A
const M1A = 31
const M1B = 15
const M1EN = 11

// declaracao dos GPIOs motor B
const M2A = 18
const M2B = 13
const M2EN = 29

// configuracao dos GPIOs como saida
rpio.open(M1A, rpio.OUTPUT, rpio.LOW);
rpio.open(M1B, rpio.OUTPUT, rpio.LOW);
rpio.open(M1EN, rpio.OUTPUT, rpio.LOW);
rpio.open(M2A, rpio.OUTPUT, rpio.LOW);
rpio.open(M2B, rpio.OUTPUT, rpio.LOW);
rpio.open(M2EN, rpio.OUTPUT, rpio.LOW);

// declaracao das funcoes de movimentacao frente, tras, esquerda, direita
function goForward() {
 rpio.write(M1A, rpio.LOW);
 rpio.write(M1B, rpio.HIGH);
 rpio.write(M2A, rpio.HIGH);
 rpio.write(M2B, rpio.LOW);
}
function goBackward() {
 rpio.write(M1A, rpio.HIGH);
 rpio.write(M1B, rpio.LOW);
 rpio.write(M2A, rpio.LOW);
 rpio.write(M2B, rpio.HIGH);
}
function goLeft() {
 rpio.write(M1A, rpio.HIGH);
 rpio.write(M1B, rpio.LOW);
 rpio.write(M2A, rpio.HIGH);
 rpio.write(M2B, rpio.LOW);
}
function goRight() {
 rpio.write(M1A, rpio.LOW);
 rpio.write(M1B, rpio.HIGH);
 rpio.write(M2A, rpio.LOW);
 rpio.write(M2B, rpio.HIGH);  
}
function enableMotors() {
 rpio.write(M1EN, rpio.HIGH);
 rpio.write(M2EN, rpio.HIGH);
}
function disableMotors() {
 rpio.write(M1EN, rpio.LOW);
 rpio.write(M2EN, rpio.LOW);
}

io.on('connection', function(socket){
 console.log('a user connected');
 socket.on('disconnect', function(){
   console.log('user disconnected');
   disableMotors();
 });
 socket.on('joystickData', function(joystickData){
   console.log(joystickData);
   enableMotors();
   if(joystickData == 'up') goForward();
   if(joystickData == 'down') goBackward();
   if(joystickData == 'left') goLeft();
   if(joystickData == 'right') goRight();
 });
 socket.on('joystickReleased', function(){
   console.log('Stop');
   disableMotors();
 });
});

server.listen(3000, '192.168.0.55', function () {
 var port = server.address().port
 console.log('Server listening:%s...', port);
});

O servidor monitora o evento joystickData. Quando os dados vão sendo recebidos, a função de movimentação correspondente é chamada.

socket.on('joystickData', function(joystickData){
   console.log(joystickData);
   enableMotors();
   if(joystickData == 'up') goForward();
   if(joystickData == 'down') goBackward();
   if(joystickData == 'left') goLeft();
   if(joystickData == 'right') goRight();
 });

Para controle de GPIOs através de Node.js, foi utilizado pacote chamado rpio. Mais detalhes aqui.

Driver Motor L293D para Raspberry Pi

O driver desenvolvido pode controlar até 4 motores mas para este projeto foram utilizados apenas 2 motores. O driver tem o mesmo fator de forma da Raspberry Pi Zero e segue a pinagem abaixo:

Mini Robô
Figura 11 – Pinagem Driver L293D

São utilizado 3 pinos de controle para cada motor. Dois pinos indicam o sentido e 1 pino habilita/desabilita o movimento.

Funcionamento Driver L293D
Figura 12 – Funcionamento Driver L293D

Por exemplo, na seguinte função em Node.js, ativa-se um motor no sentido horário e outro anti-horário, fazendo com que o robô se movimente para frente.

function goForward() {
 rpio.write(M1A, rpio.LOW);
 rpio.write(M1B, rpio.HIGH);
 rpio.write(M2A, rpio.HIGH);
 rpio.write(M2B, rpio.LOW);
}

Para saber mais sobre este driver de motor, o articulista do Embarcados Pedro Bertoleti, fez um super review em vídeo, explicando vários pontos técnicos dessa placa. Confira o vídeo na íntegra aqui.

Conclusão

Com os vários conceitos mostrados neste artigo, foi possível desenvolver um pequeno robô controlado pelo celular tomando proveito da conectividade Wi-Fi da placa Raspberry Pi Zero W. Utilizando-se de recursos web tanto do lado cliente como servidor foi possível desenvolver um aplicativo web para smartphone que contém um joystick virtual e exibe streaming de vídeo em tempo real.

Veja um vídeo do robô em funcionamento:

O código fonte de toda aplicação pode ser encontrado no GitHub.  

Referências

Express – https://expressjs.com/

Socket.io – https://socket.io/

NippleJS – https://yoannmoinet.github.io/nipplejs/

node-rpio – https://github.com/jperkin/node-rpio

Aplicativos web com Manifest.json

MJPG-Streamer – https://github.com/jacksonliam/mjpg-streamer

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
4 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
rafah_oliveira
rafah_oliveira
20/10/2017 11:29

Olá, qual seria o link do código do github? O código está todo aqui no artigo, mas eu gostaria de olhar o arquivo package.json.

Miller Oliveira
Miller Oliveira
12/10/2017 22:01

Parabéns Giovanni, excelente projeto!

Giovanni Bauermeister
Giovanni Bauermeister
Reply to  Miller Oliveira
13/10/2017 09:42

Obrigado Miller!

Os comentários estão desativados.

Home » Raspberry Pi » Berry·E Mini Robô com Câmera e Raspberry Pi Zero W

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: