Nosso projeto de Robô IoT com ESP8266 NodeMCU vai juntar os tópicos que foram vistos nos posts NodeMCU com MQTT e Como controlar motor dc com ESP8266 NodeMCU. O NodeMCU é uma placa / plataforma muito boa para prototipação rápida de soluções IoT.
Junto com o MQTT, vamos construir um robô totalmente controlado pela Internet à partir de um navegador web comum!
Descrição do projeto Robo IoT com ESP8266 NodeMCU
O projeto deste post consiste em um robô equipado com um módulo ESP8266 NodeMCU, controlado via Internet por MQTT. Tal robô utilizará duas rodas para locomoção, sendo capaz de se movimentar em três direções: para frente, para a esquerda e para a direita.
Utilizar MQTT para este controle permitirá:
- Controle do robô IoT com ESP8266 NodeMCU a partir de uma página web
- Controle do robô de qualquer lugar do planeta que possua conexão com a Internet
- Possibilidade de controlar o robô a partir de qualquer dispositivo conectado à Internet(exemplo: smartphones, tablets e computadores), com qualquer sistema operacional.
O diagrama de como o robô IoT com ESP8266 NodeMCU será controlado pode ser visto na figura abaixo:
Na comunicação MQTT para controle do robô, o payload da mensagem informará qual ação o robô deve tomar. As ações possíveis podem ser visualizadas na tabela abaixo:
A forma de execução de um comando / ação é a seguinte: o robô vai executar indefinidamente o último comando recebido até que seja recebido um novo comando válido.
Material utilizado no projeto Robô IoT com ESP8266 NodeMCU
Para construir este robô, será necessário o seguinte material:
- Um chassis de duas rodas (Kit Chassi 2WD)
- Protoboard de 400 pontos
- Quatro pilhas 1,5V do tipo AA ou AAA. É altamente recomendável o uso de pilhas recarregáveis.
- Um módulo ESP8266 NodeMCU
- Um módulo relé 5V de 2 canais
- Kit de jumpers macho-macho
- Um regulador de tensão 7805
- Dois transistores BC548 (ou equivalente NPN, como o BC337, por exemplo)
Esquema elétrico do Robô IoT com ESP8266 NodeMCU
Na figura abaixo está o esquema elétrico do Robô IoT:
Programação do ESP8266 NodeMCU
Abaixo, segue o código-fonte completo do projeto.
Importante: leia atentamente os comentários do código!
#include <ESP8266WiFi.h> // Importa a Biblioteca ESP8266WiFi #include <PubSubClient.h> // Importa a Biblioteca PubSubClient //defines: //defines de id mqtt e tópicos para publicação e subscribe #define TOPICO_SUBSCRIBE "MQTTRoboIoTMakerHeroEnvia" //tópico MQTT de escuta #define TOPICO_PUBLISH "MQTTRoboIoTMakerHeroRecebe" //tópico MQTT de envio de informações para Broker #define ID_MQTT "RoboIotMakerHero01" //id mqtt (para identificação de sessão) //IMPORTANTE: este deve ser único no broker (ou seja, // se um client MQTT tentar entrar com o mesmo // id de outro já conectado ao broker, o broker // irá fechar a conexão de um deles). //defines - mapeamento de pinos do NodeMCU #define D0 16 #define D1 5 #define D2 4 #define D3 0 #define D4 2 #define D5 14 #define D6 12 #define D7 13 #define D8 15 #define D9 3 #define D10 1 //defines - motores #define MOTOR_DIRETO D0 #define MOTOR_ESQUERDO D1 // WIFI const char* SSID = " "; //Coloque aqui o SSID / nome da rede WI-FI que deseja se conectar const char* PASSWORD = " "; //Coloque aqui a senha da rede WI-FI que deseja se conectar // MQTT const char* BROKER_MQTT = "iot.eclipse.org"; //URL do broker MQTT que se deseja utilizar int BROKER_PORT = 1883; // Porta do Broker MQTT //Variáveis e objetos globais WiFiClient espClient; // Cria o objeto espClient PubSubClient MQTT(espClient); // Instancia o Cliente MQTT passando o objeto espClient char EstadoMotorDireto = '0'; //variável que armazena o estado atual do motor da direita char EstadoMotorEsquerdo = '0'; //variável que armazena o estado atual do motor da esquerda //Prototypes void initSerial(); void initWiFi(); void initMQTT(); void reconectWiFi(); void mqtt_callback(char* topic, byte* payload, unsigned int length); void VerificaConexoesWiFIEMQTT(void); void InitOutputs(void); /* * Implementações das funções */ void setup() { //inicializações: InitOutputs(); initSerial(); initWiFi(); initMQTT(); } //Função: inicializa comunicação serial com baudrate 115200 (para fins de monitorar no terminal serial // o que está acontecendo. //Parâmetros: nenhum //Retorno: nenhum void initSerial() { Serial.begin(115200); } //Função: inicializa e conecta-se na rede WI-FI desejada //Parâmetros: nenhum //Retorno: nenhum void initWiFi() { delay(10); Serial.println("------Conexao WI-FI- Robo IoT com NodeMCU -----"); Serial.print("Conectando-se na rede: "); Serial.println(SSID); Serial.println("Aguarde"); reconectWiFi(); } //Função: inicializa parâmetros de conexão MQTT(endereço do // broker, porta e seta função de callback) //Parâmetros: nenhum //Retorno: nenhum void initMQTT() { MQTT.setServer(BROKER_MQTT, BROKER_PORT); //informa qual broker e porta deve ser conectado MQTT.setCallback(mqtt_callback); //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega) } //Função: função de callback // esta função é chamada toda vez que uma informação de // um dos tópicos subescritos chega) //Parâmetros: nenhum //Retorno: nenhum void mqtt_callback(char* topic, byte* payload, unsigned int length) { String msg; //obtem a string do payload recebido for(int i = 0; i < length; i++) { char c = (char)payload[i]; msg += c; } //toma ação dependendo da string recebida: //----------------------------------------------------- // Mensagem recebida | Ação tomada //----------------------------------------------------- // F | O robô vai para frente // D | O robô vai para a direita // E | O robô vai para a esquera // P | O robô para imediatamente if (msg.equals("F")) { //para ir para frente, os dois motores são ligados digitalWrite(MOTOR_DIRETO, HIGH); digitalWrite(MOTOR_ESQUERDO, HIGH); EstadoMotorDireto = '1'; EstadoMotorEsquerdo = '1'; } if (msg.equals("D")) { //para ir para a direita, somente o motor da esquerda é ligado digitalWrite(MOTOR_DIRETO, LOW); digitalWrite(MOTOR_ESQUERDO, HIGH); EstadoMotorDireto = '0'; EstadoMotorEsquerdo = '1'; } if (msg.equals("E")) { //para ir para a esquerda, somente o motor da direita é ligado digitalWrite(MOTOR_DIRETO, HIGH); digitalWrite(MOTOR_ESQUERDO, LOW); EstadoMotorDireto = '1'; EstadoMotorEsquerdo = '0'; } if (msg.equals("P")) { //para parar, os dois motores são desligados digitalWrite(MOTOR_DIRETO, LOW); digitalWrite(MOTOR_ESQUERDO, LOW); EstadoMotorDireto = '0'; EstadoMotorEsquerdo = '0'; } } //Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) // em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. //Parâmetros: nenhum //Retorno: nenhum void reconnectMQTT() { while (!MQTT.connected()) { Serial.print("* Tentando se conectar ao Broker MQTT: "); Serial.println(BROKER_MQTT); if (MQTT.connect(ID_MQTT)) { Serial.println("Conectado com sucesso ao broker MQTT!"); MQTT.subscribe(TOPICO_SUBSCRIBE); } else { Serial.println("Falha ao reconectar no broker."); Serial.println("Havera nova tentatica de conexao em 2s"); delay(2000); } } } //Função: reconecta-se ao WiFi //Parâmetros: nenhum //Retorno: nenhum void reconectWiFi() { //se já está conectado a rede WI-FI, nada é feito. //Caso contrário, são efetuadas tentativas de conexão if (WiFi.status() == WL_CONNECTED) return; WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print("."); } Serial.println(); Serial.print("Conectado com sucesso na rede "); Serial.print(SSID); Serial.println("IP obtido: "); Serial.println(WiFi.localIP()); } //Função: verifica o estado das conexões WiFI e ao broker MQTT. // Em caso de desconexão (qualquer uma das duas), a conexão // é refeita. //Parâmetros: nenhum //Retorno: nenhum void VerificaConexoesWiFIEMQTT(void) { if (!MQTT.connected()) reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita reconectWiFi(); //se não há conexão com o WiFI, a conexão é refeita } //Função: envia ao Broker o estado atual do output //Parâmetros: nenhum //Retorno: nenhum void EnviaEstadoOutputMQTT(void) { char EstadosMotores[3]; EstadosMotores[0] = EstadoMotorDireto; EstadosMotores[1] = '-'; EstadosMotores[2] = EstadoMotorEsquerdo; MQTT.publish(TOPICO_PUBLISH, EstadosMotores); Serial.println("- Estados dos motores enviados ao broker!"); delay(1000); } //Função: inicializa os outputs em nível lógico baixo (desliga os dois motores) //Parâmetros: nenhum //Retorno: nenhum void InitOutputs(void) { pinMode(MOTOR_DIRETO, OUTPUT); pinMode(MOTOR_ESQUERDO, OUTPUT); digitalWrite(MOTOR_DIRETO, LOW); digitalWrite(MOTOR_ESQUERDO, LOW); } //programa principal void loop() { //garante funcionamento das conexões WiFi e ao broker MQTT VerificaConexoesWiFIEMQTT(); //envia o status de todos os outputs para o Broker no protocolo esperado EnviaEstadoOutputMQTT(); //keep-alive da comunicação com broker MQTT MQTT.loop(); }
Interface web
Para controlar o robô IoT com ESP8266 NodeMCU por MQTT, foi desenvolvida uma interface web. Você pode baixá-la clicando aqui.
Assim como foi feito no artigo sobre MQTT no NodeMCU, você pode hospedar essa interface em QUALQUER servidor web ou mesmo rodar no seu próprio computador / rodar localmente (desde que o computador possua conexão com Internet, claro)! Esta interface web é basicamente um websocket que se comunica diretamente com o broker, por isso pode estar rodando em qualquer lugar com disponibilidade de Internet que funciona.
Observe a figura abaixo:
Monte também o seu robô IoT e boa diversão!
Gostou? Deixe seu comentário logo abaixo.
Tem algum tutorial como configurar MQTT em um pc local? ja estou com o carrinho todo montado porém estou com dificuldades no servidor MQTT, pode me ajudar?
Olá Lázaro.
Veja o conteúdo que temos no blog a respeito de MQTT: https://www.makerhero.com/?s=mqtt&post_type=post
Att.
Vitor Mattos.
MakerHero.
Olá eu estou tentando montar esse projeto e ao tentar conectar o broker com a interface web, aparece esse erro: ‘WebSocket connection to ‘ws://mqtt.eclipseprojects.io/ws’ failed: mosquitto.js:90′ e não consigo resolver, alguém sabe?
Olá.
Verifique a liberação de portas da sua rede e tente utilizar outra porta.
Att.
Vitor Mattos.
Suporte Técnico MaherHero.
Salve, estou interessado em fazer esse projeto, mas fiquei com uma dúvida sobre o funcionamento, existem um delay do comando para o carrinho tomar ação?
Olá Kayque,
Sim, haverá um delay, que depende da conexão de internet do dispositivo que irá controlar até o servidor, e depois do servidor até o carrinho.
Em geral o atraso é na casa de 200 ms, mas pode variar de acordo com a conexão.
Abraços!
Vinícius – Equipe MakerHero
olha no esquema elétrico do Robô mostra algumas resistência, minha duvida e ten que usar resistores quais eu devo usar
Olá,
Os resistores são de 2,2 kOhms (três faixas vermelhas) e 220 ohms (duas faixas vermelhas e uma marrom).
Abraços!
Vinícius – Equipe MakerHero
2,2 kOhms cara eu não acho para compra esse restor por acaso tem alguma alternativa
Olá!
Nós temos ele aqui: https://www.makerhero.com/produto/resistor-22k%cf%89-1-4w/
Abraços!
Vinícius – Equipe MakerHero
Boa noite, a alimentação com 4 pilhas de 1,5v não corre o risco de danificar a olaca? Já que ela suporta uma alimentação de 5 à 3,3v?
Matheus,
Como estamos utilizando um NodeMCU, essa placa vai até 9V para alimentação, então está tranquilo 😉
Abraços, e cuide-se com o COVID-19!
Diogo – Equipe MakerHero
Boa tarde.. Muito bom esse projeto..
Gostaria de saber se tem o código para os movimento para colocar no Android Studio?
Francisco, obrigado.
Respondendo sua pergunta, não temos um código de um app (nem nada do tipo) para colocar no Android Studio.
Boa tarde, posso utilizar o esp8266 – esp-01 para fazer a comunicação entre o robo e a Internet?
Fernando, boa tarde.
Em teoria, sim. Porém não seria possível aproveitar 100% do código deste projeto (ele precisaria ser adaptado para o ESP-01). Além disso, a forma de programar o ESP-01 pela Arduino IDE é diferente e exige uma circuitaria extra.
Atenciosamente,
Pedro Bertoleti
pedro boa tarde” como eu consigo o controle desta placa com o celular.
Claudio, nao entendi sua pergunta. Poderia reformula-la por favor?
Olá Pedro e Claudio!
Talvez o Claudio esteja procurando por isso:
https://www.makerhero.com/blog/robo-com-nodemcu-controlado-via-celular/
Abraços!
André – Equipe MakerHero
Poderia ter o kit inteiro para vender na loja, tentei comprar agora um a um mas está em falta o nodemcu, seria minha primeira experiência com microcontroladores
Boa tarde Pedro,
Sobre a aplicação web, como eu posso passar usuário, senha e ssl usando seu exemplo de aplicação web para autenticar em um broker privado?
Bom dia!
Fiz as conexões do esp8266 e abri a interface web nos navegadores (Chrome e Explorer), mas apesar de dar o comando via interface ou clicando na letras indicadas o robô não está recebendo o comando.
Obs. Aparece interface “Esse site diz…”0-0 quando clico parar, 1-1 quando clico frente.
E gostaria de saber se poderia utilizar o “D1 Arduino compatible Based Esp8266” utilizando a mesma programação.
Obrigado
Iago, boa noite.
Não aparece os simbolos de duas rodas (representando roda esquerda e roda direita) quando o comando é recebido? Você testou no seu computador ou em algum dispositivo móvel (tablet ou smartphone, por exemplo)?
Faço estas perguntas para entender melhor o seu cenário e te ajudar a resolver.
Atenciosamente,
Pedro Bertoleti
Bom dia Pedro!
Os 2 símbolos aparecem, mas os comandos só estão aparecendo na própria interface como avia tido 1-0 (Esquerda), 0-1(Direita) , 1-1(Frente) e 0-0 (Parado) lembrando que o robô fica parado independente do comando.
Testei no meu computador e também no smartphone (não apareceu esses comandos 1-1).
E gostaria de saber se eu poderia utilizar o “D1 Arduino compatible Based Esp8266″ utilizando a mesma programação e o mesmo circuito.
Att:
Iago Bacelar
Iago, quanto a usar o “D1 Arduino compatible Based Esp8266″ eu não sei, pois nunca utilizei este.
Quanto ao robo, você modificou os nomes dos tópicos de envio e recepção, certo? Os nomes dos tópicos no NodeMCU estão iguais aos da interface?
Boa Tarde Pedro
Eu mantive o mesmo nome que está na programa fornecida pelo MakerHero, conferi os tópicos de envio e recepção, verifiquei a tensão de entrada do relé, e também a minha alimentação.
E mesmo assim não consigo dar comando fica interface web.
Obs. No meu wifi aparece o ESP conectado.
Att
Iago Bacelar
Vc usou esse programa na IDE do arduino?
Sim.
Boa noite, topei fazer esse projeto . Achei bem interessante, agradeço por terem disponibilizado. Gostaria de saber quais os resistores (intensidades) deverão ser utilizadas !
Joel, boa tarde.
Muito obrigado por curtir o projeto e querer dar vida ao mesmo também!
Quanto aos resistores, estes são de valores 2k2 e 220 ohms.
Atenciosamente,
Pedro Bertoleti
E no caso, eles iriam em que entrada/saída , cada um ?
Joel, observe o circuito esquemático contido neste artigo. Lá você obtém esta informação.
Olá, Pedro!
Observando o código do projeto, creio que houve uma pequena inversão na definição dos tópicos para publicação e subscribe. Nas linhas 6 e 7, está assim:
#define TOPICO_SUBSCRIBE “MQTTRoboIoTMakerHeroEnvia” //tópico MQTT de escuta
#define TOPICO_PUBLISH “MQTTRoboIoTMakerHeroRecebe” //tópico MQTT de envio de informações para Broker
Pergunto eu: não seria o contrário?
#define TOPICO_SUBSCRIBE “Recebe” //tópico MQTT de escuta
#define TOPICO_PUBLISH “Envia” //tópico MQTT de envio de informações para Broker
Ou seja, “Recebe” para o SUBSCRIBE e “Envia” para o PUBLISH ?
Sei que o que está entre aspas pode ser alterado na interface web (vc até recomenda isso), mas a lógica não seria essa?
Parabéns pelo seu trabalho na MakerHero! Estou começando com um Arduino (comprei um Mega2560 exatamente hoje) e gosto muito dos seus posts aqui no Blog.
Atenciosamente,
Pedro
Pedro, boa noite.
Primeiramente, muito obrigado pela leitura e pelos elogios! Fico feliz que você curtiu o projeto!
No caso dos tópicos, a “referência” de nome dos mesmos é a interface web (ou seja, quando a interface web envia algo, o nodemcu deve escutar e vice-versa). Por isso, no programa do NodeMCU, já esta impressão de que as coisas estão ao contrário.
Ficou claro? Se não ficou, me avisa que explico de outra forma.
Atenciosamente,
Pedro Bertoleti
Olá, comprei o esp8266 e fiz a conexão conforme o post e ocorreu tudo bem, só que na interface aparece somente a roda esquerda e centralizada. Não passei o pente fino no código ainda, mas fica o comentário construtivo e se rodar certinho com vocês me avisa.
Parabéns pelo material e pela entrega também que foi muito rápida.
Paulo, boa tarde.
Muito obrigado pelo elogio, pela leitura e desculpe pela demora. Eu verifiquei novamente aqui e a interface rodou sem problemas.
Para melhor entender o problema, por favor responda:
1) Qual navegador utilizou?
2) Abriu no celular ou computador?
Atenciosamente,
Pedro Bertoleti
Após executar no navegador (Safari ou Chrome) em ambos não aparecem as 2 rodas realmente!
Parabéns Pedro pelo post. Vc sabe se dá para colocar mais um sensor de distância e dois leds neste robô? Ou seja, qtos GPIOs tem disponíveis ainda neste robô?
Grato,
Augusto
Augusto, boa tarde.
Obrigado pela leitura e pelo elogio. Quanto às suas perguntas:
– Dois LEDs com certeza é possível colocar
– O sensor de distância eu nunca utilizei com o NodeMCU. Sendo assim, infelizmente não sei te dizer se funcionaria 100%.
– Ainda há 9 GPIOs disponíveis. Ou seja, dá pra acrescentar algumas funcionalidades neste robô sem problemas.
Atenciosamente,
Pedro Bertoleti
Boa noite!
Gostaria de saber qual é o comando para utilizar o Motor de vibração no arduino uno? (comando para fazer ele vibrar)
esse motor = https://www.makerhero.com/pd-361d89-motor-de-vibracao-1027.html?ct=&p=1&s=1
Obrigado
Boa tarde Guilherme,
Esse motor não tem comando, você aplica tensão nos terminais e ele começa a vibrar. No Arduino, você pode controlar a vibração ligando e desligando uma porta digital, por exemplo.
Abraço!
Adilson – Equipe MakerHero
Ótima série de posts Pedro, vai agregar bastante a comunidade!
Filipe, muito obrigado!
Fico feliz que gostou do post! Pra mim é uma satisfação poder ajudar a comunidade!
Atenciosamente,
Pedro Bertoleti