0

Robot controlado por voz via WiFi

O diagrama de blocos abaixo nos dá uma geral sobre o projeto que desenvolveremos aqui:

WiFi_Robot_Block_Diagram

e o filme mostra-nos como ficará o projeto:

Por favor, considere que um de meus motores estava com muito pouco torque. Apesar de o resultado parecer estranho, o projeto funciona a contento. Assim que mudar o motor, atualizarei o vídeo. Obrigado.

1: Lista de materiais (BoM)

 

  1. NodeMCU ESP8266-12E
  2. 400-point Experiment Breadboard Breadboard
  3. H-Bridge L293D
  4. Motor Robot Car Chassis Kit
  5. Male-Female Dupont Cables
  6. Portable Charger 5VDC 3000mAh Power Bank
  7. Bateria 9V DC

….. e qualquer telefone ou tablet Android!

2: A Ponte-H L293D

L293D

Para “drivar” os motores usaremos o L293D.

De acordo com seu Datasheet, o L293D é um controlador do tipo half-H quádruplo de alta corrente. O L293D foi projetado para fornecer correntes bidirecionais de até 600 mA em tensões variando de 4,5 V a 36 V.

Usaremos o CI L293D diretamente com o NodeMCU, em vez de um Shield, como se vê mais comumente em projetos no mercado.

Pois bem, nosso robot terá duas rodas, acionadas por 2 motores DC:

  • Motor esquerdo (LEFT)
  • Motor direito (RIGHT)NodeMCU_L293D_Block_Diagram
  • Ligaremos os motores ao L293D e este ao NodeMCU, como mostra o diagrama em blocos anterior, onde 6 de seus GPIOs comandarão esses motores.
 
int rightMotor2 = 13;   // D7 - right Motor -
int rightMotor1 = 15;   // D8 - right Motor +
int leftMotor2 = 0;     // D3 - left Motor - 
int leftMotor1 = 2;     // D4 - left Motor +
int eneLeftMotor = 12;  // D6 - enable Motor Left
int eneRightMotor = 14; // D5 - enable Motor Right
 

Por exemplo, para mover o robô para a frente,  girando o motor esquerdo (LEFT) no sentido apropriado, você deve colocar:

  • HIGH no pino D4 (motor esquerdo +) e
  • LOW no pino D3 (motor esquerdo -)

Para o motor direito (RIGHT) você deve fazer o oposto:

  • HIGH no pino D8 (motor direito +) e
  • LOW no pino D7 (motor esquerdo -)
  • The H-Bridge L293D
  • Devido à maneira como meus motores são montados, a combinação acima irá girar ambos motores no mesmo sentido, “empurrando” o robot para a frente.
  • Robot direction.jpg
  • O diagrama acima define (ou melhor, convenciona) como o robot deverá se mover. Isso é importante para a definição adequada de suas variáveis.

    Para controlar a H-Bridge corretamente, você também deverá trabalhar com os pinos de habilitação (“enable”). No exemplo anterior onde o robô se move para a frente, além dos 4 GPIOs discutidos, o robot só funcionaia se os pinos de habilitação (eneLeftMotor e eneRightMotor) estiverem ambos em HIGH. Poderá conectar esses pinos do L293D (1 e 9) diretamente a + VCC e esquecê-los. Eu não gosto disso, porque se necessitar por exemplo, parar rapidamente seu robot, esses pinos deveriam estar em necessariamente em LOW. Além disso, associar os pinos de habilitação a saídas PWM do NodeMCU, permitirá também controlar a velocidade do motor. Em nosso exemplo, usaremos estes pinos apenas com valores digitais tais como HIGH e LOW, o que ajustará a velocidade para MAX e ZERO, respectivamente.

    Asim, para se criar uma função que conduza nosso robot para a frente, devemos escrever um código como este:

 
void forwardMotor(void)   
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
    
  digitalWrite(leftMotor1,HIGH);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}
 

3: Movendo o robot noutras direções

Na etapa anterior, aprendemos como podemos mover o robot para a frente, pensemos agora como movê-lo em outras direções.
Definamos 5 possíveis comandos:
  1. STOP: Pare
  2. LEFT: Vire à esquerda
  3. RIGHT: Vire à direita
  4. REVERSE: Dê marcha à ré
  5. FORWARD: Vá para a frente

O primeiro comando “STOP” é simples de realizar. Todas as entradas da H-Bridge devem estar em LOW, desta forma os motores não se moverão:

 
void stopMotor(void)   
{
  digitalWrite(eneLeftMotor,LOW);
  digitalWrite(eneRightMotor,LOW);

  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,LOW);
}
 

Da mesma forma pensemos em fazer o robot tomar outra direção, digamos que “virar à ESQUERDA”. Considere que o robot está indo para a frente, se queremos virar à esquerda podemos pensar em duas situações:

  1. Parar o motor ESQUERDO, mantendo o motor DIREITO no sentido a frente (Forward): o robot executará uma trajetória de arco para a esquerda
  2. Inverter o sentido do motor ESQUERDO, mantendo o motor DIREITO no sentido a frente (Forward): o robot irá girar sobre seu eixo para a esquerda.

Implementemos o caso 2 acima:

 
void leftMotor(void)   
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH); 
  
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,HIGH);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}
 

Os demais comandos seguirão a mesma lógica, como ilustra a tabela abiaxo:

Moving the Robot Around

4: Completando o HW

Completing the HW

Siga o diagrama acima e complete o HW de seu Robot.

Você poderá executar alguns testes simples para verificar que seu código está OK.  Para isto, introduziremos um “botão” para iniciar o seu robot. Vamos instalá-lo na porta D0 do NodeMCU como mostrado no diagrama elétrico anterior.

Você poderá utilizar o programa abaixo para testar os movimentos do seu robot:

 
// Set Motor Control Pins
int rightMotor2 = 13;    // D7 - right Motor -
int rightMotor1 = 15;    // D8 - right Motor +
int leftMotor2 = 0;    // D3 - left Motor - 
int leftMotor1 = 2;    // D4 - left Motor +
int eneLeftMotor = 12;  // D6 - enable Mortor Left
int eneRightMotor = 14; // D5 - enable Mortor Right

int buttonPin = 16; // D0

void setup()
{
  Serial.begin(115200);

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(eneLeftMotor, OUTPUT); 
  pinMode(eneRightMotor, OUTPUT); 
  pinMode(leftMotor1, OUTPUT); 
  pinMode(leftMotor2, OUTPUT);  
  pinMode(rightMotor1, OUTPUT);  
  pinMode(rightMotor2, OUTPUT);  

  digitalWrite(eneLeftMotor,LOW);
  digitalWrite(eneRightMotor,LOW);
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,LOW);
      
  while (digitalRead(buttonPin))  // Wait for button to be pressed to move on 
  {  
  }
}

void loop()
{
  forwardMotor();
  delay (5000);
  stopMotor();
  delay (200);
  leftMotor();
  delay (3000);
  stopMotor();
  delay (200);
  forwardMotor();
  delay (5000);
  stopMotor();
  delay (200);
  rightMotor();
  delay (3000);
  stopMotor();
  delay (200);
  reverseMotor();
  delay (5000);
  stopMotor();
  delay (200);
} 

/* command motor forward */
void forwardMotor(void)   
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
    
  digitalWrite(leftMotor1,HIGH);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}

/* command motor backward */
void reverseMotor(void)   
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
  
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,HIGH);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,HIGH);
}

/* command motor turn left */
void leftMotor(void)   
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH); 
  
  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,HIGH);
  digitalWrite(rightMotor1,HIGH);
  digitalWrite(rightMotor2,LOW);
}

