← 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
Driver de motor TB6612
Receptor + controle sem fio PS2
Motor DC com caixa de redução Motor DC com caixa de redução
Rodas (impressão 3D) Rodas (impressão 3D)
Bateria (pack de pilhas ou LiPo) Bateria (pack de pilhas ou LiPo)
Chassi (impressão 3D) Chassi (impressão 3D)
Jumpers e parafusos Jumpers e parafusos
🔌 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.