Em meu último tutorial: Controle ativado por voz com Android e NodeMCU, exploramos como desenvolver nossa própria App em um smartphone Android para controlar localmente (usando botões ou voz) dispositivos domésticos inteligentes. Que tal agora, em vez de dispositivos domésticos controlarmos motores? E melhor ainda, que tal ter esses motores movendo um robô? Pois isso, é exatamente o que desenvolveremos aqui, um robô controlado por voz via WiFi e utilizando como microcontrolador nosso velho amigo, o NodeMCU!
O diagrama de blocos abaixo nos dá uma geral sobre o projeto que desenvolveremos aqui:
e o filme nos mostra 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)
Valores em USD, apenas para referência.
- NodeMCU ESP8266-12E ($8.79)
- 400-point Experiment Breadboard Breadboard ($ 4.97)
- H-Bridge L293D ($2.17)
- Motor Robot Car Chassis Kit ($13.00)
- Male-Female Dupont Cables ($1.00)
- Portable Charger 5VDC 3000mAh Power Bank ($10.00)
- Bateria 9V DC
….. e qualquer telefone ou tablet Android!
2: A Ponte-H 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 robô terá duas rodas, acionadas por 2 motores DC:
- Motor esquerdo (LEFT)
- Motor direito (RIGHT)
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 -)
Devido à maneira como meus motores são montados, a combinação acima irá girar ambos motores no mesmo sentido, “empurrando” o robô para a frente.
O diagrama acima define (ou melhor, convenciona) como o robô 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 robô só funcionaia se os pinos de habilitação (eneLeftMotor e eneRightMotor) estiverem ambos em HIGH. Você poderá conectar esses pinos do L293D (1 e 9) diretamente a + VCC e esquecê-los. Eu não gosto disso, porque se voce necessita por exemplo, parar rapidamente seu robô, 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 robô 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 robô em outras direções
- STOP: Pare
- LEFT: Vire à esquerda
- RIGHT: Vire à direita
- REVERSE: Dê marcha à ré
- 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 robô tomar outra direção, digamos que “virar à ESQUERDA”. Considere que o robô está indo para a frente, se queremos virar à esquerda podemos pensar em duas situações:
- Parar o motor ESQUERDO, mantendo o motor DIREITO no sentido a frente (Forward): o robô executará uma trajetória de arco para a esquerda
- Inverter o sentido do motor ESQUERDO, mantendo o motor DIREITO no sentido a frente (Forward): o robô 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:
4: Completando o HW
Siga o diagrama acima e complete o HW de seu Robô.
Você poderá executar alguns testes simples para verificar que seu código está OK. Para isto, introduziremos um “botão” para iniciar o seu robô. 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 de seu robô:
// 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 robô 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 de meu GitHub:
5: Montando o corpo do robô
- Use o Kit: Chassis, 2 Rodas, 2 Motores DC, 1 roda solta (coaster)
- Solde 2 fios de 10 cm (Vermelho e Preto) em cada polo do motor
- Fixe os motores ao chassi como mostrado na foto acima
- Monte o coaster
- Conecte os fios do motor à eletrônica (L293D)
- Fixe a bateria de 9V ao chassi
- Fixe a bateria de 5V sob o chassi
O robô deverá ficar com essa cara:
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.
Tome nota deste endereço de IP. Precisaremos dele para conectar o App Android.
O código acima poderá ser baixado de meu GitHub:
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 robô 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:
- STOP: Pare
- LEFT: Vire à esquerda
- RIGHT: Vire à direita
- REVERSE: Dê marcha à ré
- FORWARD: Vá para a frente
Baixe o código completo: WiFi_Robot_NodeMCU_Android_Voice_EXT de meu 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”
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
- Input of IP Address
- Non Visible Components:
- Web1
- SpeachRecognizer1
- TextToSpeach1
- Other:
- Text Box:
- Speach_To_Text
- Label:
- Comm_Status
- Text Box:
9: A App Android: Botões
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:
- Um comando será enviado no formato: http: / ip_address * / forward
- Um “eco” no mesmo formato é esperado
- 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
Você poderá utilizar qualquer mensagem, ou até mesmo deixar a mensagem vazia.
10: A App Android: Reconhecimento de voz
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
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:
12: Teste final
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 você 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:
O video abaixo mostra alguns testes de motores utilizando-se do App:
Conclusão
Como sempre, espero que este projecto possa ajudar outros a encontrarem o seu caminho no emocionante mundo da electrónica, robótica e do IoT!
Verifique o depositário no GitHub para obter os arquivos atualizados:
Saludos desde el sur del mundo!
Até o próximo tutorial!
Obrigado
Marcelo
Ola amigo saudaçoes muito obrigado por compartilhar seu projeto,eu nao estou conseguindo fazer com que o comando de voz funcione voce poderia me ajudar?não sei se ão as biblhotecas wi fi ou se seria algo com o dispositivo celular ja tentei de varias formas e sem sucesso,como em outros casos eu entendo que ele realmente era pra soletrar em minusculo exatamente como no seu cod e isso esta acontecendo mas nao consigo um retorno do esp ja os botoes funcionando perfeitamente
CurtirCurtir
preciso da sua ajuda , tenho tudo como o circuito eletrico apresenta .
e depois quando meto o ip na aplicaçao e tento virar o robo dá o erro de url errado …
preciso de estar , ligado aao modulo no wifi ? enquanto o estiver a executar.?
CurtirCurtir
Actually, I Have Been trying to modify the wi-fi voice controlled robot. I am trying to send sensor data read by nodemcu app back to the MIT inventor created in app. Can you please help me in that?
CurtirCurtir
not working please help in this erorr
CurtirCurtir