<
*

Ivanov

  • Allahu Akbar
  • *****
  • 72
  • 2
  • Zhokhov
    • Ver perfil
Robot controlado por voz via WiFi
« Online: Dezembro 08, 2017, 09:27:10 am »
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: