Guias · 20 min de leitura

Como fazer um carrinho robô com Arduino: controle por Bluetooth passo a passo

Monte um carrinho robô com Arduino passo a passo: peças e custo, ligação do L298N e do HC-05, baterias 18650, código de movimento, controle pelo celular e soluções para desvio e resets.

Montar um carrinho com Arduino é uma das formas mais divertidas de aprender eletrônica e programação em um único projeto. Com dois motores CC com redução, um driver de motor L298N, duas baterias 18650, um módulo Bluetooth HC-05 e um Arduino Uno, você monta em um fim de semana um carrinho robô que dirige pelo celular. No caminho, vai ver com os próprios olhos por que motores não podem ser ligados direto no Arduino, por que a escolha da bateria importa tanto e como algumas linhas de código movem um veículo de verdade.

Neste guia montamos juntos, do início ao fim, um carrinho robô 2WD (dois motores): lista de peças e divisão de custos, montagem do chassi, tabelas de ligação, código para frente, para trás e curvas e controle por Bluetooth pelo celular. Os dois problemas que mais dão trabalho aos iniciantes, o carrinho que não anda reto e o Arduino que reinicia quando os motores ligam, ganham cada um a sua própria seção, com soluções práticas e testadas. Nas últimas seções você vê como dirigir o mesmo carrinho com um ESP32 ou um Raspberry Pi Pico e como transformá-lo em um robô que desvia de obstáculos ou segue linha.

Placa Arduino Uno
Placa Arduino Uno
Driver de motor L298N
Driver de motor L298N
Módulo Bluetooth HC-05
Módulo Bluetooth HC-05
Bateria Li-ion 18650
Bateria Li-ion 18650

Como funciona um carrinho robô com Arduino?

Você pode dividir um carrinho robô em quatro partes. O Arduino é o cérebro: ele lê o comando do celular e decide qual motor gira em qual sentido e com que velocidade. O driver de motor L298N é o músculo: ele transforma os sinais fracos de 5 V do Arduino na corrente alta de que os motores precisam. Os motores com redução giram as rodas, e o pacote de baterias alimenta tudo. Esses carrinhos não têm direção; eles fazem curvas girando as duas rodas em velocidades ou sentidos diferentes. Isso se chama tração diferencial: se a roda esquerda gira para a frente e a direita para trás, o carrinho gira no lugar para a direita. Uma pequena roda boba, que gira livre na frente ou atrás, mantém o corpo equilibrado.

Motor TT amarelo com redução e conjunto de roda de 65 mm
O motor padrão de carrinho robô: um motor TT com caixa de redução de plástico amarela e roda de 65 mm. A caixa de redução diminui a rotação do motor 48 vezes e aumenta o torque.
CaracterísticaMotor TT amarelo (1:48)
Tensão de operação3–6 V
Relação de redução1:48 (engrenagens de plástico)
Rotação sem cargaCerca de 90–120 RPM em 3 V, 200–250 RPM em 6 V
Corrente sem cargaCerca de 150–160 mA
Corrente de travamentoCerca de 1,1–1,5 A
Diâmetro da roda (nos kits)65 mm
Velocidade do carrinho em 6 VCerca de 0,7 m/s (π × 0,065 m × 200 / 60)

A linha mais importante da tabela é a corrente de travamento: quando uma roda empurra um obstáculo ou o carrinho arranca, cada motor puxa por um instante mais de 1 ampère. Um pino do Arduino fornece no máximo 20–40 mA, então os motores são sempre ligados através de um driver. Fazendo esse trabalho, o L298N perde cerca de 1,5–2,5 V; com um pacote de baterias de 7,4 V, sobram 5–6 V para os motores, exatamente a faixa ideal dos motores TT. Explicamos em detalhe o funcionamento interno do driver e a ideia da ponte H em Controle de motor CC com L298N.

Lista de peças

PeçaQtd.Observação
Kit de chassi de acrílico para carrinho robô 2WD1Normalmente traz 2 motores TT, 2 rodas, uma roda boba, uma chave, suportes de motor e parafusos
Arduino Uno R3 (um clone serve) + cabo USB1Um Nano também funciona; os números dos pinos são os mesmos
Módulo driver de motor L298N12 A por canal; aciona dois motores de forma independente
Módulo Bluetooth HC-05 ou HC-061Para conversar com um celular Android
Célula Li-ion 186502Células de marca que fornecem pelo menos 5 A
Suporte para 2 baterias 18650 (em série)1Liga as duas células em série para 7,4 V
Carregador de 186501Um carregador que carrega cada célula separadamente
Jumpers (macho-fêmea e fêmea-fêmea)20+Entre o Arduino, o L298N e o HC-05
Resistores de 1 kΩ e 2 kΩ1 + 1Divisor de tensão para a entrada RXD do HC-05
Capacitor cerâmico de 100 nF2–4Nos terminais dos motores, para suprimir ruído
Capacitor eletrolítico de 470–1000 µF (16 V ou mais)1Recomendado; na entrada de alimentação do L298N
Abraçadeiras, fita dupla face, espaçadores M3AlgunsPara fixar as placas e os fios no lugar

A maioria dos kits de chassi também traz um suporte para 4 pilhas AA; como você vai ver daqui a pouco, esse suporte é fraco demais em conjunto com o L298N, por isso colocamos células 18650 na lista. O HC-06 é o irmão mais simples do HC-05, que só funciona como escravo, e serve perfeitamente para controlar um carrinho pelo celular. Os discos de plástico com fendas do kit são discos de encoder para um sensor de velocidade que você pode usar depois para fazer o carrinho andar perfeitamente reto; não os jogue fora, só deixe de lado por enquanto.

Custo: para onde vai o orçamento?

