Controle Seu Carro Robô Arduino sem Fio com HC-05 Bluetooth, NRF24L01 e Módulos Transceptores HC-12
Neste tutorial, aprenderemos a controlar sem fio o carro robô Arduino que fizemos no vídeo anterior. Mostrarei três métodos diferentes de controle sem fio: usando o módulo Bluetooth HC-05, o módulo transceptor NRF24L01 e o módulo wireless de longo alcance HC-12, bem como usando um Smartphone e um aplicativo Android personalizado. Você pode assistir ao vídeo a seguir ou ler o tutorial escrito abaixo para mais detalhes.
Já tenho tutoriais sobre como conectar e usar cada um destes módulos com a placa Arduino, então se precisar de mais detalhes, pode sempre conferi-los. Os links para cada um deles podem ser encontrados abaixo no artigo.
Controle do Carro Robô Arduino Usando Módulo Bluetooth HC-05
Começaremos com a comunicação Bluetooth, e para isso precisamos de dois módulos Bluetooth HC-05 que precisam ser configurados como dispositivos master e slave.

Podemos fazer isso facilmente usando comandos AT, e configurei o joystick como master e o carro robô Arduino como slave. Aqui está o esquemático completo do circuito para este exemplo:

Você pode obter os componentes necessários para este exemplo nos links abaixo:
- Módulo Bluetooth HC-05
- Módulo Joystick
- Baterias 18650
- Carregador de Bateria 18650
- Driver L298N
- Motor DC High Torque 12V
- Placa Arduino
Código Fonte
Usaremos o mesmo código do tutorial anterior, onde controlamos o carro robô Arduino diretamente usando o joystick, e faremos algumas modificações.
Código HC-05 Master (Joystick):
/* Arduino Robot Car Wireless Control using the HC-05 Bluetooth
== MASTER DEVICE - Joystick ==
by Dejan Nedelkovski, www.HowToMechatronics.com */
int xAxis, yAxis;
void setup() {
Serial.begin(38400); // Taxa de comunicação padrão do módulo Bluetooth
}
void loop() {
xAxis = analogRead(A0); // Lê eixo X do Joystick
yAxis = analogRead(A1); // Lê eixo Y do Joystick
// Envia os valores via porta serial para o dispositivo HC-05 Bluetooth slave
Serial.write(xAxis/4); // Dividindo por 4 para converter de 0-1023 para 0-256 (1 byte)
Serial.write(yAxis/4);
delay(20);
}
O código no dispositivo master (joystick) é bastante simples. Apenas precisamos ler os valores X e Y do joystick, que regulam a velocidade dos motores, e enviá-los via porta serial para o dispositivo HC-05 Bluetooth slave. Podemos notar aqui que os valores analógicos do joystick de 0 a 1023 são convertidos em valores de 0 a 255 dividindo-os por 4.
Fazemos isso porque esse intervalo, de 0 a 255, pode ser enviado pelo dispositivo Bluetooth como 1 byte, o que é mais fácil de ser aceito do outro lado, ou no carro robô Arduino.
Então aqui, se a serial recebeu os 2 bytes (valores X e Y), usando a função Serial.read() leremos ambos.
// Código do Carro Robô Arduino
// Lê os dados de entrada do Joystick, ou do dispositivo Bluetooth master
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
Agora só temos que converter os valores de volta para o intervalo de 0 a 1023, adequado para o código de controle de motor abaixo, que já explicamos como funciona no vídeo anterior.
// Código do Carro Robô Arduino
// Converte de volta o intervalo 0-255 para 0-1023, adequado para código de controle de motor
xAxis = x*4;
yAxis = y*4;
Uma nota rápida: ao fazer upload do código, precisamos desconectar os pinos RX e TX da placa Arduino.
Código HC-05 Slave Completo (Carro Robô):
/* Arduino Robot Car Wireless Control using the HC-05 Bluetooth
== SLAVE DEVICE - Arduino robot car ==
by Dejan Nedelkovski, www.HowToMechatronics.com */
#define enA 9
#define in1 4
#define in2 5
#define enB 10
#define in3 6
#define in4 7
int xAxis, yAxis;
unsigned int x = 0;
unsigned int y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(38400); // Taxa de comunicação padrão do módulo Bluetooth
}
void loop() {
// Valor padrão - sem movimento quando Joystick fica no centro
x = 510 / 4;
y = 510 / 4;
// Lê os dados de entrada do Joystick, ou do dispositivo Bluetooth master
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
delay(10);
// Converte de volta o intervalo 0-255 para 0-1023, adequado para código de controle de motor
xAxis = x*4;
yAxis = y*4;
// Eixo Y usado para controle frente/trás
if (yAxis < 470) {
// Motor A para trás
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Motor B para trás
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Converte leituras decrescentes do eixo Y para ir para trás de 470 a 0 em valor 0-255 para sinal PWM
motorSpeedA = map(yAxis, 470, 0, 0, 255);
motorSpeedB = map(yAxis, 470, 0, 0, 255);
} else if (yAxis > 550) {
// Motor A para frente
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// Motor B para frente
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// Converte leituras crescentes do eixo Y para ir para frente de 550 a 1023 em valor 0-255 para sinal PWM
motorSpeedA = map(yAxis, 550, 1023, 0, 255);
motorSpeedB = map(yAxis, 550, 1023, 0, 255);
}
// Se joystick fica no meio, motores não se movem
else {
motorSpeedA = 0;
motorSpeedB = 0;
}
// Eixo X usado para controle esquerda/direita
if (xAxis < 470) {
// Converte leituras decrescentes do eixo X de 470 a 0 em valor crescente 0-255
int xMapped = map(xAxis, 470, 0, 0, 255);
// Move para esquerda - diminui velocidade motor esquerdo, aumenta motor direito
motorSpeedA = motorSpeedA - xMapped;
motorSpeedB = motorSpeedB + xMapped;
// Limita intervalo de 0 a 255
if (motorSpeedA < 0) { motorSpeedA = 0; }
if (motorSpeedB > 255) { motorSpeedB = 255; }
}
if (xAxis > 550) {
// Converte leituras crescentes do eixo X de 550 a 1023 em valor 0-255
int xMapped = map(xAxis, 550, 1023, 0, 255);
// Move para direita - diminui velocidade motor direito, aumenta motor esquerdo
motorSpeedA = motorSpeedA + xMapped;
motorSpeedB = motorSpeedB - xMapped;
// Limita intervalo de 0 a 255
if (motorSpeedA > 255) { motorSpeedA = 255; }
if (motorSpeedB < 0) { motorSpeedB = 0; }
}
// Evita zumbido em baixas velocidades (Ajuste conforme seus motores. Meus motores não conseguiam começar a mover se valor PWM abaixo de 70)
if (motorSpeedA < 70) { motorSpeedA = 0; }
if (motorSpeedB < 70) { motorSpeedB = 0; }
analogWrite(enA, motorSpeedA); // Envia sinal PWM para motor A
analogWrite(enB, motorSpeedB); // Envia sinal PWM para motor B
}
Controle do Carro Robô Arduino Usando Smartphone e App Android Personalizado
Em seguida, vamos ver como podemos controlar nosso carro robô Arduino usando um app Android personalizado. O esquemático do carro robô é exatamente o mesmo do exemplo anterior, com o módulo Bluetooth HC-05 configurado como dispositivo slave.

Por outro lado, usando o aplicativo online MIT App Inventor, construiremos nosso próprio app Android, e aqui está como ele fica.
Basicamente, o app simula um joystick, cuja aparência é feita de duas imagens, ou image sprites.


Se olharmos os blocos deste app, podemos ver que quando o sprite do joystick é arrastado, a imagem da bola do joystick é movida para a localização atual do nosso dedo, e ao mesmo tempo enviamos os valores X e Y via Bluetooth para o carro Arduino.
Estes valores são aceitos pelo Arduino da mesma forma que no exemplo anterior, usando a função Serial.read.
// Lê os dados de entrada do Smartphone Android App
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
O que precisamos fazer adicionalmente aqui é converter os valores X e Y recebidos do smartphone para o intervalo 0 a 1023, adequado para o código de controle de motor abaixo. Estes valores dependem do tamanho do canvas, e os valores X e Y que eu obtinha do meu app eram de 60 a 220, que usando a função map() converti facilmente.
// Garante que recebemos valores corretos
if (x > 60 & x < 220) {
xAxis = map(x, 220, 60, 1023, 0); // Converte valores X e Y do smartphone para intervalo 0-1023
}
if (y > 60 & y < 220) {
yAxis = map(y, 220, 60, 0, 1023);
}
Nos blocos da aplicação, também podemos ver que quando o image sprite é solto (touch up), a bola do joystick volta para o centro do canvas e valores apropriados são enviados para o carro para parar de mover. Você pode encontrar e baixar este app no artigo do site, bem como as duas imagens do joystick para construir seu próprio ou modificar este app.
Você pode baixar o App Android abaixo, bem como as duas imagens para o joystick:
Arduino_Robot_Car_Joystick_App.apk
1 arquivo(s) 1.62 MB Download
Arduino_Robot_Car_Joystick_App_aia_file
1 arquivo(s) 171.20 KB Download
Joystick App Images
1 arquivo(s) 44.36 KB DownloadCódigo Arduino Completo (com App Android):
/* Arduino Robot Car Wireless Control using the HC-05 Bluetooth and custom-build Android app
== SLAVE DEVICE - Arduino robot car ==
by Dejan Nedelkovski, www.HowToMechatronics.com */
#define enA 9
#define in1 4
#define in2 5
#define enB 10
#define in3 6
#define in4 7
int xAxis, yAxis;
int x = 0;
int y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(38400); // Taxa de comunicação padrão do módulo Bluetooth
}
void loop() {
// Valor padrão - sem movimento quando Joystick fica no centro
xAxis = 510;
yAxis = 510;
// Lê os dados de entrada do Smartphone Android App
while (Serial.available() >= 2) {
x = Serial.read();
delay(10);
y = Serial.read();
}
delay(10);
// Garante que recebemos valores corretos
if (x > 60 & x < 220) {
xAxis = map(x, 220, 60, 1023, 0);
}
if (y > 60 & y < 220) {
yAxis = map(y, 220, 60, 0, 1023);
}
// Eixo Y usado para controle frente/trás
if (yAxis < 470) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
motorSpeedA = map(yAxis, 470, 0, 0, 255);
motorSpeedB = map(yAxis, 470, 0, 0, 255);
} else if (yAxis > 550) {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
motorSpeedA = map(yAxis, 550, 1023, 0, 255);
motorSpeedB = map(yAxis, 550, 1023, 0, 255);
} else {
motorSpeedA = 0;
motorSpeedB = 0;
}
// Eixo X usado para controle esquerda/direita
if (xAxis < 470) {
int xMapped = map(xAxis, 470, 0, 0, 255);
motorSpeedA = motorSpeedA - xMapped;
motorSpeedB = motorSpeedB + xMapped;
if (motorSpeedA < 0) { motorSpeedA = 0; }
if (motorSpeedB > 255) { motorSpeedB = 255; }
}
if (xAxis > 550) {
int xMapped = map(xAxis, 550, 1023, 0, 255);
motorSpeedA = motorSpeedA + xMapped;
motorSpeedB = motorSpeedB - xMapped;
if (motorSpeedA > 255) { motorSpeedA = 255; }
if (motorSpeedB < 0) { motorSpeedB = 0; }
}
// Evita zumbido em baixas velocidades
if (motorSpeedA < 70) { motorSpeedA = 0; }
if (motorSpeedB < 70) { motorSpeedB = 0; }
analogWrite(enA, motorSpeedA);
analogWrite(enB, motorSpeedB);
}
Controle Wireless do Carro Robô Arduino Usando Módulo Transceptor NRF24L01
Agora podemos passar para o próximo método: controle wireless do carro robô Arduino usando os módulos transceptores NRF24L01.


Aqui está o esquemático do circuito. Podemos notar que estes módulos usam comunicação SPI, então comparado ao exemplo anterior, tive que mover os pinos Enable A e Enable B do driver L298N para os pinos 2 e 3 da placa Arduino.
Código Fonte
Para este exemplo, precisamos instalar a biblioteca RF24. De forma semelhante ao exemplo anterior, após definir alguns pinos e configurar o módulo como transmissor, lemos os valores X e Y do joystick e os enviamos para o outro módulo NRF24L01 no carro robô Arduino.
Primeiro, podemos notar que as leituras analógicas são Strings, que usando a função string.toCharArray() são colocadas em um array de caracteres. Então, usando a função radio.write(), enviamos esses dados do array de caracteres para o outro módulo.
Código do Transmissor (Joystick):
/* Arduino Robot Car Wireless Control using the NRF24L01 Transceiver module
== Transmitter - Joystick ==
by Dejan Nedelkovski, www.HowToMechatronics.com
Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(8, 9); // CE, CSN
const byte address[6] = "00001";
char xyData[32] = "";
String xAxis, yAxis;
void setup() {
Serial.begin(9600);
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
}
void loop() {
xAxis = analogRead(A0); // Lê eixo X do Joystick
yAxis = analogRead(A1); // Lê eixo Y do Joystick
// Valor X
xAxis.toCharArray(xyData, 5); // Coloca String (Valor X) em array de caracteres
radio.write(&xyData, sizeof(xyData)); // Envia array de dados (valor X) para outro módulo NRF24L01
// Valor Y
yAxis.toCharArray(xyData, 5);
radio.write(&xyData, sizeof(xyData));
delay(20);
}
Do outro lado, no carro robô Arduino, após definir o módulo como receptor, aceitamos dados usando a função radio.read(). Então, usando a função atoi(), convertemos os dados recebidos (valores X e Y do joystick) em valores inteiros, adequados para o código de controle de motor abaixo.
// Código do Carro Robô Arduino - Exemplo NRF24L01
if (radio.available()) {
radio.read(&receivedData, sizeof(receivedData));
xAxis = atoi(&receivedData[0]);
delay(10);
radio.read(&receivedData, sizeof(receivedData));
yAxis = atoi(&receivedData[0]);
delay(10);
}
É simples assim, mas claro, como já disse, se precisar de mais detalhes sobre como conectar e configurar os módulos, pode sempre conferir meu tutorial particular para isso.
Código do Receptor (Carro Robô):
/* Arduino Robot Car Wireless Control using the NRF24L01 Transceiver module
== Receiver - Arduino robot car ==
by Dejan Nedelkovski, www.HowToMechatronics.com
Library: TMRh20/RF24, https://github.com/tmrh20/RF24/ */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define enA 2 // Nota: Pino 9 no vídeo anterior (pino 10 usado para SPI do NRF24L01)
#define in1 4
#define in2 5
#define enB 3 // Nota: Pino 10 no vídeo anterior
#define in3 6
#define in4 7
RF24 radio(8, 9); // CE, CSN
const byte address[6] = "00001";
char receivedData[32] = "";
int xAxis, yAxis;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MIN);
radio.startListening();
}
void loop() {
if (radio.available()) {
radio.read(&receivedData, sizeof(receivedData));
xAxis = atoi(&receivedData[0]);
delay(10);
radio.read(&receivedData, sizeof(receivedData));
yAxis = atoi(&receivedData[0]);
delay(10);
}
// Controle frente/trás (eixo Y)
if (yAxis < 470) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
motorSpeedA = map(yAxis, 470, 0, 0, 255);
motorSpeedB = map(yAxis, 470, 0, 0, 255);
} else if (yAxis > 550) {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
motorSpeedA = map(yAxis, 550, 1023, 0, 255);
motorSpeedB = map(yAxis, 550, 1023, 0, 255);
} else {
motorSpeedA = 0;
motorSpeedB = 0;
}
// Controle esquerda/direita (eixo X)
if (xAxis < 470) {
int xMapped = map(xAxis, 470, 0, 0, 255);
motorSpeedA = motorSpeedA - xMapped;
motorSpeedB = motorSpeedB + xMapped;
if (motorSpeedA < 0) { motorSpeedA = 0; }
if (motorSpeedB > 255) { motorSpeedB = 255; }
}
if (xAxis > 550) {
int xMapped = map(xAxis, 550, 1023, 0, 255);
motorSpeedA = motorSpeedA + xMapped;
motorSpeedB = motorSpeedB - xMapped;
if (motorSpeedA > 255) { motorSpeedA = 255; }
if (motorSpeedB < 0) { motorSpeedB = 0; }
}
// Evita zumbido em baixas velocidades
if (motorSpeedA < 70) { motorSpeedA = 0; }
if (motorSpeedB < 70) { motorSpeedB = 0; }
analogWrite(enA, motorSpeedA);
analogWrite(enB, motorSpeedB);
}
Controle Wireless do Carro Robô Arduino Usando Transceptor HC-12 Longo Alcance
Para o último método de controle wireless do carro robô Arduino, usaremos os módulos transceptores HC-12 de longo alcance. Estes módulos podem se comunicar entre si com distâncias de até 1,8 km.
O esquemático do circuito para este exemplo é quase o mesmo do dos módulos Bluetooth HC-05, pois eles usam o mesmo método de comunicação com o Arduino, via porta serial.

Código Fonte
O código do Joystick é exatamente o mesmo do usado para comunicação Bluetooth. Apenas lemos os valores analógicos do joystick e os enviamos para o outro módulo usando a função Serial.write().
Código do Transmissor (Joystick):
/* Arduino Robot Car Wireless Control using the HC-12 long range wireless module
== Transmitter - Joystick ==
by Dejan Nedelkovski, www.HowToMechatronics.com */
int xAxis, yAxis;
void setup() {
Serial.begin(9600); // Taxa de comunicação padrão do módulo Bluetooth
}
void loop() {
xAxis = analogRead(A0); // Lê eixo X do Joystick
yAxis = analogRead(A1); // Lê eixo Y do Joystick
// Envia os valores via porta serial para o dispositivo HC-05 Bluetooth slave
Serial.write(xAxis/4); // Dividindo por 4 para converter de 0-1023 para 0-256 (1 byte)
Serial.write(yAxis/4);
delay(20);
}
Do outro lado, com o loop while() esperamos até os dados chegarem, então lemos usando a função Serial.read() e convertemos de volta para o intervalo 0 a 1023, adequado para o código de controle de motor abaixo.
Código do Receptor (Carro Robô):
/* Arduino Robot Car Wireless Control using the HC-12 long range wireless module
== Receiver - Arduino robot car ==
by Dejan Nedelkovski, www.HowToMechatronics.com */
#define enA 9
#define in1 4
#define in2 5
#define enB 10
#define in3 6
#define in4 7
int xAxis, yAxis;
int x = 0;
int y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
Serial.begin(9600); // Taxa de comunicação padrão do módulo Bluetooth
}
void loop() {
// Valor padrão - sem movimento quando Joystick fica no centro
xAxis = 510;
yAxis = 510;
// Lê os dados de entrada do
while (Serial.available() == 0) {}
x = Serial.read();
delay(10);
y = Serial.read();
delay(10);
// Converte de volta o intervalo 0-255 para 0-1023, adequado para código de controle de motor
xAxis = x * 4;
yAxis = y * 4;
// Eixo Y usado para controle frente/trás
if (yAxis < 470) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
motorSpeedA = map(yAxis, 470, 0, 0, 255);
motorSpeedB = map(yAxis, 470, 0, 0, 255);
} else if (yAxis > 550) {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
motorSpeedA = map(yAxis, 550, 1023, 0, 255);
motorSpeedB = map(yAxis, 550, 1023, 0, 255);
} else {
motorSpeedA = 0;
motorSpeedB = 0;
}
// Eixo X usado para controle esquerda/direita
if (xAxis < 470) {
int xMapped = map(xAxis, 470, 0, 0, 255);
motorSpeedA = motorSpeedA - xMapped;
motorSpeedB = motorSpeedB + xMapped;
if (motorSpeedA < 0) { motorSpeedA = 0; }
if (motorSpeedB > 255) { motorSpeedB = 255; }
}
if (xAxis > 550) {
int xMapped = map(xAxis, 550, 1023, 0, 255);
motorSpeedA = motorSpeedA + xMapped;
motorSpeedB = motorSpeedB - xMapped;
if (motorSpeedA > 255) { motorSpeedA = 255; }
if (motorSpeedB < 0) { motorSpeedB = 0; }
}
// Evita zumbido em baixas velocidades
if (motorSpeedA < 70) { motorSpeedA = 0; }
if (motorSpeedB < 70) { motorSpeedB = 0; }
analogWrite(enA, motorSpeedA);
analogWrite(enB, motorSpeedB);
}
É basicamente isso para este tutorial. Sinta-se à vontade para fazer qualquer pergunta na seção de comentários abaixo.
Processo de manufatura
- Construa um Robô Raspberry Pi Controlado por Bluetooth com Feedback de Áudio
- Controle Remoto Universal Android com Arduino, 1Sheeld e IR
- Construa um Voltímetro Inteligente com Arduino e Smartphone – Projeto DIY Fácil
- Controlar um LED via Bluetooth com Arduino – Guia DIY Simples
- Controle um Rover Arduino com Firmata e Gamepad Xbox One
- Contador Inteligente de Vagas: Rastreamento de Veículos em Tempo Real com Arduino, Processing e PHP
- Controle sua TV com Alexa via Arduino IoT Cloud – Guia Passo a Passo
- Construa um Rádio FM Compacto com Arduino Nano e RDA5807M
- Shield de Programação Wireless Arduino com HC-05 Bluetooth – Sem Cabo USB
- Controle Remoto de Carro com Arduino Uno e Bluetooth: Guia Passo a Passo