Construa um Robô Arduino com Rodas Mecanum: Mobilidade 360° - Guia DIY
Neste tutorial, vamos aprender a construir um Robô Arduino com Rodas Mecanum capaz de se mover em qualquer direção. Esta mobilidade única do robô é alcançada usando um tipo especial de rodas, chamadas Rodas Mecanum.
Você pode assistir ao vídeo a seguir ou ler o tutorial escrito abaixo.
Visão Geral
Na verdade, projetei e imprimi estas rodas em 3D porque elas podem ser um pouco caras para comprar. Elas funcionam muito bem e devo dizer que pilotar esta plataforma robótica é muito divertido. Podemos controlar o robô sem fio usando os módulos transceptores de rádio NRF24L01, ou no meu caso, estou usando meu Transmissor RC DIY que fiz em um dos meus vídeos anteriores.

Também tornei possível controlá-lo usando um smartphone via comunicação Bluetooth. Fiz um aplicativo Android personalizado através do qual podemos controlar o robô com rodas Mecanum para se mover em qualquer direção. Além disso, usando o slider no aplicativo, podemos controlar a velocidade de movimento.

O cérebro desta plataforma robótica é uma placa Arduino Mega que controla cada roda individualmente. Cada roda é acoplada a um motor de passo NEMA 17, e sabendo que motores de passo podem ser controlados com precisão, adicionei mais um recurso legal no aplicativo através do qual podemos programar o robô para se mover automaticamente. Usando o botão Salvar, podemos salvar cada posição ou passo e então o robô pode executar e repetir estes passos automaticamente. Com o mesmo botão, também podemos pausar a operação automática, bem como reiniciar ou apagar todos os passos para que possamos armazenar novos.
Modelo 3D do Robô com Rodas Mecanum
Para começar, projetei este robô com rodas Mecanum usando um software de modelagem 3D. A plataforma base deste robô é uma caixa simples que farei com placas MDF de 8mm de espessura.

Os quatro motores de passo são fixados a esta plataforma e as rodas Mecanum são fixadas aos eixos dos motores.
Você pode encontrar e baixar este modelo 3D, bem como explorá-lo no seu navegador no Thangs.

Baixe o modelo 3D de montagem do Thangs.
Arquivos STL para impressão 3D:
Como Funcionam as Rodas Mecanum
Uma roda Mecanum é uma roda com rolos fixados à sua circunferência. Estes rolos são posicionados diagonalmente ou em ângulo de 45 graus em relação ao eixo de rotação da roda. Isso faz com que a roda exerça força na direção diagonal ao mover para frente ou para trás.

Então, girando as rodas em certos padrões, utilizamos essas forças diagonais e assim o robô pode se mover em qualquer direção.
Também devemos notar aqui que precisamos de dois tipos de rodas Mecanum, frequentemente referidas como rodas Mecanum canhota e destra. A diferença entre elas é a orientação dos rolos e elas devem ser instaladas no robô em locais específicos. O eixo de rotação do rolo superior de cada roda deve apontar para o centro do robô.

Aqui está uma demonstração rápida de como o robô se move dependendo da direção de rotação das rodas.
Se todas as quatro rodas se moverem para frente, o movimento resultante do robô será para frente, e vice-versa, se todas as rodas se moverem para trás, o robô se moverá para trás. Para mover para a direita, as rodas direitas precisam girar para dentro do robô, enquanto as rodas esquerdas precisam girar para fora do robô. A força resultante devido aos rolos posicionados diagonalmente fará o robô mover para a direita. O mesmo, mas oposto, acontece ao mover para a esquerda. Com estas rodas, também podemos alcançar movimento em direção diagonal girando apenas duas rodas.
Fazendo o Robô com Rodas Mecanum
No entanto, agora deixe-me mostrar como construí esta plataforma robótica. Como mencionei, para fazer a base da plataforma estou usando placas MDF de 8mm de espessura. Usando uma serra de mesa, primeiro cortei todas as peças de acordo com as dimensões do modelo 3D.