Os preços mudam o tempo todo conforme o vendedor e o câmbio, então não citamos valores; em vez disso, mostramos quais itens ocupam o orçamento e onde dá para economizar. A regra geral é: os módulos eletrônicos (L298N, HC-05, resistores) são baratos, enquanto a maior parte do orçamento vai para a placa, o kit de chassi e, sobretudo, as baterias e o carregador. A bateria é o último lugar para economizar: boas células 18650 podem ser recarregadas centenas de vezes e reaproveitadas em todos os projetos de robô que você fizer depois.

ItemFaixa de preçoDica de economia
Kit de chassi (motores e rodas incluídos)MédioUm kit costuma sair mais barato que comprar motores, rodas e roda boba separadamente
Arduino UnoMédio (clone) – alto (original)Uma placa clone serve para aprender; você também pode reaproveitar o Uno ou o Nano que já tem
Driver de motor L298NBaixoUm módulo aciona dois motores; um basta também para 4WD
HC-05 / HC-06Baixo – médioSe você só vai dirigir pelo celular, um HC-06 basta
2× células 18650 + carregadorMaior itemCélulas muito baratas com “9900 mAh” no rótulo costumam ser falsas; não economize aqui
Fios, resistores, capacitores, parafusosBaixoA maioria já vem nos kits iniciantes
Se você já tem um kit Arduino iniciante, a placa, os jumpers e os resistores estão garantidos; você só precisa do kit de chassi, de um L298N, de um HC-05 e das baterias. Os “kits de carrinho inteligente” prontos, que vêm com tudo em uma caixa, são práticos porque trazem a própria placa de motor e código pronto, mas custam mais e tiram a chance de aprender a ligação.

2WD ou 4WD?

Característica2WD (2 motores + roda boba)4WD (4 motores)
CurvasGira no lugar, de forma fechada e fácilFaz curvas arrastando as rodas de lado (skid steer); tem dificuldade em tapetes
Consumo de correnteCerca de 0,3–0,6 A andandoCerca do dobro
Duração da bateriaMaiorMenor
Terreno irregularA roda boba pode enroscar em bordasMelhor aderência
Andar retoA roda boba pode tirar o carrinho do rumo quando giraMais estável
Ligação no L298NCada motor no seu próprio canalOs dois motores de cada lado em paralelo em um canal
Melhor paraUm primeiro carrinho, um robô seguidor de linhaAmbientes externos, cargas mais pesadas

Recomendamos 2WD para o seu primeiro carrinho: é mais barato, consome menos corrente, gira fácil no lugar e combina melhor com projetos seguintes, como um robô seguidor de linha. Se você montar um 4WD, ligue os dois motores de cada lado em paralelo nos mesmos terminais OUT e confira se os dois giram no mesmo sentido. Um canal do L298N passa então a carregar a corrente de dois motores; isso não é problema andando normalmente, mas, quando as rodas travam, o limite de 2 A por canal pode ser ultrapassado e a proteção térmica do driver corta os motores.

Alimentação: por que duas células 18650?

A maioria dos problemas de carrinhos robô vem da bateria errada. A fonte certa precisa atender duas condições ao mesmo tempo: deixar tensão suficiente para os motores depois da perda do L298N e não desabar quando os motores puxam ampères na arrancada. Duas células Li-ion 18650 em série (2S) dão 8,4 V totalmente carregadas e 7,4 V em média, e fornecem vários ampères com folga. O Arduino Uno recomenda 7–12 V na entrada VIN, então o mesmo pacote pode alimentar os motores e o Arduino. Com células de 2500 mAh, um carrinho 2WD que consome em média 0,8 A andando (motores mais placas) funciona por cerca de 3 horas na teoria; como você nunca descarrega o pacote por completo, 2–2,5 horas é um número mais realista. Para calcular com os seus valores, use a ferramenta Duração da bateria.

Célula recarregável Li-ion 18650
Célula Li-ion 18650: 18 mm de diâmetro e 65 mm de comprimento; 4,2 V quando cheia e 3,6–3,7 V em média. Duas delas em série formam o pacote ideal de 7,4 V para um carrinho robô.
Fonte de energiaTensãoCapacidade de correntePara um carrinho robô
Bateria de 9 V (PP3)9 VMuito baixaNão serve; a causa mais comum de resets
4× AA alcalinas6 V (cai rápido com carga)MédiaFraco; só cerca de 4 V chegam aos motores depois do L298N
4× AA NiMH (recarregáveis)4,8 VBoaTensão insuficiente com o L298N
2× Li-ion 18650 (2S)7,4 V (8,4 V cheia)Alta (vários ampères)Melhor escolha
3× Li-ion 18650 (3S)11,1 V (12,6 V cheia)AltaDemais para motores TT; passa do limite de 12 V do jumper de 5V
Power bank USB5 VBoaSó para alimentar o Arduino separadamente
Células Li-ion são potentes, mas exigem cuidado. Confira duas vezes a orientação do positivo e do negativo ao encaixar as células; uma 18650 encaixada ao contrário ou em curto esquenta muito e pode causar incêndio. A tensão por célula nunca deve cair abaixo de 3,0 V; carregue quando o carrinho começar a ficar lento (cerca de 6,6 V no pacote). Os módulos TP4056 só carregam uma célula e não conseguem carregar diretamente um pacote em série; tire as células do suporte, carregue-as em um carregador de 18650 e nunca as deixe carregando sem supervisão.

Em vez de adivinhar quanta carga resta, você pode medir. Ligue o positivo da bateria (depois da chave) ao A0 através de um divisor de tensão feito com dois resistores de 10 kΩ: um pacote de 8,4 V aparece como 4,2 V no A0, abaixo do limite de leitura de 5 V do Arduino. O divisor consome só cerca de 0,4 mA, então não afeta a duração da bateria.

