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.




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.

| Característica | Motor TT amarelo (1:48) |
|---|---|
| Tensão de operação | 3–6 V |
| Relação de redução | 1:48 (engrenagens de plástico) |
| Rotação sem carga | Cerca de 90–120 RPM em 3 V, 200–250 RPM em 6 V |
| Corrente sem carga | Cerca de 150–160 mA |
| Corrente de travamento | Cerca de 1,1–1,5 A |
| Diâmetro da roda (nos kits) | 65 mm |
| Velocidade do carrinho em 6 V | Cerca 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ça | Qtd. | Observação |
|---|---|---|
| Kit de chassi de acrílico para carrinho robô 2WD | 1 | Normalmente traz 2 motores TT, 2 rodas, uma roda boba, uma chave, suportes de motor e parafusos |
| Arduino Uno R3 (um clone serve) + cabo USB | 1 | Um Nano também funciona; os números dos pinos são os mesmos |
| Módulo driver de motor L298N | 1 | 2 A por canal; aciona dois motores de forma independente |
| Módulo Bluetooth HC-05 ou HC-06 | 1 | Para conversar com um celular Android |
| Célula Li-ion 18650 | 2 | Células de marca que fornecem pelo menos 5 A |
| Suporte para 2 baterias 18650 (em série) | 1 | Liga as duas células em série para 7,4 V |
| Carregador de 18650 | 1 | Um 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 + 1 | Divisor de tensão para a entrada RXD do HC-05 |
| Capacitor cerâmico de 100 nF | 2–4 | Nos terminais dos motores, para suprimir ruído |
| Capacitor eletrolítico de 470–1000 µF (16 V ou mais) | 1 | Recomendado; na entrada de alimentação do L298N |
| Abraçadeiras, fita dupla face, espaçadores M3 | Alguns | Para 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.
| Item | Faixa de preço | Dica de economia |
|---|---|---|
| Kit de chassi (motores e rodas incluídos) | Médio | Um kit costuma sair mais barato que comprar motores, rodas e roda boba separadamente |
| Arduino Uno | Mé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 L298N | Baixo | Um módulo aciona dois motores; um basta também para 4WD |
| HC-05 / HC-06 | Baixo – médio | Se você só vai dirigir pelo celular, um HC-06 basta |
| 2× células 18650 + carregador | Maior item | Células muito baratas com “9900 mAh” no rótulo costumam ser falsas; não economize aqui |
| Fios, resistores, capacitores, parafusos | Baixo | A maioria já vem nos kits iniciantes |
2WD ou 4WD?
| Característica | 2WD (2 motores + roda boba) | 4WD (4 motores) |
|---|---|---|
| Curvas | Gira no lugar, de forma fechada e fácil | Faz curvas arrastando as rodas de lado (skid steer); tem dificuldade em tapetes |
| Consumo de corrente | Cerca de 0,3–0,6 A andando | Cerca do dobro |
| Duração da bateria | Maior | Menor |
| Terreno irregular | A roda boba pode enroscar em bordas | Melhor aderência |
| Andar reto | A roda boba pode tirar o carrinho do rumo quando gira | Mais estável |
| Ligação no L298N | Cada motor no seu próprio canal | Os dois motores de cada lado em paralelo em um canal |
| Melhor para | Um primeiro carrinho, um robô seguidor de linha | Ambientes 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.

| Fonte de energia | Tensão | Capacidade de corrente | Para um carrinho robô |
|---|---|---|---|
| Bateria de 9 V (PP3) | 9 V | Muito baixa | Não serve; a causa mais comum de resets |
| 4× AA alcalinas | 6 V (cai rápido com carga) | Média | Fraco; só cerca de 4 V chegam aos motores depois do L298N |
| 4× AA NiMH (recarregáveis) | 4,8 V | Boa | Tensã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) | Alta | Demais para motores TT; passa do limite de 12 V do jumper de 5V |
| Power bank USB | 5 V | Boa | Só para alimentar o Arduino separadamente |
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.
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
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- Ligue a chave em série com o fio positivo da bateria para poder ligar e desligar o carrinho sem tirar as células.
- 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.
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.