Em seguida, usando uma broca de 3mm e uma broca Forstner de 25mm, fiz as aberturas nos painéis laterais para fixar os motores de passo. Uma vez que tive as peças prontas, continuei montando-as. Usei cola de madeira e alguns parafusos para fixá-las. A coisa mais importante aqui é ter as aberturas para os motores feitas com precisão para que todas as rodas tenham contato uniforme com a superfície posteriormente.

Claro, você também poderia imprimir esta plataforma base em 3D, em vez de fazê-la com MDF, então incluirei um arquivo 3D dela no artigo do site. Finalmente, pintei a base e sua tampa com tinta spray branca.

Em seguida, estão as rodas Mecanum. Como disse antes, estas rodas podem ser um pouco caras para comprar, então foi por isso que decidi projetar e imprimir as minhas próprias. As rodas são feitas de duas partes, lado externo e interno, que são fixadas juntas com alguns parafusos e porcas M4. Elas têm 10 rolos cada, e um acoplador de eixo especificamente projetado para se encaixar em um motor de passo NEMA 17.


Imprimi todas as peças para as rodas Mecanum usando minha impressora 3D Creality CR-10.
Aqui está um link para esta impressora 3D caso você queira conferir.

Então, uma vez que tive as peças impressas em 3D prontas, prossegui com a fabricação dos eixos para os rolos. Para esse propósito, usei arame de aço de 3mm de espessura. O comprimento dos eixos precisa ser de cerca de 40mm, então, usando uma ferramenta rotativa, cortei o arame nesse comprimento.

Comecei a montar a roda Mecanum fixando os dois lados e o acoplador de eixo usando quatro parafusos e porcas M4. O comprimento dos parafusos precisa ser de 45mm.

Para instalar os rolos, primeiro precisamos inserir levemente o eixo através dos furos localizados na circunferência do lado interno.

Então podemos inserir uma pequena arruela M3, inserir o rolo e empurrar o eixo todo o caminho para dentro do slot do lado externo da roda. Usei uma única arruela porque não tinha espaço suficiente para inserir uma segunda arruela no outro lado.

Repeti este processo para todos os 10 rolos. Na verdade, é fácil e meio divertido montar estas rodas. O importante aqui é que os rolos precisam ser capazes de se mover livremente.

No final, usei algumas gotas de cola cianoacrilato em cada um dos furos internos para garantir que os eixos não fiquem soltos.

Ok, então uma vez que as rodas estão prontas, agora podemos prosseguir com a montagem do robô inteiro. Primeiro, precisamos fixar os motores de passo à plataforma base. Para fixá-los no lugar, usei parafusos M3 com comprimento de 12mm.

Em seguida, precisamos fixar as rodas aos eixos dos motores. O acoplador de eixo que fiz tem um slot para inserir uma porca M3, através da qual um parafuso M3 pode passar e assim podemos fixar a roda ao eixo.

Em seguida, para fixar a tampa superior à base, fixei hastes roscadas em dois cantos da base. Fiz furos nas mesmas posições na tampa e assim pude inserir e fixar facilmente a tampa na base.

No lado de trás da base, fiz um furo de 20mm para fixar um interruptor de alimentação mais tarde, bem como um furo de 5mm para fixar um LED.
Diagrama de Circuito
Agora podemos prosseguir com a eletrônica. Aqui está o diagrama de circuito completo deste projeto.