C++ (Arduino IDE)
1// Pil + (anahtardan sonra) → 10 kΩ → A0 → 10 kΩ → GND / battery + (after the switch) → 10 kΩ → A0 → 10 kΩ → GND
2const float DIVIDER = 2.0;   // iki eşit direnç gerilimi yarıya böler / two equal resistors halve the voltage
3
4void setup() {
5  Serial.begin(9600);
6}
7
8void loop() {
9  float v = analogRead(A0) * 5.0 / 1023.0 * DIVIDER;
10  Serial.print(F("Pil / Battery: "));
11  Serial.print(v, 2);
12  Serial.println(F(" V"));
13  if (v < 6.6) Serial.println(F("Sarj et / Charge now"));   // hücre başına 3,3 V / 3.3 V per cell
14  delay(1000);
15}

Montagem passo a passo

  1. Tire o papel protetor das peças de acrílico. Se os motores vieram sem fios, solde dois fios em cada motor e reforce as soldas com cola quente; um fio de motor que se solta com a vibração é o defeito mais comum.
  2. Fixe os motores na parte de baixo do chassi com os suportes de acrílico em forma de T e os parafusos M3 longos do kit. Os dois eixos dos motores precisam ficar alinhados, e os terminais dos fios dos motores devem ficar virados para dentro.
  3. Se pretende usar os discos de encoder, encaixe-os agora no lado de dentro do eixo do motor; depois que as rodas estiverem colocadas, fica difícil.
  4. Monte a roda boba no meio da outra ponta do chassi usando espaçadores. Escolha uma altura de espaçador que deixe o chassi paralelo ao chão.
  5. Empurre as rodas até o fim, alinhando-as com o eixo em forma de D; uma roda frouxa faz o carrinho desviar o tempo todo.
  6. Coloque o suporte de baterias com fita dupla face ou velcro em um lugar onde o peso fique perto do eixo das rodas. Se a maior parte do peso ficar sobre a roda boba, as rodas de tração vão patinar.
  7. Monte o Arduino e o L298N no andar de cima com espaçadores de plástico. Você deve alcançar com facilidade a porta USB do Arduino, e o dissipador do L298N deve ficar ao ar livre; garanta que parafusos de metal não encostem nas soldas embaixo das placas.
  8. Ligue a chave em série com o fio positivo da bateria para poder ligar e desligar o carrinho sem tirar as células.
  9. Torça juntos os dois fios de cada motor no caminho até o L298N, mantenha todos os fios curtos e prenda-os com abraçadeiras. Antes de colocar as células, confira com um multímetro que não há curto-circuito entre os terminais da bateria.
Antes de montar os motores no chassi, encoste por um instante os terminais de cada motor em 2 pilhas AA para conferir o sentido de rotação e marque os fios. Se você marcar os dois motores de modo que “fio vermelho no positivo significa para a frente”, não vai errar o sentido na ligação.

Esquema de ligação

Pense na ligação em duas partes: o lado de potência (bateria, chave, L298N, motores) e o lado de sinal (os fios finos do Arduino até o L298N e o HC-05). Tire os pequenos jumpers dos pinos ENA e ENB do L298N; vamos ligar esses pinos às saídas PWM do Arduino para definir a velocidade no código. Deixe o jumper de 5V do L298N no lugar: como o pacote fica abaixo de 12 V, o regulador da própria placa alimenta a lógica do driver.

Módulo driver de motor L298N de dois canais
Driver de motor L298N: os motores vão nos bornes azuis das laterais e a bateria no borne de três vias da frente; os pinos ENA, IN1–IN4 e ENB vão ao Arduino.
Terminal do L298NLigação
OUT1, OUT2Motor esquerdo (no 4WD, os dois motores esquerdos em paralelo)
OUT3, OUT4Motor direito (no 4WD, os dois motores direitos em paralelo)
12VPositivo da bateria através da chave
GNDNegativo da bateria e pino GND do Arduino (GND comum)
5VFica desligado com o Arduino Uno; alimenta a placa com ESP32 e Pico
Jumper de 5VFica no lugar (bateria abaixo de 12 V)
Jumpers de ENA e ENBRetirados; os pinos vão às saídas PWM do Arduino
LigaçãoArduino UnoESP32Raspberry Pi Pico
ENA do L298N (velocidade do motor esquerdo)D5 (PWM)GPIO 25GP15
IN1 do L298ND7GPIO 27GP14
IN2 do L298ND8GPIO 33GP13
ENB do L298N (velocidade do motor direito)D6 (PWM)GPIO 26GP10
IN3 do L298ND9GPIO 32GP12
IN4 do L298ND4GPIO 4GP11
TXD do HC-05D10 (RX da SoftwareSerial)Não precisa (Bluetooth embutido)GP1 (RX da UART0)
RXD do HC-05D11, através de um divisor de 1 kΩ / 2 kΩNão precisaGP0 (TX da UART0), direto
VCC do HC-055VNão precisaSaída 5V do L298N
Alimentação da placaVIN ← positivo da bateria depois da chave5V (VIN) ← saída 5V do L298NVSYS ← saída 5V do L298N
GNDComum com o GND do L298N e o negativo da bateriaComumComum
Nunca quebre três regras: todos os GNDs (negativo da bateria, L298N, Arduino, HC-05) precisam estar ligados entre si; os motores nunca podem ser alimentados pelo pino 5V do Arduino; e a saída 5V do L298N não pode ir ao pino VIN do Arduino. O VIN precisa de pelo menos 7 V; com 5 V, o regulador do Arduino não funciona direito e a placa fica instável. O pino RXD do HC-05 é uma entrada de 3,3 V; baixe o sinal TX de 5 V do Uno com um divisor de 1 kΩ e 2 kΩ: D11 → 1 kΩ → RXD, RXD → 2 kΩ → GND (5 V × 2/3 ≈ 3,3 V).

