Tutorial · Iniciante · 1 hora
Controle um robô por Bluetooth com um módulo HC-05
Ligue um HC-05 a um Arduino, pareie-o com seu celular e projete um protocolo de comandos seriais que mantenha o robô responsivo e seguro quando a conexão cai.
Introdução
O HC-05 é a maneira mais barata de tornar um robô sem fio. É uma ponte serial Bluetooth: o que seu celular envia chega à porta serial do Arduino como bytes comuns, e o que o Arduino imprime volta para o celular. Nada no seu código precisa saber que o Bluetooth existe.
Essa simplicidade é o atrativo, mas também é a armadilha. Uma conexão por rádio não é um fio — ela cai, atrasa e se desconecta enquanto seu robô ainda está andando. A maior parte deste tutorial trata da diferença entre um cabo e uma conexão sem fio.
Ligação, e o erro que quase todo mundo comete
O módulo HC-05 opera sua lógica em 3,3 V, embora a placa adaptadora aceite 5 V em VCC. O pino RX não tolera 5 V.
| HC-05 | Arduino Uno / Nano | Observações |
|---|---|---|
VCC |
5V |
O regulador da placa resolve isso |
GND |
GND |
Massa comum com todo o restante |
TXD |
D10 (RX por software) |
A saída de 3,3 V do HC-05 é lida corretamente como nível lógico ALTO por uma entrada de 5 V |
RXD |
D11 (TX por software) por meio de um divisor |
Aplicar 5 V diretamente ao RXD pode danificá-lo com o tempo |
EN / KEY |
D9 (opcional) |
Coloque em ALTO na energização para entrar no modo de comandos AT |
Reduza a linha de transmissão de 5 V do Arduino para 3,3 V com um divisor de tensão de dois resistores — 2 kΩ do pino do Arduino ao RXD do HC-05 e 3,3 kΩ dessa junção à massa. Custa dois componentes e evita uma falha realmente frustrante de diagnosticar, porque um módulo danificado assim muitas vezes continua parcialmente funcional: ele pareia, transmite e ignora ou corrompe silenciosamente os comandos enviados.
Use SoftwareSerial, não os pinos 0 e 1. A porta serial de hardware é compartilhada com o USB, então um módulo ligado ali disputa com o monitor serial e bloqueia o carregamento do código.
#include <SoftwareSerial.h>
SoftwareSerial bt(10, 11); // RX, TX
void setup() {
Serial.begin(115200); // USB, for debugging
bt.begin(9600); // HC-05 default baud
}
Pareamento
Alimente o robô, e o LED do módulo piscará rapidamente — isso significa “aguardando pareamento”. No celular, pareie com HC-05 usando o código 1234 ou 0000.
Pareamento não é conexão. A conexão só abre quando um aplicativo no celular realmente abre a porta serial. Qualquer terminal serial Bluetooth serve para começar; o LED do módulo passa a piscar com dois lampejos em intervalos mais lentos quando há uma conexão ativa.
Projetando o protocolo de comandos
O primeiro protocolo óbvio é um caractere por comando, e ele funciona por cerca de dez minutos:
if (bt.available()) {
char c = bt.read();
if (c == 'F') forward();
else if (c == 'B') back();
else if (c == 'S') stop();
}
Duas coisas dão errado com ele.
Ele não tem velocidade. Cada comando representa potência total, então o robô fica parado ou se desloca na velocidade máxima. Envie um valor junto com o comando — uma letra e um número, encerrados por uma quebra de linha, o que é facilmente analisável e fácil de digitar manualmente durante a depuração:
// "F180\n" — forward at 180 of 255
char buffer[16];
if (bt.available()) {
int n = bt.readBytesUntil('\n', buffer, sizeof(buffer) - 1);
buffer[n] = '\0';
char cmd = buffer[0];
int value = atoi(buffer + 1);
...
}
Ele pressupõe que a mensagem chega inteira. bt.available() ficar diferente de zero significa que alguns bytes chegaram, não todos. Ler um caractere por laço e agir imediatamente pode fazer o robô executar uma ação antes de o comando completo chegar. Ler até a quebra de linha é o que torna a análise confiável.
A falha que importa: perder a conexão
Um robô com fio para quando você solta os comandos. Um robô sem fio continua fazendo a última coisa que você mandou — que, se a última coisa foi “avançar na velocidade máxima” e você acabou de sair do alcance, é um robô embaixo do sofá em velocidade total.
Todo robô sem fio precisa de um tempo limite de segurança. A regra é simples: se nenhum comando chegou recentemente, pare.
unsigned long lastCommandAt = 0;
const unsigned long TIMEOUT_MS = 500;
void loop() {
if (readCommand()) lastCommandAt = millis();
// Nothing heard recently? Assume the link is gone.
if (millis() - lastCommandAt > TIMEOUT_MS) stop();
}
Para isso ajudar, o controlador precisa continuar falando. Faça o celular enviar o comando atual repetidamente — a cada 100 ms, mais ou menos, enquanto um botão estiver pressionado — em vez de uma vez ao pressionar e uma vez ao soltar. Assim, “botão solto” e “celular fora de alcance” produzem o mesmo resultado seguro, e você nunca depende de uma mensagem de soltura que talvez nunca chegue.
Use millis() para isso, nunca delay(). Um delay(200) no laço significa 200 ms sem ler comandos, sem verificar o tempo limite e sem conseguir receber novos comandos.
Modo de comandos AT
Para renomear o módulo ou alterar sua taxa de baud, mantenha EN/KEY em ALTO enquanto o módulo é energizado. O LED pisca lentamente — cerca de uma vez a cada dois segundos — e isso indica que você está no modo de comando, não no modo de dados.
AT → OK
AT+NAME=MyRobot → OK
AT+PSWD="4821" → OK
AT+UART=38400,0,0
Os comandos devem ser enviados a 38400 baud no modo AT, independentemente da taxa de baud do modo de dados, e a maioria das implementações de firmware exige retorno de carro e quebra de linha. Se AT não retornar nada, essa incompatibilidade é quase sempre o motivo.
Aumentar a taxa de baud de dados vale a pena se você estiver enviando telemetria de volta, mas deixe em 9600 enquanto acertar o protocolo — uma taxa mais alta quase sempre dificulta enxergar erros de enquadramento.
Verifique antes de controlar
Três verificações, nesta ordem:
- Teste de eco. Faça o Arduino imprimir de volta o que recebe. Se uma linha digitada voltar intacta, a ligação e a taxa de baud estão corretas.
- Teste de análise. Imprima a letra e o valor do comando analisado. Confirme que
F180resulta emFe180, não emFe1. - Teste do tempo limite. Envie um comando de avanço e feche o aplicativo ou se afaste. O robô precisa parar dentro do prazo de segurança definido. Se não parar, corrija isso antes de colocar rodas no chão.
Quando a conexão estiver confiável, o mesmo protocolo de comandos entra diretamente em um robô com autonomia: construa a camada sem fio no projeto de robô controlado por celular ou avance para o ESP32, que serve uma página de controle pela web via Wi-Fi e não precisa de aplicativo algum.
Explore o grafo
Faz parte destas montagens
Projetos e caminhos de aprendizagem que incluem este tutorial.
Leitura complementar