← Sair
Seguidor de Linha · 4 sensores TCRT5000
Modo Bancada · Plugada

Seguidor de Linha · 4 sensores TCRT5000

Seguidor de Linha · 4 sensores TCRT5000

📶 Intermediario · ⏱ 2 a 3 aulas

🎯 O desafio

Construir e programar um robô que segue uma linha usando 4 sensores TCRT5000 e um driver TB6612, corrigindo a rota em tempo real com um PID proporcional-derivativo — calibração, ajuste de ganhos e depuração.

🧰 O que vamos usar

1x Arduino Uno 1x Driver de motor TB6612FNG 4x Sensor de linha TCRT5000 2x Motor DC com caixa de redução 1x Roda + roda boba (esfera) 1x Bateria 9V (ou pack de pilhas) 1x Chassi (impressão 3D) 1x Pista: fita isolante preta sobre fundo branco 1x Jumpers, parafusos e interruptor (opcional)

🔌 Montagem do robô

Placa: Arduino UNO

⬇ baixar SVG
🧰 Montagem do robôPlaca: Arduino UNO · 8 componentes · 16 ligações detectadas do códigoUSBATMEGA328PLARDUINO UNOAREFGND131211109876543210DIGITAL (PWM ~)IOREFRESET3V35VGNDGNDVINPOWERA0A1A2A3A4A5ANALOG INArduino UNOD9 · PWMA (vel. A)D7 · AIN1D8 · AIN2D3 · PWMB (vel. B)D5 · BIN1D4 · BIN2D6 · STBY (habilita)Driver TB6612FNGAO1·AO2Motor DC esquerdoBO1·BO2Motor DC direitoA4 · leitura da linhaSeguidor de Linha(TCRT5000) esquerdoA3 · leitura da linhaSeguidor de Linha(TCRT5000) central…A2 · leitura da linhaSeguidor de Linha(TCRT5000) central…A1 · leitura da linhaSeguidor de Linha(TCRT5000) direitoD13 · emissor infraverm…LEDLEGENDA DOS FIOSDigitalAnalógico (leitura)PWM (velocidade)Saída de motor
🧰 Montagem do robôArduino UNOplaca controladoraSeguidor de Linha…A4Seguidor de Linha…A3Seguidor de Linha…A2Seguidor de Linha…A1LEDD13Driver TB6612FNGD9D7D8D3D5D4D6Motor DC esquerdoAO1AO2Motor DC direitoBO1BO2
💻 O código
aula.ino
/*
 * Seguidor de Linha · 4 sensores TCRT5000 — Arduino UNO
 * Driver: TB6612FNG   |   Sensores: 4x TCRT5000 (lidos como régua QTR)
 * PID proporcional-derivativo simples, sempre avançando.
 * (código original adaptado; comentários traduzidos para o português)
 */

// ===== Pinos do driver TB6612FNG =====
#define PWMA 9   // velocidade do motor A
#define AIN2 8   // direção do motor A
#define AIN1 7   // direção do motor A
#define BIN1 5   // direção do motor B
#define BIN2 4   // direção do motor B
#define PWMB 3   // velocidade do motor B
#define STBY 6   // standby: precisa ficar em HIGH para o driver funcionar

int velocidadeBase = 250;   // velocidade de cruzeiro (0 a 255)

// ===== Ganhos do PID =====
float KP = 0.2;
float KD = 5;

int erro = 0;
int derivada = 0;
int erroAnterior = 0;
float correcao;

#include <QTRSensors.h>

#define NUM_SENSORES 4
#define TIMEOUT 2500
#define PINO_EMISSOR 13   // liga os LEDs infravermelhos dos sensores

QTRSensorsRC qtr(
  (unsigned char[]){18, 17, 16, 15},   // A4, A3, A2, A1
  NUM_SENSORES,
  TIMEOUT,
  PINO_EMISSOR
);

unsigned int leiturasSensores[NUM_SENSORES];
unsigned int posicao = 0;

void setup() {
  Serial.begin(115200);

  pinMode(PWMA, OUTPUT);
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(PWMB, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
  pinMode(STBY, OUTPUT);

  digitalWrite(STBY, HIGH);   // habilita o TB6612

  // Calibração: passe os 4 sensores sobre a linha e o fundo por alguns segundos
  Serial.println("== CALIBRANDO ==");
  digitalWrite(PINO_EMISSOR, HIGH);
  for (int i = 0; i < 400; i++) {
    qtr.calibrate();
    delay(5);
  }
  digitalWrite(PINO_EMISSOR, LOW);
  Serial.println("== PRONTO ==");
}

void loop() {
  posicao = qtr.readLine(leiturasSensores, QTR_EMITTERS_ON, 0);

  // Centro para 4 sensores: faixa 0..3000, centro = 1500
  erro = posicao - 1500;

  // ===== PID =====
  derivada = erro - erroAnterior;
  correcao = (erro * KP) + (derivada * KD);
  correcao = constrain(correcao, -velocidadeBase, velocidadeBase);

  int motorA = velocidadeBase - correcao;
  int motorB = velocidadeBase + correcao;
  motorA = constrain(motorA, 0, 255);
  motorB = constrain(motorB, 0, 255);

  // ===== Sempre para frente, ajustando só a velocidade de cada lado =====
  digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); analogWrite(PWMA, motorA);
  digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMB, motorB);

  erroAnterior = erro;
  delay(5);
}
🔀 Como o programa pensa
graph TD INICIO([INÍCIO]) N1["Esperar 0.005 segundos"] INICIO --> N1 N1 --> N1 style INICIO fill:#fbbf24,stroke:#1e3a8a,color:#1e3a8a
🧱 Em blocos
when green flag clicked
forever
  set [posicao v] to (qtr.readLine(leiturasSensores, QTR_EMITTERS_ON, 0))
  set [erro v] to (posicao - 1500)
  set [derivada v] to (erro - erroAnterior)
  set [correcao v] to ((erro * KP) + (derivada * KD))
  set [correcao v] to (constrain(correcao, -velocidadeBase, velocidadeBase))
  set [motorA v] to (velocidadeBase - correcao)
  set [motorB v] to (velocidadeBase + correcao)
  set [motorA v] to (constrain(motorA, 0, 255))
  set [motorB v] to (constrain(motorB, 0, 255))
  digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); analogWrite(PWMA, motorA) :: custom
  digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMB, motorB) :: custom
  set [erroAnterior v] to (erro)
  wait (0.005) secs
end
🖨️ Peça 3D

Toque para ver em 3D · gire com o dedo.

Chassi do seguidor
🎥 Veja funcionando
🔗 Abrir o vídeo
Pra fechar

Você chegou ao fim! 🎉

O que foi mais difícil? O que você faria diferente? Conte pra turma!

✓ Sair