Escolhemos D5 e D6 como pinos de velocidade de propósito. No Uno, a biblioteca Servo desativa o PWM nos pinos 9 e 10, e a função tone() o desativa nos pinos 3 e 11. Com ENA e ENB em 5 e 6, o controle de velocidade dos motores continua funcionando quando você acrescentar um servo ou um buzzer depois. D2 e D3 ficam reservados para encoders porque suportam interrupções. Você pode ver a disposição dos pinos da sua placa na ferramenta Pinagem.

Primeiro sketch: para a frente, para trás, esquerda e direita

Antes de passar para o Bluetooth, vamos testar os motores e a ligação sozinhos. O coração do código é a função drive(left, right): ela recebe a velocidade de cada motor separadamente, de -255 a 255, em que um valor positivo significa para a frente, um negativo para trás e zero, parado. Explicamos como o valor de velocidade vira tensão em O que é PWM?. Antes de carregar, coloque o carrinho em cima de uma caixa para que as rodas girem livres; a espera de 3 segundos no setup() dá tempo para isso.

C++ (Arduino IDE)
1// Sol motor / left motor: ENA=5, IN1=7, IN2=8 — Sağ motor / right motor: ENB=6, IN3=9, IN4=4
2const int ENA = 5, IN1 = 7, IN2 = 8;
3const int ENB = 6, IN3 = 9, IN4 = 4;
4
5const int SPEED = 180;   // temel hız 0-255 / base speed 0-255
6const int TRIM = 0;      // % düzeltme: + sol, - sağ motoru yavaşlatır / % trim: + slows left, - slows right
7
8void drive(int left, int right) {               // her biri -255 … 255 / each -255 … 255
9  if (TRIM > 0) left = left * (100 - TRIM) / 100;
10  if (TRIM < 0) right = right * (100 + TRIM) / 100;
11  digitalWrite(IN1, left > 0);  digitalWrite(IN2, left < 0);
12  digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
13  analogWrite(ENA, abs(left));
14  analogWrite(ENB, abs(right));
15}
16
17void forward()   { drive(SPEED, SPEED); }
18void backward()  { drive(-SPEED, -SPEED); }
19void turnLeft()  { drive(-SPEED, SPEED); }     // yerinde sola / spin left in place
20void turnRight() { drive(SPEED, -SPEED); }     // yerinde sağa / spin right in place
21void stopCar()   { drive(0, 0); }
22
23void setup() {
24  int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
25  for (int p : pins) pinMode(p, OUTPUT);
26  stopCar();
27  delay(3000);             // tekerlekleri kaldırmak için zaman / time to lift the wheels
28}
29
30void loop() {
31  forward();   delay(1500);
32  stopCar();   delay(500);
33  backward();  delay(1500);
34  stopCar();   delay(500);
35  turnLeft();  delay(600);
36  stopCar();   delay(500);
37  turnRight(); delay(600);
38  stopCar();   delay(2000);
39}
MovimentoMotor esquerdoMotor direitoCódigo
Para a frentePara a frentePara a frentedrive(180, 180)
Para trásPara trásPara trásdrive(-180, -180)
Girar para a esquerda no lugarPara trásPara a frentedrive(-180, 180)
Girar para a direita no lugarPara a frentePara trásdrive(180, -180)
Curva aberta à esquerdaPara a frente devagarPara a frentedrive(90, 180)
PararParaParadrive(0, 0)

Com as rodas no ar, o carrinho deve ir para a frente, para trás, para a esquerda e para a direita, um de cada vez. Se uma roda girar no sentido errado, não mude o código; troque os dois fios daquele motor nos terminais OUT do L298N. Se as duas rodas girarem no sentido errado, troque os fios dos dois motores. Se os motores zumbirem mas não girarem, o valor de SPEED está baixo demais: a maioria dos motores TT precisa de um valor PWM de pelo menos uns 80–120 para começar a se mover, e esse limite sobe conforme a bateria descarrega.

Controle por Bluetooth pelo celular (HC-05)

O HC-05 funciona como um cabo serial sem fio entre o celular e o Arduino: o app no celular envia uma letra, o Arduino a lê e faz o movimento correspondente. A maioria dos apps de controle que você encontra na Play Store buscando “Bluetooth RC Car” ou “Bluetooth RC Controller” envia F para a frente, B para trás, L para a esquerda, R para a direita e S para parar quando você solta um botão; alguns também usam G, I, H e J para as diagonais e 0–9 mais q para a velocidade. Os pinos do módulo, os padrões do LED e os comandos AT estão em módulo Bluetooth HC-05.

Módulo Bluetooth HC-05
HC-05: conecta ao celular por Bluetooth clássico (SPP); a velocidade padrão é 9600 baud e o PIN de pareamento é 1234 ou 0000.
  1. A chave do carrinho pode ficar desligada enquanto você carrega o sketch abaixo; o Arduino e o HC-05 são alimentados pelo USB. Se o LED do HC-05 piscar rápido, o módulo está esperando uma conexão.
  2. Encontre o HC-05 nas configurações de Bluetooth do seu celular Android e faça o pareamento com o PIN 1234 (ou 0000, se não der certo).
  3. Abra o app de controle, conceda as permissões de Bluetooth e de dispositivos por perto e selecione o HC-05 na lista de dispositivos. Depois de conectado, o LED do módulo dá duas piscadas curtas a cada dois segundos.
  4. Mantenha o Arduino ligado pelo USB, abra o Monitor Serial em 9600 baud e aperte os botões no app. A letra que cada botão envia aparece na tela; se o seu app enviar letras diferentes, mude as linhas case no código para combinar.
  5. Desconecte o cabo USB, ligue a chave, coloque o carrinho no chão e dirija.