| Terminal do L298N | Ligação |
|---|---|
| OUT1, OUT2 | Motor esquerdo (no 4WD, os dois motores esquerdos em paralelo) |
| OUT3, OUT4 | Motor direito (no 4WD, os dois motores direitos em paralelo) |
| 12V | Positivo da bateria através da chave |
| GND | Negativo da bateria e pino GND do Arduino (GND comum) |
| 5V | Fica desligado com o Arduino Uno; alimenta a placa com ESP32 e Pico |
| Jumper de 5V | Fica no lugar (bateria abaixo de 12 V) |
| Jumpers de ENA e ENB | Retirados; os pinos vão às saídas PWM do Arduino |
| Ligação | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| ENA do L298N (velocidade do motor esquerdo) | D5 (PWM) | GPIO 25 | GP15 |
| IN1 do L298N | D7 | GPIO 27 | GP14 |
| IN2 do L298N | D8 | GPIO 33 | GP13 |
| ENB do L298N (velocidade do motor direito) | D6 (PWM) | GPIO 26 | GP10 |
| IN3 do L298N | D9 | GPIO 32 | GP12 |
| IN4 do L298N | D4 | GPIO 4 | GP11 |
| TXD do HC-05 | D10 (RX da SoftwareSerial) | Não precisa (Bluetooth embutido) | GP1 (RX da UART0) |
| RXD do HC-05 | D11, através de um divisor de 1 kΩ / 2 kΩ | Não precisa | GP0 (TX da UART0), direto |
| VCC do HC-05 | 5V | Não precisa | Saída 5V do L298N |
| Alimentação da placa | VIN ← positivo da bateria depois da chave | 5V (VIN) ← saída 5V do L298N | VSYS ← saída 5V do L298N |
| GND | Comum com o GND do L298N e o negativo da bateria | Comum | Comum |
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.
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}| Movimento | Motor esquerdo | Motor direito | Código |
|---|---|---|---|
| Para a frente | Para a frente | Para a frente | drive(180, 180) |
| Para trás | Para trás | Para trás | drive(-180, -180) |
| Girar para a esquerda no lugar | Para trás | Para a frente | drive(-180, 180) |
| Girar para a direita no lugar | Para a frente | Para trás | drive(180, -180) |
| Curva aberta à esquerda | Para a frente devagar | Para a frente | drive(90, 180) |
| Parar | Para | Para | drive(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.

- 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.
- 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).
- 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.
- 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.
- Desconecte o cabo USB, ligue a chave, coloque o carrinho no chão e dirija.
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}| Letra | Movimento | Motor esquerdo / direito |
|---|---|---|
| F | Para a frente | +velocidade / +velocidade |
| B | Para trás | −velocidade / −velocidade |
| L | Girar para a esquerda | −velocidade / +velocidade |
| R | Girar para a direita | +velocidade / −velocidade |
| G, I | Frente-esquerda, frente-direita | Um lado na metade da velocidade |
| H, J | Trás-esquerda, trás-direita | Um lado na metade da velocidade |
| S | Parar | 0 / 0 |
| 0–9, q | Nível de velocidade | 0 → 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 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.
| Sintoma | Causa provável | Solução |
|---|---|---|
| Sempre desvia para o mesmo lado | Os motores giram em velocidades diferentes | Correção por software com TRIM, ou encoders |
| Dá uma guinada na arrancada e depois se endireita | Um motor começa mais tarde, ou a roda boba gira | Partida suave; roda boba de esfera no lugar da giratória |
| O desvio muda a cada vez | Roda frouxa, pneu patinando ou suporte do motor torto | Encaixe a roda até o fim no eixo, aperte os parafusos |
| Gira no lugar em vez de ir para a frente | Os fios de um motor estão invertidos | Troque os fios desse motor no terminal OUT |
| O desvio aumenta conforme a bateria descarrega | A diferença entre os motores cresce com tensão baixa | Carregue a bateria; ajuste o TRIM com a bateria cheia |
| Puxa para um lado conforme acelera | O peso está de um lado | Mova 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:
- Carregue totalmente as células; calibrar com a bateria cheia dá resultados consistentes.
- Cole no chão uma faixa reta de fita de 2 metros e coloque o carrinho no início, apontando ao longo da fita.
- No loop() do primeiro sketch, deixe só forward() e uma espera de 3 segundos e deixe o carrinho andar.
- 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.
- 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.
- 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.
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()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.
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:
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: stopPró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.



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.
Projetos para montar depois desta leitura
Ver todos os projetos
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

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

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

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

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

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

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

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
Mais artigos
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

