No post de hoje, nós iremos fazer um carrinho de controle remoto controlado por quatro push buttons!
O projeto consiste em duas partes: o Emissor e o Receptor. Para o emissor, nós iremos utilizar apenas um ESP8266 e quatro push buttons. Para o receptor, nós vamos usar um ESP32, que será conectado a um Arduino UNO para o controle dos motores.
Para fazer a transmissão dos dados sem fio entre os ESPs, nós iremos utilizar o protocolo ESP-NOW, desenvolvido pela Espressif.
No envio dos dados, o ESP8266 se conecta ao ESP32 por meio do endereço MAC do esp32, e envia os dados (Frente, Traz, Esquerda, Direita). Esses dados, quando recebidos pelo ESP32, serão transmitidos para o Arduino UNO por meio do protocolo de Master/Slave via I₂C.
O código que deve ser carregado no ESP8266 é o seguinte:
//inclui as bibliotecas #include <espnow.h> #include <ESP8266WiFi.h> //define em quais portas os botões serão conectados #define botaoesq D5 #define botaobaixo D6 #define botaocima D7 #define botaodir D2 bool esq = 0; bool dir = 0; bool cima = 0; bool baixo = 0; // é necessario mudar o endereço de acordo com o endereço do seu ESP32 uint8_t receiverMacAddress[] = {0xC0,0x49,0xEF,0xE4,0xD8,0xA8}; //C0:49:EF:E4:D8:A8 struct PacketData { byte esq; byte dir; byte cima; byte baixo; }; PacketData data; // callback quando os dados são enviados void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) { Serial.print("Status dos dados enviados: "); if (sendStatus == 0) { Serial.println("Envio ok!"); } else { Serial.println("Falha no envio!"); } } void setup() { Serial.begin(115200); pinMode(botaoesq, INPUT_PULLUP); pinMode(botaodir, INPUT_PULLUP); pinMode(botaocima, INPUT_PULLUP); pinMode(botaobaixo, INPUT_PULLUP); WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != 0) { Serial.println("Erro ao inicializar o ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); esp_now_register_send_cb(OnDataSent); esp_now_add_peer(receiverMacAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0); } void loop() { if (digitalRead(botaoesq) == LOW) // Se o botão for pressionado { esq = 1; //define a variável para verdadeira } else{ //caso contrário esq = 0; //define a variável para falsa } if (digitalRead(botaodir) == LOW) // Se o botão for pressionado { dir = 1; //define a variável para verdadeira } else{ //caso contrário dir = 0; //define a variável para falsa } if (digitalRead(botaocima) == LOW) // Se o botão for pressionado { cima = 1; //define a variável para verdadeira } else{ //caso contrário cima = 0; //define a variável para falsa } if (digitalRead(botaobaixo) == LOW) // Se o botão for pressionado { baixo = 1; //define a variável para verdadeira } else{ //caso contrário baixo = 0; //define a variável para falsa } data.esq = esq; data.dir = dir; data.cima = cima; data.baixo = baixo; Serial.print("esq: "); Serial.println(esq); Serial.print("dir: "); Serial.println(dir); Serial.print("cima: "); Serial.println(cima); Serial.print("baixo: "); Serial.println(baixo); uint8_t result = esp_now_send(receiverMacAddress, (uint8_t *) &data, sizeof(data)); delay(50); }
O código que deve ser carregado no ESP32 é o seguinte:
//inclui as bibliotecas #include <esp_now.h> #include <WiFi.h> #include <Wire.h> const int slaveAdress = 0x08; // endereço da placa UNO na relação master/slave #define SIGNAL_TIMEOUT 10000 unsigned long lastRecvTime = 0; struct PacketData { byte esq; byte dir; byte cima; byte baixo; }; PacketData receiverData; // funçao callback quando os dados sao recebidos void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { if (len == 0) { return; } memcpy(&receiverData, incomingData, sizeof(receiverData)); // envia os dados para o UNO pela comunicação master/slave if(receiverData.cima == 1){ Wire.beginTransmission(slaveAdress); Wire.write("1"); Wire.endTransmission(); } if(receiverData.baixo == 1){ Wire.beginTransmission(slaveAdress); Wire.write("2"); Wire.endTransmission(); } if(receiverData.dir == 1){ Wire.beginTransmission(slaveAdress); Wire.write("3"); Wire.endTransmission(); } if(receiverData.esq == 1){ Wire.beginTransmission(slaveAdress); Wire.write("4"); Wire.endTransmission(); } lastRecvTime = millis(); } void setup() { Wire.begin(); Serial.begin(115200); WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Erro inicializando ESP-NOW"); return; } esp_now_register_recv_cb(OnDataRecv); } void loop() { //Checa a perda de sinal unsigned long now = millis(); if ( now - lastRecvTime > SIGNAL_TIMEOUT ) { Serial.println("sinal perdido"); } }
O código que deve ser carregado no Arduino UNO é o seguinte:
//inclui a biblioteca #include "Wire.h" //define o endereço para o Master/Slave const int myAdress = 0x08; //define onde os pinos da ponte H estão conectados no arduino int pino1 = 4; int pino2 = 5; int pino3 = 6; int pino4 = 7; //variaveis para o controle dos dados recebidos int dados = 0; bool frente = false; bool tras = false; bool esquerda = false; bool direita = false; void setup(){ Serial.begin(9600); Wire.begin(myAdress); //inicia o protocolo master/slave Wire.onReceive(receiveEvent); //define os pinos como saida pinMode(pino1, OUTPUT); pinMode(pino2, OUTPUT); pinMode(pino3, OUTPUT); pinMode(pino4, OUTPUT); } void loop(){ Serial.print("DADOS: "); Serial.println(dados); // condições para o controle do motor de acordo com os dados recebidos dos botões if (dados == 51) { Serial.println("RECEBIDO 1"); direita = true ; // se a placa receber que o botão de cima está pressionado, ele manda o robô ir para frente } if (dados == 49){ Serial.println("RECEBIDO 2"); tras = true; // se a placa receber que o botão de baixo está pressionado, ele manda o robô ir para trás } if (dados == 52){ Serial.println("RECEBIDO 3"); esquerda = true; // se a placa receber que o botão da direita está pressionado, ele manda o robô ir para direita } if(dados == 50){ Serial.println("RECEBIDO 4"); frente = true ; // se a placa receber que o botão da esquerda está pressionado, ele manda o robô ir para esquerda } if(tras == true){ vaitras(); tras = !tras; dados = 0; } else if(frente == true){ vaifrente(); frente = !frente ; dados = 0; } else if(esquerda == true){ vaiesquerda(); esquerda = !esquerda ; dados = 0; } else if(direita == true){ vaidireita(); direita = !direita; dados = 0; } } void receiveEvent(int howMany) { // verifica se existem dados para serem lidos no barramento I2C if (Wire.available()) { char received = Wire.read(); Serial.println(received); dados = received; } int dados = Wire.read(); } void vaifrente(){ //responsável por mandar o robo para frente digitalWrite(pino1, HIGH); digitalWrite(pino2, LOW); digitalWrite(pino3, HIGH); digitalWrite(pino4, LOW); delay(200); digitalWrite(pino1, HIGH); digitalWrite(pino2, HIGH); digitalWrite(pino3, HIGH); digitalWrite(pino4, HIGH); } void vaitras(){ //responsável por mandar o robo para trás digitalWrite(pino1, LOW); digitalWrite(pino2, HIGH); digitalWrite(pino3, LOW); digitalWrite(pino4, HIGH); delay(200); digitalWrite(pino1, HIGH); digitalWrite(pino2, HIGH); digitalWrite(pino3, HIGH); digitalWrite(pino4, HIGH); } void vaidireita(){ //responsável por mandar o robo para esquerda digitalWrite(pino3, LOW); digitalWrite(pino4, LOW); digitalWrite(pino1, LOW); digitalWrite(pino2, HIGH); delay(200); digitalWrite(pino1, HIGH); digitalWrite(pino2, HIGH); digitalWrite(pino3, HIGH); digitalWrite(pino4, HIGH); } void vaiesquerda(){ //responsável por mandar o robo para direita digitalWrite(pino3, LOW); digitalWrite(pino4, HIGH); digitalWrite(pino1, HIGH); digitalWrite(pino2, HIGH); delay(200); digitalWrite(pino1, HIGH); digitalWrite(pino2, HIGH); digitalWrite(pino3, HIGH); digitalWrite(pino4, HIGH); }
Caso queira entender mais sobre o protocolo ESP-NOW, acesse o post abaixo:
https://blog.eletrogate.com/esp-now-comunicacao-sem-fio-entre-esp32s/
É necessário mudar o endereço Mac no código do emissor de acordo com o endereço MAC do seu esp32.
No meu caso, o endereço MAC do meu ESP32 é C0:49:EF:E4:D8:A8
Para descobrir o seu endereço MAC, basta carregar o seguinte código no seu esp32:
/****************************************************************************** ESP-NOW: Comunicação entre ESP32s Sketch Obtendo endereço MAC do ESP32 Criado em 08 de Dezembro de 2022 por Michel Galvão Eletrogate - Loja de Arduino \\ Robótica \\ Automação \\ Apostilas \\ Kits https://www.eletrogate.com/ ******************************************************************************/ // Inclusão das bibliotecas #include <WiFi.h> void setup() { Serial.begin(115200); // configurada a taxa de transferência em 115200 bits por segundo para a transmissão serial WiFi.mode(WIFI_MODE_STA); // configura o WIFi para o Modo de estação WiFi Serial.print("Endereço MAC: "); Serial.println(WiFi.macAddress()); // retorna o endereço MAC do dispositivo while(1); // loop infinito } void loop() {}
Esse código foi feito pelo Michel Galvão lá no post sobre ESP-NOW.
Diagrama do Emissor:
Diagrama do Receptor:
*É necessário remover o jumper da alimentação do circuito lógico da ponte H
Caso tenha interesse em mudar a alimentação do seu projeto da forma adequada, acesse o post abaixo:
|
A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.
Tenha a Metodologia Eletrogate dentro da sua Escola! Conheça nosso Programa de Robótica nas Escolas!