C++ (Arduino IDE)
1#include <SoftwareSerial.h>
2
3SoftwareSerial bt(10, 11);               // RX, TX → HC-05 TXD, RXD (RXD bölücüyle / RXD via divider)
4
5const int ENA = 5, IN1 = 7, IN2 = 8;     // sol motor / left motor
6const int ENB = 6, IN3 = 9, IN4 = 4;     // sağ motor / right motor
7const int TRIM = 0;                      // % düzeltme / % trim
8const unsigned long TIMEOUT = 600;       // ms; 0 = kapalı / 0 = disabled
9
10int speed = 200;                         // 0-255
11unsigned long lastCmd = 0;
12
13void drive(int left, int right) {
14  if (TRIM > 0) left = left * (100 - TRIM) / 100;
15  if (TRIM < 0) right = right * (100 + TRIM) / 100;
16  digitalWrite(IN1, left > 0);  digitalWrite(IN2, left < 0);
17  digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
18  analogWrite(ENA, abs(left));
19  analogWrite(ENB, abs(right));
20}
21
22void setup() {
23  int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
24  for (int p : pins) pinMode(p, OUTPUT);
25  drive(0, 0);
26  Serial.begin(9600);                    // gelen harfleri görmek için / to see incoming letters
27  bt.begin(9600);                        // HC-05 veri modu hızı / HC-05 data mode baud rate
28}
29
30void loop() {
31  if (bt.available()) {
32    char c = bt.read();
33    Serial.println(c);
34    lastCmd = millis();
35    int half = speed / 2;
36    switch (c) {
37      case 'F': drive(speed, speed);   break;   // ileri / forward
38      case 'B': drive(-speed, -speed); break;   // geri / backward
39      case 'L': drive(-speed, speed);  break;   // yerinde sola / spin left
40      case 'R': drive(speed, -speed);  break;   // yerinde sağa / spin right
41      case 'G': drive(half, speed);    break;   // ileri-sol / forward-left
42      case 'I': drive(speed, half);    break;   // ileri-sağ / forward-right
43      case 'H': drive(-half, -speed);  break;   // geri-sol / back-left
44      case 'J': drive(-speed, -half);  break;   // geri-sağ / back-right
45      case 'S': drive(0, 0);           break;   // dur / stop
46      case 'q': speed = 255;           break;   // tam hız / full speed
47      default:
48        if (c >= '0' && c <= '9') speed = map(c - '0', 0, 9, 100, 240);   // hız kademesi / speed level
49    }
50  }
51  if (TIMEOUT > 0 && millis() - lastCmd > TIMEOUT) drive(0, 0);   // komut yoksa dur / no command: stop
52}
LetraMovimentoMotor esquerdo / direito
FPara a frente+velocidade / +velocidade
BPara trás−velocidade / −velocidade
LGirar para a esquerda−velocidade / +velocidade
RGirar para a direita+velocidade / −velocidade
G, IFrente-esquerda, frente-direitaUm lado na metade da velocidade
H, JTrás-esquerda, trás-direitaUm lado na metade da velocidade
SParar0 / 0
0–9, qNível de velocidade0 → 100, 9 → 240, q → 255

O TIMEOUT do código é um recurso de segurança: esses apps ficam enviando a mesma letra enquanto você segura um botão, então, se nenhuma letra chegar por 600 ms, o código entende que a conexão caiu e para o carrinho. Assim o carrinho não continua indo em direção à parede quando o celular sai do alcance ou o app fecha. Se o seu app enviar a letra só uma vez por toque no botão, o carrinho vai parar depois de 600 ms; nesse caso, coloque TIMEOUT em 0 para desativar esse recurso. Também não usamos delay() em nenhum lugar do loop(); esperas longas fazem os comandos atrasarem, e você descobre por quê em millis() vs delay().

O HC-05 e o HC-06 usam Bluetooth clássico, então não funcionam com iPhone; o iOS não permite esse tipo de conexão serial. Se quiser dirigir com um iPhone, use um módulo BLE como o HM-10 ou um ESP32 com BLE. Se quiser criar o seu próprio app de controle, dê uma olhada no guia Bluetooth do Arduino com App Inventor.

O carrinho não anda reto: causas e soluções

Se o carrinho desvia devagar para um lado mesmo que você dê o mesmo valor PWM de “para a frente” aos dois motores, não se preocupe; esse é o problema mais comum de carrinhos robô. Motores baratos com redução giram em velocidades diferentes mesmo com a mesma tensão: diferenças no atrito das engrenagens, nas escovas e nos ímãs deixam cada motor um pouco diferente. Some uma roda frouxa, uma roda boba que fica girando ou peso concentrado de um lado, e um desvio de 20–30 cm em 2 metros é perfeitamente normal. Corrija primeiro as causas mecânicas e depois ajuste a diferença que sobrar no software.

SintomaCausa provávelSolução
Sempre desvia para o mesmo ladoOs motores giram em velocidades diferentesCorreção por software com TRIM, ou encoders
Dá uma guinada na arrancada e depois se endireitaUm motor começa mais tarde, ou a roda boba giraPartida suave; roda boba de esfera no lugar da giratória
O desvio muda a cada vezRoda frouxa, pneu patinando ou suporte do motor tortoEncaixe a roda até o fim no eixo, aperte os parafusos
Gira no lugar em vez de ir para a frenteOs fios de um motor estão invertidosTroque os fios desse motor no terminal OUT
O desvio aumenta conforme a bateria descarregaA diferença entre os motores cresce com tensão baixaCarregue a bateria; ajuste o TRIM com a bateria cheia
Puxa para um lado conforme aceleraO peso está de um ladoMova a bateria e as placas para o meio, perto do eixo das rodas

Depois de resolver os problemas mecânicos, faça o ajuste fino no software. A constante TRIM do código diminui em uma porcentagem a velocidade do motor mais rápido: um valor positivo deixa o motor esquerdo mais lento, um negativo, o direito. Calibre assim:

  1. Carregue totalmente as células; calibrar com a bateria cheia dá resultados consistentes.
  2. Cole no chão uma faixa reta de fita de 2 metros e coloque o carrinho no início, apontando ao longo da fita.
  3. No loop() do primeiro sketch, deixe só forward() e uma espera de 3 segundos e deixe o carrinho andar.
  4. Se o carrinho desviar para a direita, o motor esquerdo está mais rápido: aumente o TRIM em 3; se desviar para a esquerda, diminua o TRIM em 3.
  5. Repita até o desvio em 2 metros cair para poucos centímetros e depois copie o mesmo valor de TRIM para o sketch do Bluetooth.
  6. Calibre na velocidade que você mais usa; a diferença entre os motores muda um pouco com a velocidade.

O próximo nível para andar perfeitamente reto e medir distância é o encoder. Você encaixa os discos de 20 fendas do kit nos eixos dos motores e conta cada fenda com um sensor de velocidade de fenda baseado no LM393. Ligue as saídas dos sensores aos pinos D2 e D3, que aceitam interrupções, e compare a contagem de pulsos das duas rodas: se o lado esquerdo se adiantar, diminua um pouco a velocidade do motor esquerdo. Esse controle proporcional (P) simples mantém o carrinho reto independentemente do nível da bateria e do piso. Uma roda de 65 mm percorre cerca de 20,4 cm por volta, então cada pulso significa aproximadamente 1 cm de deslocamento. Explicamos como as interrupções funcionam em Interrupções no Arduino.

O Arduino reinicia quando os motores ligam

Se o Arduino reinicia ou o HC-05 perde a conexão (o LED volta a piscar rápido) quando o carrinho arranca, muda de sentido ou bate em um obstáculo, o problema quase sempre está na alimentação. Na arrancada, os dois motores juntos podem puxar 2–3 A; uma bateria fraca não consegue fornecer isso e a tensão dela desaba por um instante. O processador do Uno se reinicia por segurança quando a alimentação cai abaixo de 2,7 V (brown-out). Some a isso o ruído elétrico das escovas dos motores e a queda de tensão em fios finos. Estas são as soluções, começando pela mais eficaz:

  • Troque a bateria: use duas células 18650 carregadas em vez de uma bateria de 9 V ou de pilhas AA cansadas; a maioria dos problemas acaba aqui.
  • Use o caminho de alimentação certo: alimente o Arduino pela bateria através do VIN; não ligue a saída 5V do L298N ao VIN.
  • Capacitores nos motores: solde um capacitor cerâmico de 100 nF entre os dois terminais de cada motor; ele suprime o ruído das escovas na origem.
  • Capacitor de reserva: ligue um capacitor eletrolítico de 470–1000 µF aos terminais 12V e GND do L298N (terminal positivo no 12V). Ele cobre a demanda de corrente momentânea na arrancada.
  • Partida suave: em vez de saltar para 255, aumente a velocidade passo a passo, como mostrado abaixo; o pico de corrente fica menor.
  • Pare antes de dar ré: passar direto de para a frente para trás leva a corrente do motor ao pico; pare por 100–200 ms antes de mudar o sentido.
  • Fios de potência grossos e curtos: não use jumpers nem protoboard entre a bateria e o L298N; use fio de pelo menos 0,5 mm² e bornes com parafuso.
  • Fontes separadas: se o problema continuar, alimente o Arduino com um power bank e os motores com a bateria e ligue os dois GNDs.
C++ (Arduino IDE)
1// Yumuşak kalkış: ilk koddaki drive() ile kullan / soft start: use with drive() from the first sketch
2void rampTo(int target) {
3  for (int s = 60; s < target; s += 20) {
4    drive(s, s);
5    delay(15);              // yaklaşık 10 adımda tam hız / full speed in about 10 steps
6  }
7  drive(target, target);
8}
9
10// Kullanım: forward() yerine rampTo(SPEED) / usage: rampTo(SPEED) instead of forward()
Um jeito fácil de saber se o problema é de alimentação ou de código: desligue o fio do VIN, mantenha o Arduino alimentado pelo USB do computador (deixe a ligação do GND no lugar) e faça os motores funcionarem com a bateria. Se os resets pararem, o problema com certeza está na alimentação. Ligar um multímetro entre VIN e GND e observar a tensão quando o carrinho arranca também mostra a queda diretamente. Para outras causas, veja Arduino reiniciando sozinho.

Carrinho robô com ESP32 e Raspberry Pi Pico

O ESP32 tem Bluetooth clássico embutido, então você não precisa de um HC-05: a biblioteca BluetoothSerial cria a mesma conexão serial com o celular, e os apps de controle acima funcionam sem mudanças. As entradas do L298N entendem como HIGH qualquer valor acima de cerca de 2,3 V, então os sinais de 3,3 V do ESP32 bastam. Alimente a placa ESP32 pela saída 5V do L298N no pino 5V (VIN) da placa; não ligue a bateria direto nesse pino. Este código não compila para o ESP32-S3 e o ESP32-C3, porque eles só têm BLE.

C++ (Arduino IDE)
1#include "BluetoothSerial.h"
2
3BluetoothSerial bt;
4
5const int ENA = 25, IN1 = 27, IN2 = 33;   // sol motor / left motor
6const int ENB = 26, IN3 = 32, IN4 = 4;    // sağ motor / right motor
7
8int speed = 200;                          // 0-255
9unsigned long lastCmd = 0;
10
11void drive(int left, int right) {
12  digitalWrite(IN1, left > 0);  digitalWrite(IN2, left < 0);
13  digitalWrite(IN3, right > 0); digitalWrite(IN4, right < 0);
14  analogWrite(ENA, abs(left));
15  analogWrite(ENB, abs(right));
16}
17
18void setup() {
19  int pins[] = {ENA, IN1, IN2, ENB, IN3, IN4};
20  for (int p : pins) pinMode(p, OUTPUT);
21  drive(0, 0);
22  bt.begin("BlueGrays-Car");              // telefonda görünecek ad / name shown on the phone
23}
24
25void loop() {
26  if (bt.available()) {
27    char c = bt.read();
28    lastCmd = millis();
29    switch (c) {
30      case 'F': drive(speed, speed);   break;   // ileri / forward
31      case 'B': drive(-speed, -speed); break;   // geri / backward
32      case 'L': drive(-speed, speed);  break;   // yerinde sola / spin left
33      case 'R': drive(speed, -speed);  break;   // yerinde sağa / spin right
34      case 'S': drive(0, 0);           break;   // dur / stop
35      case 'q': speed = 255;           break;   // tam hız / full speed
36      default:
37        if (c >= '0' && c <= '9') speed = map(c - '0', 0, 9, 100, 240);
38    }
39  }
40  if (millis() - lastCmd > 600) drive(0, 0);    // komut yoksa dur / no command: stop
41}

