← Sair
Robô de Futebol (controle PS2)
RoboFeed · aula plugada

Robô de Futebol (controle PS2)

Robô de Futebol (controle PS2)

🎓 7º ano · 8º ano · 9º ano · 1EM · 2EM · 3EM 🧭 🧭 🧭
Capa da aula
🎯 Nossa missão hoje

O que vamos conseguir fazer

1

Montar e programar um robô de futebol controlado por um controle sem fio (PS2): ler o controle e traduzir os comandos em movimento dos dois motores — frente, trás e giro (direção diferencial).

🧰 O que temos na bancada

Peças e materiais

Arduino Uno Arduino Uno 1×
Driver de motor TB6612 1×
Receptor + controle sem fio PS2 1×
Motor DC com caixa de redução Motor DC com caixa de redução 2×
Rodas (impressão 3D) Rodas (impressão 3D) 2×
Bateria (pack de pilhas ou LiPo) Bateria (pack de pilhas ou LiPo) 1×
Chassi (impressão 3D) Chassi (impressão 3D) 1×
Jumpers e parafusos Jumpers e parafusos 1×
🔌 Como as peças se ligam

O mapa do nosso robô

⬇ baixar SVG
🧰 Montagem do robôPlaca: Arduino Uno · 4 componentes · 16 ligações detectadas do códigoUSBATMEGA328PLARDUINO UNOAREFGND131211109876543210DIGITAL (PWM ~)IOREFRESET3V35VGNDGNDVINPOWERA0A1A2A3A4A5ANALOG INArduino Uno⚡ Barramento de alimentação · 5V (+) / GND (–)D9 · ENA (vel. A)D4 · IN1D3 · IN2D5 · ENB (vel. B)D8 · IN3D7 · IN4L298NSAÍDA ASAÍDA B+12VGND+5VENAIN1IN2IN3IN4ENBPonte H (L298N)OUT1·OUT2Motor DC esquerdoOUT3·OUT4Motor DC direitoA3 · clockA1 · comandoA0 · seleçãoA2 · dadosReceptor PS2 (sem fio)LEGENDA DOS FIOSAlimentação (+5V)Terra (GND)DigitalAnalógico (leitura)Saída de motor
🧰 Montagem do robôArduino Unoplaca controladoraReceptor PS2 (sem fio)A3A1A0A23,3VGNDL298NSAÍDA ASAÍDA B+12VGND+5VENAIN1IN2IN3IN4ENBPonte H (L298N)D9D4D3D5D8D7Motor DC esquerdoOUT1OUT2Motor DC direitoOUT3OUT4

cada fio colorido é uma ligação de verdade — o diagrama completo está na página da aula

Momento 1 de 5

Introdução

Apresente o robô de futebol pilotado por um controle sem fio (PS2). Pergunta: como o controle 'conversa' com o robô e vira movimento? Compare com o seguidor de linha (autônomo) — este é TELEOPERADO.

Momento 2 de 5

Montagem / Hardware

1

Montar o chassi, as rodas e os 2 motores.

Peça impressa em 3D
2

Ligar o driver TB6612 (motor A: AIN1 D4, AIN2 D3, PWMA D9 · motor B: BIN1 D8, BIN2 D7, PWMB D5). O pino STBY vai no 5V para habilitar o driver.

3

Ligar o receptor PS2: CLK A3, CMD A1, ATT A0, DAT A2. ⚠️ Alimente o receptor em 3,3V (NUNCA 5V). Alimentação: bateria na entrada VM do TB6612, o VCC do TB6612 no 5V do Arduino, GND comum.

Placa Arduino (Uno / Nano / Mega)
Momento 3 de 5

Programação

Instalar a biblioteca PS2X. Carregar o código. Explicar a leitura dos joysticks (map, zona morta) e a DIREÇÃO DIFERENCIAL: velocidade do motor A = base − giro, motor B = base + giro. Parear o controle com o receptor.

Momento 4 de 5

Teste e ajustes

Testar a pilotagem. Depurar em equipe: se o robô anda torto, confira/inverta os fios de um motor; ajuste a zona morta; se não responde, cheque os fios CLK/CMD/ATT/DAT do receptor.

Momento 5 de 5

Encerramento

Rodas + Eixos plásticos

Roda de conversa: o que é teleoperação? Qual a diferença entre robô autônomo (seguidor) e teleoperado (este)? Onde cada um é melhor? Encerrar com uma partida de robô-futebol.

🔀 O plano do robô

Como ele decide o que fazer