Então, controlaremos os quatro motores de passo NEMA 17 usando quatro drivers de passo DRV8825, ou também poderíamos usar os drivers de passo A4988. Para alimentar os steppers e todo o robô, usaremos uma fonte de alimentação de 12V, e no meu caso, usarei uma bateria Li-Po 3S que fornece cerca de 12V. Para a comunicação de rádio, estamos usando o módulo NRF24L01, e para a comunicação Bluetooth, estamos usando o módulo Bluetooth HC-05. Também incluí um divisor de tensão simples que será usado para monitorar a tensão da bateria e uma conexão de LED para indicar quando a tensão da bateria cair abaixo de 11V.
Também incluí um regulador de tensão dedicado de 5V que pode fornecer cerca de 3A de corrente. Isso é opcional, mas estou planejando em um vídeo futuro combinar este projeto com meu projeto de Braço Robótico Arduino, e para esse propósito precisaria de 5V para acionar seus motores servo.
Você pode obter os componentes necessários para este projeto nos links abaixo:
- Motor de Passo – NEMA 17………………
- Driver de Passo DRV8825…………………
- Módulo Transceptor NRF24L01…….…
- Módulo Bluetooth HC-05 …………….…
- Bateria Li-Po …………………………….……
- Placa Arduino Mega ………………….…
Design da PCB
No entanto, para manter os componentes eletrônicos organizados e livrar-nos da bagunça de fios, projetei uma PCB personalizada usando o software gratuito de design de circuitos online EasyEDA. Esta PCB atuará na verdade como um shield Arduino MEGA, porque poderemos conectá-la diretamente sobre a placa Arduino Mega. Usei tanto a camada superior quanto a inferior para rotear as conexões. Para aqueles pinos do Arduino que não usei, incluí conexões de header de pinos para que estejam disponíveis caso queiramos usá-los para algo no futuro. Também incluí pinos de conexão de 12V, 5V e GND, bem como pinos para selecionar a resolução de passo dos drivers.

Aqui está um link para os arquivos do projeto deste design de PCB. Então, uma vez finalizado o design, gerei o arquivo Gerber necessário para a fabricação da PCB.
Arquivo Gerber:
Então, encomendei a PCB na JLCPCB, que também são os patrocinadores deste vídeo.

Aqui podemos simplesmente arrastar e soltar o arquivo Gerber e, uma vez carregado, podemos revisar nossa PCB no visualizador Gerber. Se tudo estiver certo, podemos prosseguir e selecionar as propriedades que queremos para nossa PCB. Desta vez, escolhi a cor da PCB para ser azul, para combinar com a cor da placa Arduino. E pronto, agora podemos simplesmente encomendar nossa PCB a um preço razoável. Note que se for seu primeiro pedido na JLCPCB, você pode obter até 10 PCBs por apenas $2.

Após alguns dias, as PCBs chegaram. A qualidade das PCBs é ótima e tudo está exatamente igual ao design.

Montagem da PCB
Ok, agora podemos prosseguir e montar a PCB. Comecei soldando os componentes menores primeiro, os resistores e capacitores. Então, inseri e soldei headers de pinos macho na PCB que serão usados para conectá-la à placa Arduino.

Em seguida, coloquei todos os headers de pinos fêmea no lugar e os soldei também. Quanto às conexões dos motores de passo e pinos para selecionar a resolução de passo, usei headers de pinos macho. Dessa forma, podemos conectar os motores diretamente à PCB e usar jumpers para selecionar a resolução de passo. Então, soldei os bornes de terminal, o trimpot e o regulador de tensão.

E pronto, a PCB agora está pronta e podemos prosseguir com a inserção dos drivers e conexão dos motores a ela. Primeiro, coloquei os jumpers para selecionar a resolução de passo. Selecionei resolução de 1/16 de passo conectando os pinos MS3 dos drivers a 5V.

Então, por cima deles, coloquei os drivers DRV8825, bem como conectei o módulo NRF24L01 e o módulo Bluetooth HC-05. Agora podemos simplesmente fixar a PCB na placa Arduino.

Em seguida, conectei a bateria ao bloco de terminais apropriado e a coloquei na plataforma base.

Aqui, inseri o interruptor de alimentação no lugar e o conectei ao outro bloco de terminais. Logo acima do interruptor de alimentação, também inseri o LED indicador de bateria.

O que resta agora é conectar os motores à PCB. Devemos notar aqui que, ao conectar motores opostos, devemos conectar seus conectores de forma oposta também. Isso é necessário mais tarde ao programar o robô, para que, por exemplo, o comando frente, mova ambos os motores na mesma direção, embora eles estejam virados e um faria rotação horária e o outro anti-horária.