O Raspberry Pi Pico padrão não tem Bluetooth, então você liga o HC-05 aos pinos da UART0. Como o Pico trabalha em 3,3 V, desta vez não é preciso divisor de tensão. Alimente o Pico pelo pino VSYS e o HC-05 direto pela saída 5V do L298N; funcionando com baterias, sem USB, não há tensão no pino VBUS. No código do Pico, a velocidade é dada em porcentagem, de -100 a 100:

MicroPython
1from machine import Pin, PWM, UART
2import time
3
4bt = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))   # GP0 → HC-05 RXD, GP1 ← HC-05 TXD
5
6ena = PWM(Pin(15)); ena.freq(1000)                  # sol motor hızı / left motor speed
7enb = PWM(Pin(10)); enb.freq(1000)                  # sağ motor hızı / right motor speed
8in1, in2 = Pin(14, Pin.OUT), Pin(13, Pin.OUT)
9in3, in4 = Pin(12, Pin.OUT), Pin(11, Pin.OUT)
10
11def drive(left, right):                             # -100 … 100 (%)
12    in1.value(left > 0); in2.value(left < 0)
13    in3.value(right > 0); in4.value(right < 0)
14    ena.duty_u16(int(abs(left) * 655))
15    enb.duty_u16(int(abs(right) * 655))
16
17speed = 80
18last = time.ticks_ms()
19drive(0, 0)
20
21while True:
22    if bt.any():
23        c = bt.read(1)
24        last = time.ticks_ms()
25        if c == b'F':   drive(speed, speed)          # ileri / forward
26        elif c == b'B': drive(-speed, -speed)        # geri / backward
27        elif c == b'L': drive(-speed, speed)         # yerinde sola / spin left
28        elif c == b'R': drive(speed, -speed)         # yerinde sağa / spin right
29        elif c == b'S': drive(0, 0)                  # dur / stop
30        elif c == b'q': speed = 100                  # tam hız / full speed
31        elif c and 48 <= c[0] <= 57:                 # '0'…'9' hız kademesi / speed level
32            speed = 40 + (c[0] - 48) * 6
33    if time.ticks_diff(time.ticks_ms(), last) > 600:
34        drive(0, 0)                                  # komut yoksa dur / no command: stop

Próximos passos: melhore o seu carrinho

  • Robô que desvia de obstáculos: acrescente na frente um sensor de distância HC-SR04 e um servo motor que o vira para a esquerda e para a direita; detalhes no guia Robô que desvia de obstáculos.
  • Robô seguidor de linha: coloque 2–3 sensores infravermelhos TCRT5000 embaixo da frente e siga uma linha preta no chão; veja Robô seguidor de linha.
  • Controle com joystick: monte um controle de verdade, sem celular, com um segundo Arduino, um módulo joystick e um nRF24L01.
  • Controle infravermelho: dirija com os botões do controle da TV; associe os códigos de Receptor IR + controle remoto aos comandos de direção.
  • Direção por Wi-Fi: use um ESP32 para servir uma página de controle que abre no navegador do celular; o guia Servidor web e WebSocket com ESP32 cobre o básico.
  • Encoders e distância: use sensores de velocidade para andar exatamente 1 metro e girar exatamente 90 graus; essa é a base dos robôs que resolvem labirintos.
  • Braço robótico: acrescente em cima do carrinho um pequeno braço robótico com servos para carregar objetos.
Sensor de distância HC-SR04
Sensor de distância HC-SR04
Sensor infravermelho TCRT5000
Sensor infravermelho TCRT5000
Servo SG90
Servo SG90

Erros comuns e soluções

  • Nenhum motor gira: os GNDs não estão em comum, a chave está desligada, os jumpers de ENA e ENB foram retirados mas os pinos não estão ligados, ou a bateria está descarregada.
  • O LED do L298N acende, mas os motores só zumbem: o valor PWM está abaixo do limite de partida do motor ou a tensão da bateria está baixa; aumente a velocidade e carregue a bateria.
  • O sketch não carrega: pode estar selecionada a porta ou a placa errada; se você ligou o HC-05 nos pinos 0 e 1, desligue-o durante o carregamento. Outras causas em Erro ao carregar código no Arduino.
  • O celular vê o HC-05, mas não conecta: o módulo está conectado a outro celular, o app não recebeu a permissão de “dispositivos por perto” ou o PIN de pareamento está errado.
  • O carrinho reage aos comandos com atraso: há um delay() no loop() ou muita coisa sendo mostrada no Monitor Serial; faça as esperas com millis().
  • O dissipador do L298N esquenta muito: as rodas estão travadas ou, em um carrinho 4WD, a corrente por canal está alta demais; procure atrito mecânico.
  • O carrinho dá um tranco ao ligar: os pinos ficam indefinidos por um instante na inicialização; defina os pinos como saída e chame drive(0, 0) logo nas primeiras linhas do setup().