/* command motor turn right */
void rightMotor(void)   
{
  digitalWrite(eneLeftMotor,HIGH);
  digitalWrite(eneRightMotor,HIGH);
  
  digitalWrite(leftMotor1,HIGH);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,HIGH);
}

/* command motor stop */
void stopMotor(void)   
{
  digitalWrite(eneLeftMotor,LOW);
  digitalWrite(eneRightMotor,LOW);

  digitalWrite(leftMotor1,LOW);
  digitalWrite(leftMotor2,LOW);
  digitalWrite(rightMotor1,LOW);
  digitalWrite(rightMotor2,LOW);
}
 

Quando você pressionar o botão, o robot começará a fazer os movimentos definidos no loop (). Os movimentos continuarão até que você pressione “Reset” no NodeMCU. Pressionando o botão “verde” novamente, o ciclo se repetirá.

O código acima poderá ser baixado deste GitHub:

WiFi_Robot_NodeMCU_Android_Voice_Motor_tests

5: Montando o corpo do robot

body Assembly

  1. Use o Kit: Chassis, 2 Rodas, 2 Motores DC, 1 roda solta (coaster)
  2. Solde 2 fios de 10 cm (Vermelho e Preto) em cada polo do motor
  3. Fixe os motores ao chassi como mostrado na foto acima
  4. Monte o coaster
  5. Conecte os fios do motor à eletrônica (L293D)
  6. Fixe a bateria de 9V ao chassi
  7. Fixe a bateria de 5V sob o chassi

O robot deverá ficar com essa cara:

Body Final

6: Conectando o NodeMCU ao seu WiFi local

Conectemos o NodeMCU ao WiFi local, verificando seu endereço IP. Para isso, podemos utilizar o programa abaixo:

 
#include 
WiFiClient client;
WiFiServer server(80);
const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";

void setup() 
{
  Serial.begin(115200);
  connectWiFi();
  server.begin();
}

void loop() 
{
}