flowchart TD A(["Início"]) --> CFG["Configurar o controle PS2 e o driver"] CFG --> L["Ler o controle (joysticks e setas)"] L --> ZM["Aplicar a zona morta"] ZM --> V["Calcular a velocidade base e o giro"] V --> D{"Joystick para frente, trás ou parado?"} D -->|Frente| F["Avançar (ajustando o giro)"] D -->|Trás| T["Recuar"] D -->|Parado| G["Girar no lugar"] F --> L T --> L G --> L
💻 O cérebro do robô

O código da aula

/*
 * Robô de Futebol — controle sem fio PS2 + driver TB6612 (Arduino UNO)
 * Lê os joysticks do controle PS2 e move 2 motores com direção diferencial
 * (frente, trás e giro no lugar). (código original; comentários em português)
 *
 * Driver TB6612: os pinos abaixo controlam AIN1/AIN2/PWMA (motor A) e
 * BIN1/BIN2/PWMB (motor B). O pino STBY do TB6612 deve ficar em nível ALTO
 * (ligado no 5V) para o driver funcionar. Os nomes IN/EN abaixo são herdados
 * do código original e mapeiam direto nesses terminais.
 */
#include <PS2X_lib.h>

PS2X ps2x;
int error = 0;
byte vibrate = 0;

// Pinos do driver TB6612  (IN1/IN2->AIN1/AIN2, ENA->PWMA, IN3/IN4->BIN1/BIN2, ENB->PWMB)
const int IN1 = 4;
const int IN2 = 3;
const int IN3 = 8;
const int IN4 = 7;
const int ENA = 9;
const int ENB = 5;

void controlMotores(int velocidadMotorA, int velocidadMotorB);

void setup() {
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);

  delay(300);
  // config_gamepad(clock A3, command A1, attention A0, data A2)
  error = ps2x.config_gamepad(A3, A1, A0, A2, true, true);
}

void loop() {
  ps2x.read_gamepad(false, vibrate);

  // Ler o joystick direito (frente / trás)
  int joyY = ps2x.Analog(PSS_RY) - 127;
  if (joyY == -128) joyY = -127;

  // Ler o joystick esquerdo (giros)
  int joyX = ps2x.Analog(PSS_LX) - 127;
  if (joyX == -128) joyX = -127;

  // Ler os botões de direção (setas)
  bool flechaIzq = ps2x.Button(PSB_PAD_LEFT);
  bool flechaDer = ps2x.Button(PSB_PAD_RIGHT);

  // Zona morta
  if (abs(joyY) < 15) joyY = 0;
  if (abs(joyX) < 15) joyX = 0;

  // Velocidade base a partir do joystick direito
  int velocidadBase = map(abs(joyY), 0, 127, 0, 255);

  // Giro proporcional a partir do joystick esquerdo
  int giro = map(joyX, -127, 127, -255, 255);

  // Prioridade: se apertar as setas, substitui o giro
  if (flechaIzq) giro = -200;
  else if (flechaDer) giro = 200;

  // Inicializar as velocidades
  int velocidadMotorA = 0;
  int velocidadMotorB = 0;

  if (joyY < 0) {
    // Avançar
    velocidadMotorA = velocidadBase - giro;
    velocidadMotorB = velocidadBase + giro;
  } else if (joyY > 0) {
    // Recuar
    velocidadMotorA = -velocidadBase + giro;
    velocidadMotorB = -velocidadBase - giro;
  } else {
    // Parado: permite girar no lugar
    velocidadMotorA = giro;
    velocidadMotorB = -giro;
  }

  // Limitar os valores
  velocidadMotorA = constrain(velocidadMotorA, -255, 255);
  velocidadMotorB = constrain(velocidadMotorB, -255, 255);

  controlMotores(velocidadMotorA, velocidadMotorB);

  delay(30);
}

void controlMotores(int velocidadMotorA, int velocidadMotorB) {
  // Motor A
  if (velocidadMotorA > 0) {
    digitalWrite(IN1, HIGH);
    digitalWrite(IN2, LOW);
  } else if (velocidadMotorA < 0) {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, HIGH);
  } else {
    digitalWrite(IN1, LOW);
    digitalWrite(IN2, LOW);
  }

  // Motor B
  if (velocidadMotorB > 0) {
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, HIGH);
  } else if (velocidadMotorB < 0) {
    digitalWrite(IN3, HIGH);
    digitalWrite(IN4, LOW);
  } else {
    digitalWrite(IN3, LOW);
    digitalWrite(IN4, LOW);
  }

  // Velocidade
  analogWrite(ENA, abs(velocidadMotorA));
  analogWrite(ENB, abs(velocidadMotorB));
}

role dentro da caixa · o código completo está na página da aula

🥊

Bora construir!

dúvidas? a página completa da aula tem tudo: montagem, código e materiais.