Um carrinho robô com Arduino é um ótimo ponto de partida que ensina controle de motores, gestão de energia, comunicação sem fio e depuração em um único projeto. Quando terminar, você vai ter um chassi que fica um pouco mais inteligente a cada sensor novo. No app BlueGrays você encontra passo a passo, com esquemas do circuito e código, os projetos do carrinho controlado por Bluetooth com L298N, do robô que desvia de obstáculos e da detecção de superfície preta e branca com TCRT5000.

Perguntas frequentes

Do que eu preciso para montar um carrinho com Arduino e quanto custa?

Para um carrinho básico com Bluetooth, você precisa de um kit de chassi 2WD (2 motores TT, rodas, uma roda boba), um Arduino Uno, um driver de motor L298N, um módulo Bluetooth HC-05, duas células 18650 com suporte e alguns jumpers. Os preços variam conforme o vendedor; os módulos são baratos, e a maior parte do orçamento vai para a placa, o kit de chassi e as baterias com carregador. Se você já tem um kit iniciante, o custo cai bastante.

Que bateria devo usar em um carrinho robô com Arduino?

A melhor opção são duas células Li-ion 18650 em série: elas dão 7,4 V, deixam 5–6 V para os motores depois da perda de cerca de 2 V do L298N e fornecem a corrente alta necessária na arrancada. Uma bateria de 9 V (PP3) não fornece corrente suficiente e causa resets, enquanto 4 pilhas AA deixam os motores lentos com um L298N.

Por que o meu carrinho com Arduino não anda reto?

Motores baratos com redução giram em velocidades diferentes mesmo com o mesmo valor PWM, e rodas frouxas, a roda boba e o peso desigual aumentam o desvio. Corrija primeiro os problemas mecânicos e depois deixe o motor mais rápido um pouco mais lento com um valor de trim no código. Para andar realmente reto, você precisa de encoders para medir e igualar a velocidade das duas rodas.

Por que o meu Arduino reinicia quando os motores ligam?

Os motores puxam vários ampères na arrancada, e a tensão de uma bateria fraca desaba por um instante; o processador do Uno se reinicia quando a alimentação cai. Use células 18650 carregadas, acrescente capacitores de 100 nF nos terminais dos motores e um capacitor de 470–1000 µF na entrada do L298N e aumente a velocidade aos poucos. Se o problema continuar, alimente o Arduino com uma fonte separada e ligue os GNDs.

Um carrinho com Bluetooth HC-05 funciona com iPhone?

Não. O HC-05 e o HC-06 usam o perfil de porta serial do Bluetooth clássico, e o iOS não deixa apps comuns abrirem esse tipo de conexão. Para controlar o carrinho por um iPhone, use um módulo BLE como o HM-10 ou um ESP32 com BLE; celulares Android se conectam ao HC-05 sem problemas.

Posso usar um shield de motor L293D no lugar do L298N?

Sim. O shield de motor L293D encaixa em cima do Arduino Uno e aciona quatro motores CC, o que simplifica a ligação em carrinhos 4WD. Porém, a corrente contínua dele é de só cerca de 0,6 A por canal, então ele sofre antes do L298N quando os motores travam, e o shield ocupa muitos pinos. Se quiser algo mais eficiente, drivers com MOSFET como o TB6612FNG perdem muito menos tensão.

Ver todos os projetos
Carrinho controlado por Bluetooth com L298N
#80Avançado
Premium

Carrinho controlado por Bluetooth com L298N

Transforme seu celular em um controle remoto e dirija seu próprio carrinho robô. O Arduino recebe os comandos de um aplicativo de controle remoto no celular por meio de um módulo Bluetooth e aciona as

5.0(38)
65
Robô que desvia de obstáculos
#81Avançado
Premium

Robô que desvia de obstáculos

Que tal construir um veículo inteligente que encontra seu próprio caminho? O robô que desvia de obstáculos monitora o ambiente constantemente com o sensor ultrassônico na parte da frente. Ao encontrar

5.0(38)
49
Controle de LED pelo celular via Bluetooth
#34Iniciante
Premium

Controle de LED pelo celular via Bluetooth

Um pequeno ensaio para acender e apagar as luzes do seu quarto pelo celular. O módulo Bluetooth repassa ao Arduino as letras enviadas pelo celular; uma letra acende o LED vermelho, outra acende o verd

4.8(68)
89
Detecção de superfícies pretas e brancas com TCRT5000
#78Intermediário
Premium

Detecção de superfícies pretas e brancas com TCRT5000

Com o pequeno sensor que funciona como o olho dos robôs seguidores de linha, você identifica se o piso é preto ou branco. O TCRT5000 emite luz invisível em direção ao piso e verifica quanto dela é ref

4.7(40)
49
Leitura de reflexão (proximidade) com TCRT5000
#77Intermediário
Premium

Leitura de reflexão (proximidade) com TCRT5000

Com um pequeno sensor que emite luz invisível e mede quanto dela é refletido, você detecta a superfície à frente dele. Quanto mais o sensor se aproxima de um objeto ou de uma superfície clara, mais lu

4.6(33)
43
Medição de distância com HC-SR04 (Monitor Serial)
#27Iniciante

Medição de distância com HC-SR04 (Monitor Serial)

O sensor HC-SR04 funciona como um morcego que se orienta no escuro: emite um som que você não consegue ouvir, escuta o eco e mede a distância até o objeto à sua frente. O Arduino escreve essa distânci

4.6(46)
71
Sensor de estacionamento com HC-SR04
#28Intermediário
Premium

Sensor de estacionamento com HC-SR04

Uma versão em miniatura do sensor de estacionamento de um carro: quanto mais perto um objeto chega, mais rápidos ficam os bipes. O sensor de distância mede a distância até o objeto à sua frente; se el

4.8(64)
85
Uso de servo motor
#35Iniciante
Premium

Uso de servo motor

O braço de um pequeno servo motor gira para três posições em sequência: o início, o meio e o fim do percurso, esperando dois segundos em cada parada. O Arduino informa ao motor em qual ângulo ficar, e

4.7(48)
67