No final, posso simplesmente inserir a tampa no topo, e assim terminamos com este projeto de robô com rodas Mecanum.

Código Arduino do Robô com Rodas Mecanum
O que resta para este vídeo é dar uma olhada no código Arduino. Na verdade, existem dois códigos Arduino separados. Este é para controlar o robô usando os módulos NRF24L01 e o outro é para controlar o robô usando um smartphone.
Código Arduino para controlar o robô usando os módulos NRF24L01:
/* === Robô Arduino Rodas Mecanum === Controle por rádio com NRF24L01 por Dejan, www.HowToMechatronics.com Bibliotecas: RF24, https://github.com/tmrh20/RF24/ AccelStepper por Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #include <AccelStepper.h> RF24 radio(48, 49); // nRF24L01 (CE, CSN) const byte address[6] = "00001"; unsigned long lastReceiveTime = 0; unsigned long currentTime = 0; // Define os motores de passo e os pinos que eles usarão AccelStepper LeftBackWheel(1, 42, 43); // (Tipo:driver, STEP, DIR) - Stepper1 AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2 AccelStepper RightBackWheel(1, 44, 45); // Stepper3 AccelStepper RightFrontWheel(1, 46, 47); // Stepper4 int wheelSpeed = 1500; // Tamanho máximo desta struct é 32 bytes - limite do buffer NRF24L01 struct Data_Package { byte j1PotX; byte j1PotY; byte j1Button; byte j2PotX; byte j2PotY; byte j2Button; byte pot1; byte pot2; byte tSwitch1; byte tSwitch2; byte button1; byte button2; byte button3; byte button4; }; Data_Package data; // Cria uma variável com a estrutura acima void setup() { // Define valores iniciais para os steppers LeftFrontWheel.setMaxSpeed(3000); LeftBackWheel.setMaxSpeed(3000); RightFrontWheel.setMaxSpeed(3000); RightBackWheel.setMaxSpeed(3000); radio.begin(); radio.openReadingPipe(0, address); radio.setAutoAck(false); radio.setDataRate(RF24_250KBPS); radio.setPALevel(RF24_PA_LOW); radio.startListening(); // Define o módulo como receptor Serial.begin(115200); } void loop() { // Verifica se continuamos recebendo dados, ou se temos conexão entre os dois módulos currentTime = millis(); if ( currentTime - lastReceiveTime > 1000 ) { // Se o tempo atual for mais de 1 segundo desde que recebemos os últimos dados, significa que perdemos a conexão resetData(); // Se a conexão for perdida, reinicia os dados. Evita comportamento indesejado, por exemplo, se um drone tem throttle up, se perdermos a conexão, ele pode continuar voando se não reiniciarmos a função } // Verifica se há dados para serem recebidos if (radio.available()) { radio.read(&data, sizeof(Data_Package)); // Lê todos os dados e armazena na estrutura 'data' lastReceiveTime = millis(); // Neste momento recebemos os dados } // Define velocidade - potenciômetro esquerdo wheelSpeed = map(data.pot1, 0, 255, 100, 3000); if (data.j1PotX > 150) { moveSidewaysLeft(); } else if (data.j1PotX < 100) { moveSidewaysRight(); } else if (data.j1PotY > 160) { moveForward(); } else if (data.j1PotY < 100) { moveBackward(); } else if (data.j2PotX < 100 & data.j2PotY > 160) { moveRightForward(); } else if (data.j2PotX > 160 & data.j2PotY > 160) { moveLeftForward(); } else if (data.j2PotX < 100 & data.j2PotY < 100) { moveRightBackward(); } else if (data.j2PotX > 160 & data.j2PotY < 100) { moveLeftBackward(); } else if (data.j2PotX < 100) { rotateRight(); } else if (data.j2PotX > 150) { rotateLeft(); } else { stopMoving(); } // Executa os passos LeftFrontWheel.runSpeed(); LeftBackWheel.runSpeed(); RightFrontWheel.runSpeed(); RightBackWheel.runSpeed(); // Monitora tensão da bateria int sensorValue = analogRead(A0); float voltage = sensorValue * (5.0 / 1023.00) * 3; // Converte valores de leitura de 5v para 12V adequados // Se tensão abaixo de 11V liga o LED if (voltage < 11) { digitalWrite(led, HIGH); } else { digitalWrite(led, LOW); } } void moveForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); } void moveBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); } void moveSidewaysRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); } void moveSidewaysLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); } void rotateLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); } void rotateRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); } void moveRightForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(wheelSpeed); } void moveRightBackward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(0); } void moveLeftForward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(0); } void moveLeftBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(-wheelSpeed); } void stopMoving() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(0); } void resetData() { // Reinicia os valores quando não há conexão de rádio - Define valores padrão iniciais data.j1PotX = 127; data.j1PotY = 127; data.j2PotX = 127; data.j2PotY = 127; data.j1Button = 1; data.j2Button = 1; data.pot1 = 1; data.pot2 = 1; data.tSwitch1 = 1; data.tSwitch2 = 1; data.button1 = 1; data.button2 = 1; data.button3 = 1; data.button4 = 1; }
Descrição: Então, aqui estamos usando a biblioteca RF24 para a comunicação de rádio e a biblioteca AccelStepper para controlar os motores de passo. Primeiro, precisamos definir os pinos aos quais todos eles estão conectados, definir algumas variáveis necessárias para o programa abaixo, e na seção setup definir a velocidade máxima dos steppers e iniciar a comunicação de rádio.
Na seção loop, começamos lendo os dados vindos do transmissor RC. O código do transmissor RC, bem como mais detalhes sobre como esta comunicação funciona, podem ser encontrados no meu tutorial particular para ele.
Então, dependendo dos dados recebidos, por exemplo, se o joystick esquerdo for movido para frente, seu valor será maior que 160 e, nesse caso, chamaremos a função personalizada moveForward(). Se dermos uma olhada nesta função, podemos ver que tudo o que ela faz é definir a velocidade dos motores para positiva. Para mover para trás, a velocidade é definida como negativa. Então, para mover em todas as outras direções, só temos que definir as rotações das rodas apropriadamente como explicado no início.
Para executar esses comandos, na seção loop, precisamos chamar as funções runSpeed() para todos os steppers. Na seção loop, também lemos a entrada analógica do divisor de tensão vindo da bateria, e de acordo com este valor podemos saber quando a tensão da bateria cairá abaixo de 11V para que possamos ligar o LED indicador.
Código Arduino para controlar o robô usando um smartphone:
/* === Robô Arduino Rodas Mecanum === Controle via Smartphone Bluetooth por Dejan, www.HowToMechatronics.com Bibliotecas: RF24, https://github.com/tmrh20/RF24/ AccelStepper por Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */ #include <SoftwareSerial.h> #include <AccelStepper.h> SoftwareSerial Bluetooth(A8, 38); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX) // Define os motores de passo e os pinos que eles usarão AccelStepper LeftBackWheel(1, 42, 43); // (Tipo:driver, STEP, DIR) - Stepper1 AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2 AccelStepper RightBackWheel(1, 44, 45); // Stepper3 AccelStepper RightFrontWheel(1, 46, 47); // Stepper4 #define led 14 int wheelSpeed = 1500; int dataIn, m; int lbw[50], lfw[50], rbw[50], rfw[50]; // para armazenar posições/passos int index = 0; void setup() { // Define valores iniciais para os steppers LeftFrontWheel.setMaxSpeed(3000); LeftBackWheel.setMaxSpeed(3000); RightFrontWheel.setMaxSpeed(3000); RightBackWheel.setMaxSpeed(3000); Serial.begin(38400); Bluetooth.begin(38400); // Taxa de baud padrão do módulo Bluetooth Bluetooth.setTimeout(1); delay(20); pinMode(led, OUTPUT); } void loop() { // Verifica dados de entrada if (Bluetooth.available() > 0) { dataIn = Bluetooth.read(); // Lê os dados if (dataIn == 0) { m = 0; } if (dataIn == 1) { m = 1; } if (dataIn == 2) { m = 2; } if (dataIn == 3) { m = 3; } if (dataIn == 4) { m = 4; } if (dataIn == 5) { m = 5; } if (dataIn == 6) { m = 6; } if (dataIn == 7) { m = 7; } if (dataIn == 8) { m = 8; } if (dataIn == 9) { m = 9; } if (dataIn == 10) { m = 10; } if (dataIn == 11) { m = 11; } if (dataIn == 12) { m = 12; } if (dataIn == 14) { m = 14; } // Define velocidade if (dataIn >= 16) { wheelSpeed = dataIn * 10; Serial.println(wheelSpeed); } } if (m == 4) { moveSidewaysLeft(); } if (m == 5) { moveSidewaysRight(); } if (m == 2) { moveForward(); } if (m == 7) { moveBackward(); } if (m == 3) { moveRightForward(); } if (m == 1) { moveLeftForward(); } if (m == 8) { moveRightBackward(); } if (m == 6) { moveLeftBackward(); } if (m == 9) { rotateLeft(); } if (m == 10) { rotateRight(); } if (m == 0) { stopMoving(); } //Serial.println(dataIn); // Se botão "SAVE" é pressionado if (m == 12) { if (index == 0) { LeftBackWheel.setCurrentPosition(0); LeftFrontWheel.setCurrentPosition(0); RightBackWheel.setCurrentPosition(0); RightFrontWheel.setCurrentPosition(0); } lbw[index] = LeftBackWheel.currentPosition(); // salva posição no array lfw[index] = LeftFrontWheel.currentPosition(); rbw[index] = RightBackWheel.currentPosition(); rfw[index] = RightFrontWheel.currentPosition(); index++; // Incrementa o índice do array m = 0; } if (m == 14) { runSteps(); if (dataIn != 14) { stopMoving(); memset(lbw, 0, sizeof(lbw)); // Limpa dados do array para 0 memset(lfw, 0, sizeof(lfw)); memset(rbw, 0, sizeof(rbw)); memset(rfw, 0, sizeof(rfw)); index = 0; // Índice para 0 } } LeftFrontWheel.runSpeed(); LeftBackWheel.runSpeed(); RightFrontWheel.runSpeed(); RightBackWheel.runSpeed(); // Monitora tensão da bateria int sensorValue = analogRead(A0); float voltage = sensorValue * (5.0 / 1023.00) * 3; // Converte valores de leitura de 5v para 12V adequados //Serial.println(voltage); // Se tensão abaixo de 11V liga o LED if (voltage < 11) { digitalWrite(led, HIGH); } else { digitalWrite(led, LOW); } } void runSteps() { for (int i = index - 1; i >= 0; i--) { // Percorre todos os passos(index) LeftFrontWheel.moveTo(lfw[i]); LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.moveTo(lbw[i]); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.moveTo(rfw[i]); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.moveTo(rbw[i]); RightBackWheel.setSpeed(wheelSpeed); while (LeftBackWheel.currentPosition() != lbw[i] & LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) { LeftFrontWheel.runSpeedToPosition(); LeftBackWheel.runSpeedToPosition(); RightFrontWheel.runSpeedToPosition(); RightBackWheel.runSpeedToPosition(); if (Bluetooth.available() > 0) { // Verifica dados de entrada dataIn = Bluetooth.read(); if ( dataIn == 15) { // Se botão "PAUSE" é pressionado while (dataIn != 14) { // Espera até "RUN" ser pressionado novamente if (Bluetooth.available() > 0) { dataIn = Bluetooth.read(); if ( dataIn == 13) { stopMoving(); break; } } } } if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; } if ( dataIn == 13) { break; } } } } // Volta pelos passos for (int i = 1; i <= index - 1; i++) { // Percorre todos os passos(index) LeftFrontWheel.moveTo(lfw[i]); LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.moveTo(lbw[i]); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.moveTo(rfw[i]); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.moveTo(rbw[i]); RightBackWheel.setSpeed(wheelSpeed); while (LeftBackWheel.currentPosition() != lbw[i]& LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) { LeftFrontWheel.runSpeedToPosition(); LeftBackWheel.runSpeedToPosition(); RightFrontWheel.runSpeedToPosition(); RightBackWheel.runSpeedToPosition(); //Serial.print(" current: "); //Serial.println(LeftBackWheel.currentPosition()); if (Bluetooth.available() > 0) { // Verifica dados de entrada dataIn = Bluetooth.read(); if ( dataIn == 15) { // Se botão "PAUSE" é pressionado while (dataIn != 14) { // Espera até "RUN" ser pressionado novamente if (Bluetooth.available() > 0) { dataIn = Bluetooth.read(); if ( dataIn == 13) { stopMoving(); break; } } } } if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; } if ( dataIn == 13) { //Serial.println("DEKI"); break; } } } } } void moveForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); } void moveBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); } void moveSidewaysRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); } void moveSidewaysLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); } void rotateLeft() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(wheelSpeed); } void rotateRight() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(-wheelSpeed); } void moveRightForward() { LeftFrontWheel.setSpeed(wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(wheelSpeed); } void moveRightBackward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(-wheelSpeed); RightFrontWheel.setSpeed(-wheelSpeed); RightBackWheel.setSpeed(0); } void moveLeftForward() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(wheelSpeed); RightFrontWheel.setSpeed(wheelSpeed); RightBackWheel.setSpeed(0); } void moveLeftBackward() { LeftFrontWheel.setSpeed(-wheelSpeed); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(-wheelSpeed); } void stopMoving() { LeftFrontWheel.setSpeed(0); LeftBackWheel.setSpeed(0); RightFrontWheel.setSpeed(0); RightBackWheel.setSpeed(0); }
Descrição: O outro código para controlar o robô usando o aplicativo Android é muito similar e funciona da mesma forma. Aqui, em vez do módulo de rádio, precisamos definir o módulo Bluetooth e inicializar sua comunicação na seção setup. Então, novamente, primeiro lemos os dados de entrada do smartphone ou do aplicativo Android, e de acordo com eles, dizemos ao robô em qual direção mover.
Se dermos uma olhada no aplicativo Android, podemos ver que ele simplesmente envia números de 0 a 15 através do Bluetooth quando os botões são pressionados.