/* connecting WiFi */
void connectWiFi()
{
  Serial.println("Connecting to WIFI");
  WiFi.begin(ssid, password);
  while ((!(WiFi.status() == WL_CONNECTED)))
  {
    delay(300);
    Serial.print("..");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("NodeMCU Local IP is : ");
  Serial.print((WiFi.localIP()));
}
 

No monitor serial voce poderá observar o endereço IP dinâmico designado pelo Modem ao seu NodeMCU.

Connecting the NodeMCU to Local WiFi

Tome nota deste endereço de IP. Precisaremos dele para conectar o App Android.

O código acima poderá ser baixado deste GitHub:

NodeMCU_Connection_Test_EXT

7: Completando o código fonte para o NodeMCU

Para que nosso robô se mova, o NodeMCU deverá receber comandos provenientes do dispositivo Android. Para tal, definamos uma variável para receber estes comandos:

String  command ="";



Por exemplo, se a aplicação Android enviar como um comando: “forward” (a frente), o robot deverá avançar, invocando-se a função forwardMotor(). Veja abaixo:

 
if (command == "forward")
{
  forwardMotor();
}
 

O mesmo conceito deverá ser aplicado a todo os demais comandos e funções associadas tal como vimos no item 4:

  1. STOP: Pare
  2. LEFT: Vire à esquerda
  3. RIGHT: Vire à direita
  4. REVERSE: Dê marcha à ré
  5. FORWARD: Vá para a frente

Descarregue o código completo: WiFi_Robot_NodeMCU_Android_Voice_EXT deste GitHub.

Entre com as credenciais de sua rede local:

 

const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";

Carregue o código em seu NodeMCU e pronto! Você poderá verificar no Monitor Serial se o programa está em execução. Deixe o programa em execução para podermos testar o o aplicativo a ser desenvolvido na próxima etapa.

8: A App Android : “Designer Tab”

The Android App:

Usaremos o MIT App Inventor para o desenvolvimento de nossa App Android.

Principais componentes da Screen 1 (veja a foto anterior):

  • User Interface:
    • Input of IP Address
      • TextBox named “IP_Address”
    • 5 Command Buttons:
      • forward
      • reverse
      • right
      • left
      • stop
    • Voice Input Button
      • Voice_Input
  • Non Visible Components:
    • Web1
    • SpeachRecognizer1
    • TextToSpeach1
  • Other:
    • Text Box:
      • Speach_To_Text
    • Label:
      • Comm_Status
      • Screenshot_2017-04-02-14-36-34
      • 9: A App Android: Botões

        The Android App: Buttons

      • Na Tab “Blocks”, deveremos criar 5 Botões, um para cada comando. Todos eles seguirão a estrutura dos blocos acima.

        Estes blocos serão chamados quando o botão “forward” (“botão com a seta para cima”) é pressionado.

        Quando você clicar no botão, 3 ações serão executadas:

        1. Um comando será enviado no formato: http: / ip_address * / forward
        2. Um “eco” no mesmo formato é esperado
        3. Uma “mensagem” audível será executada pela App: no caso: “forward”

        * O IP_Address será a que você digitar no seu App. Por exemplo, se o IP address é 10.1.0.3, a mensagem completa seria: http: /10.0.1.3/forward

        Poderá utilizar qualquer mensagem, ou até mesmo deixar a mensagem vazia.

        10: A App Android: Reconhecimento de voz

        The Android App: Voice Recognition

         

      • Os blocos acima mostram o código de reconhecimento de voz para o nosso aplicativo.Note que, para qualquer comando de voz inserido, o resultado será um comando em letras minúsculas. Isso facilitará a descodificação do comando pelo NodeMCU.Por exemplo, se você deseja mover o robô para a frente, uma palavra ou sentença deverá ser enviada para ser interpretada pelo NodeMCU. No exemplo abaixo, o código reconheceria qualquer uma das palavras: “forward”, “frente” ou “a frente “.
 
if (command == "forward" || command == "frente" || command == "a frente")  
{
  forwardMotor();
}
 

Assim, por exemplo quando digo “frente”, a App enviará : http: / 10.0.1.10/frente e o NodeMCU tomará o que é recebido após o “/”,  a palavra “frente” que será interpretada como um comando do tipo “forward”. Com este comando, a função forwardMotor () será invocada.

11: A App Android: Manipulação de erros

The Android App: Error Manipulation

Se ocorrer um erro, por exemplo, quando você diz um comando de voz não reconhecido pelo NodeMCU, o bloco acima irá gravar os detalhes do erro na última linha (Comm_Status) do App, conforme mostrado abaixo:

Screenshot_2017-04-02-14-36-50

12: Teste final

Final Test

Você poderá criar seu aplicativo passo a passo, como mostrado nas etapas anteriores ou fazer o upload do meu projeto completo (.aia) no MIT App Inventor, modificando-o de acordo a suas necessidades. Além disso, caso não tenha experiência no desenvolvimento de aplicativos para Android, poderá executar o arquivo .apk diretamente em seu dispositivo Android.

Ambos, os arquivos .aia e .apk podem ser baixados de meu GitHub:

WiFi_Voice_Robot_Ctrl_V2.aia

WiFi_Voice_Robot_Ctrl_V2.apk

O video abaixo mostra alguns testes de motores utilizando-se do App:

Artigo disponibilizado por MJRobot.org

Todos os produtos utilizados neste artigo podem ser encontrados na Loja de Eletrónica e Robótica – ElectroFun.

Gostaram deste artigo? Deixem o vosso comentário no formulário a baixo e partilhem com os vossos amigos.

Não se esqueçam de fazer like na nossa Página no Facebook.

Podem ainda colocar as vossas dúvidas no nosso Forum da Comunidade Arduino em Portugal ou no nosso Grupo no Facebook Arduino Portugal – Qual o teu projeto?

Comments

Comentários

ArduinoPortugal.pt

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

To use BrandCaptcha you must get an API Key