← Sair
Robô de Futebol (controle PS2)
Modo Bancada · Plugada

Robô de Futebol (controle PS2)

Robô de Futebol (controle PS2)

🎯 O que vamos aprender
  • 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 vamos usar

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

🪜 Passo 1 de 5

Introdução / Contextualizaçã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.

🪜 Passo 2 de 5

Montagem do Circuito / Hardware

1) Montar o chassi, as rodas e os 2 motores. 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.

🪜 Passo 3 de 5

Programação / Codificaçã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.

🪜 Passo 4 de 5

Teste, Depuração 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.

🪜 Passo 5 de 5

Encerramento / Socialização

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.

🔌 Montagem do robô

Placa: Arduino Uno

⬇ baixar SVG
🧰 Montagem do robôPlaca: Arduino Uno · 4 componentes · 20 ligações detectadas do códigoUSBATMEGA328PLARDUINO UNOAREFGND131211109876543210DIGITAL (PWM ~)IOREFRESET3V35VGNDGNDVINPOWERA0A1A2A3A4A5ANALOG INArduino Uno⚡ Barramento de alimentação · 5V (+) / GND (–)D4 · direção AD3 · direção AD9 · PWM velocidade AD8 · direção BD7 · direção BD5 · PWM velocidade B5V (Arduino) · habilita o driver…Driver de motor(TB6612)AO1·AO2Motor DC esquerdoBO1·BO2Motor DC direitoA3 · clockA1 · comandoA0 · seleçãoA2 · dadosReceptor PS2 (sem fio)LEGENDA DOS FIOSAlimentação (+5V)Terra (GND)DigitalAnalógico (leitura)PWM (velocidade)Saída de motorOutro / dados
🧰 Montagem do robôArduino Unoplaca controladoraDriver de motor (TB6612)D4D3D9D8D7D55V (Arduino)bateria +5V (Arduino)GNDReceptor PS2 (sem fio)A3A1A0A23,3VGNDMotor DC esquerdoAO1AO2Motor DC direitoBO1BO2
💻 O código
aula.ino
/*
 * 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));
}
🔀 Como o programa pensa
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
🧱 Em blocos
quando @greenFlag for clicado
configurar o controle PS2 e o driver TB6612
sempre
  ler o controle (joysticks e setas)
  aplicar a zona morta
  calcular a velocidade base e o giro
  se <joystick para frente> então
    avançar (ajustando o giro)
  senão
    se <joystick para trás> então
      recuar
    senão
      girar no lugar
    end
  end
end
🖨️ Peças 3D

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

Chassi do robô
Rodas (rines)
Pra fechar

Você chegou ao fim! 🎉

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

✓ Sair