O aplicativo é feito usando o aplicativo online MIT App Inventor e você pode encontrar mais detalhes sobre ele no meu tutorial particular para ele.

Aqui você pode baixar este aplicativo, bem como o arquivo de projeto editável:
Para programar o movimento automático do robô com este aplicativo, quando pressionamos o botão "SALVAR", simplesmente armazenamos as posições atuais dos motores de passo em arrays. Então, quando pressionamos o botão "EXECUTAR", chamamos a função personalizada runSteps() que executa ou percorre todos os passos armazenados usando alguns loops for e while.
Espero que tenha gostado deste tutorial e aprendido algo novo. Sinta-se à vontade para fazer qualquer pergunta na seção de comentários abaixo e confira minha Coleção de Projetos Arduino.
Processo de manufatura
- Construa um Robô Raspberry Pi Controlado por Bluetooth com Feedback de Áudio
- Robô Desviador de Obstáculos com Servo: Construa com Arduino e HC-SR04
- Criar Robô Seguidor de Linha Autônomo com Arduino UNO
- Construa um Robô Controlado por Voz com Arduino Nano
- PiBot: Robô Pianista Arduino para Performance Musical de Precisão
- LittleArm 2C: Braço Robótico Arduino 3D-Printado Durável para Educação STEM
- Robô Assistente Doméstico Autônomo: Lista Completa de Peças e Guia de Configuração
- Controle Braço Robótico Arduino via App Android Dedicado
- Kit de Robô de Navegação Interna Inteligente para Projetos Arduino
- WiDC: Robô FPV Wi‑Fi – Controle Remoto com Vídeo ao Vivo