Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Componentes e Materiais

Componente Quantidade Observações
Arduino UNO 1
Driver de Motor Dual H-Bridge L298 (SparkFun) 1
Kit Robô Tanque DIY 1
Controle Sem Fio Sony PS2 1

Aplicativos e Serviços Online

Sobre o Projeto

Neste tutorial, mostro como usar um joystick sem fio PlayStation 2 (PS2) para pilotar um tanque robótico. Uma placa Arduino Uno é o núcleo do projeto. Ela recebe comandos do controle sem fio e define a velocidade dos motores. Outras placas de desenvolvimento (NodeMCU, Firebeetle, etc.) também podem ser usadas, e os princípios aqui apresentados aplicam-se a outros modelos de robôs e gadgets.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2
Tanque Robô Arduino Controlado por Joystick Sem Fio PS2
Tanque Robô Arduino Controlado por Joystick Sem Fio PS2
Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Passo 1: Ferramentas e Materiais

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Ferramentas utilizadas:

Peças de hardware:

Passo 2: Montagem do Robô

A primeira parte foi a montagem da estrutura. O kit surpreendeu pela qualidade e peças sobressalentes. Inclui todas as ferramentas necessárias (chaves Allen, chave de fenda), ótimo para iniciantes. Como ponto negativo, a documentação (manual em chinês) não é amigável e há poucos tutoriais online. O chassi de alumínio pode causar curto-circuito se pinos das placas tocarem a estrutura.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2
Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Passo 3: Ligação do Circuito

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Um pacote de três baterias 18650 na traseira fornece 11.1V. O L298N recebe sinais de 5V do Arduino e fornece tensão maior aos motores, permitindo rotação em ambas as direções.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Conexões Arduino Uno:

Conexões H-Bridge:

Receptor PS2:

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2
Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Passo 4: Configuração do Arduino IDE

  1. Baixe e instale a versão mais recente do Arduino IDE em arduino.cc.
  2. Adicione a biblioteca Arduino PS2X: baixe em GitHub, descompacte e copie as pastas para a pasta libraries/tools do Arduino IDE.

Passo 5: Biblioteca do Controle PS2 Explicada

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

O controle PS2 tem 20 botões digitais e 2 sticks analógicos. Usei a biblioteca PS2X de Bill Porter. Cria-se um objeto PS2X ps2x; e configura-se com ps2x.config_gamepad(clock, command, attention, data, pressure?, rumble?). Funções principais: ps2x.Button(button) para leitura digital e ps2x.Analog(stick_axis) para leitura analógica (0-255). Mapeamento dos botões: direcionais (PSB_PAD_UP, DOWN, LEFT, RIGHT), ação (PSB_GREEN/TRIANGLE, PSB_RED/CIRCLE, PSB_BLUE/CROSS, PSB_PINK/SQUARE), gatilhos (PSB_L1, R1, L2, R2), sticks (PSB_L3, R3), menu (PSB_SELECT, START). Eixos analógicos: PSS_LY, PSS_LX, PSS_RY, PSS_RX.

Passo 6: Sketch #1 – Botões Direcionais (D-pad)

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Emula controles de jogos antigos: botões ligam/desligam motores em velocidade fixa. Mapeamento: CIMA = frente, BAIXO = ré, ESQUERDA = virar esquerda, DIREITA = virar direita. Ao virar, motores giram em sentidos opostos para girar no próprio eixo.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Código Arduino (Sketch #1): – veja seção Código abaixo.

Explicação do Código: Inclui PS2X_lib.h. Define pinos do H-Bridge. Variáveis globais: ps2x, error, type, vibrate. No setup(): configura pinos como saída, desabilita motores, inicia Serial (57600), configura ps2x com pinos (13,11,10,12), verifica erros e tipo de controle. No loop(): lê botões D-pad e define pinos de saída para mover rodas. Usa PWM nos pinos ENA/ENB (0-1023). Se nenhum botão pressionado, desabilita motores.

Passo 7: Sketch #2 – Stick Analógico Esquerdo e Botões Digitais (L2 e R2)

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Usa stick analógico esquerdo para direção (eixo X) e botões L2/R2 como acelerador/freio/ré. Pressiona R2 para frente, L2 para ré. A posição X do stick mapeia diferença de velocidade entre esteiras.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

No loop: lê PSS_LX, mapeia 0-255 para -1023 a 1023. Ajusta velocidade de cada motor. Se R2 pressionado, move frente com PWM proporcional. Se L2, move ré. Se nenhum, desabilita motores.

Passo 8: Sketch #3 – Sticks Analógicos Esquerdo e Direito (Direção Diferencial)

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Meu favorito: cada stick controla uma esteira. Stick esquerdo → esteira esquerda, direito → esteira direita. Lê eixos Y de ambos (PSS_LY, PSS_RY), mapeia para -1023 a 1023. Define direção de cada motor conforme sinal. Usa zona morta (±50) para desabilitar motores.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Passo 9: Sketch #4 – Apenas Stick Analógico Esquerdo

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Único joystick controla tudo: velocidade de cada esteira depende de X e Y. Ótimo em recursos (sobram botões), mas mais complexo de entender. Baseado em tutorial de direção diferencial.

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Passo 10: Considerações Finais

Esforcei-me para tornar este projeto claro e educativo. Se gostou, curta e compartilhe! Confira meus outros tutoriais de robótica:

Considere apoiar futuros projetos com doação Bitcoin: 1FiWFYSjRaL7sLdr5wr6h86QkMA6pQxkXJ

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Código

Sketch #1 – Botões Direcionais

// PS2 Tank by Igor Fonseca @2019
// Controls a robotic tank using a PS2 joystick, using D-pad buttons
// based on an example using the PS2X library by Bill Porter 2011
#include 
#define ENA 3
#define MOTORA_1 4
#define MOTORA_2 5
#define MOTORB_1 8
#define MOTORB_2 7
#define ENB 6
PS2X ps2x;
int error = 0;
byte type = 0;
byte vibrate = 0;
void setup() {
  pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT);
  pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT);
  digitalWrite(ENA,0); digitalWrite(ENB,0);
  Serial.begin(57600);
  error = ps2x.config_gamepad(13,11,10,12, true, true);
  if(error == 0) Serial.println("Found Controller, configured successful");
  else if(error == 1) Serial.println("No controller found, check wiring or reset the Arduino");
  else if(error == 2) Serial.println("Controller found but not accepting commands");
  else if(error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it.");
  type = ps2x.readType();
  switch(type) {
    case 0: Serial.println("Unknown Controller type"); break;
    case 1: Serial.println("DualShock Controller Found"); break;
    case 2: Serial.println("GuitarHero Controller Found"); break;
  }
}
void loop() {
  if(error == 1) return;
  ps2x.read_gamepad(false, vibrate);
  if(ps2x.Button(PSB_PAD_UP)) {
    digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH);
    digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW);
    analogWrite(ENB, 1023); analogWrite(ENA, 1023);
    Serial.println("Move forward");
  }
  if(ps2x.Button(PSB_PAD_RIGHT)) {
    digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW);
    digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW);
    analogWrite(ENB, 1023); analogWrite(ENA, 1023);
    Serial.println("Turn right");
  }
  if(ps2x.Button(PSB_PAD_LEFT)) {
    digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH);
    digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH);
    analogWrite(ENB, 1023); analogWrite(ENA, 1023);
    Serial.println("Turn left");
  }
  if(ps2x.Button(PSB_PAD_DOWN)) {
    digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW);
    digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH);
    analogWrite(ENB, 1023); analogWrite(ENA, 1023);
    Serial.println("Move back");
  }
  if (!ps2x.Button(PSB_PAD_DOWN) && !ps2x.Button(PSB_PAD_UP) && !ps2x.Button(PSB_PAD_RIGHT) && !ps2x.Button(PSB_PAD_LEFT)) {
    analogWrite(ENB, 0); analogWrite(ENA, 0);
  }
  delay(50);
}

Sketch #2 – Stick Analógico e Botões L2/R2

// PS2 Tank by Igor Fonseca @2019
#include 
#define ENA 3
#define MOTORA_1 4
#define MOTORA_2 5
#define MOTORB_1 8
#define MOTORB_2 7
#define ENB 6
int motor_right_speed = 0;
int motor_left_speed = 0;
PS2X ps2x;
int error = 0;
byte type = 0;
byte vibrate = 0;
void setup() {
  pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT);
  pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT);
  digitalWrite(ENA,0); digitalWrite(ENB,0);
  Serial.begin(57600);
  error = ps2x.config_gamepad(13,11,10,12, true, true);
  if(error == 0) Serial.println("Found Controller, configured successful");
  else if(error == 1) Serial.println("No controller found, check wiring or reset the Arduino");
  else if(error == 2) Serial.println("Controller found but not accepting commands");
  else if(error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it.");
  type = ps2x.readType();
  switch(type) {
    case 0: Serial.println("Unknown Controller type"); break;
    case 1: Serial.println("DualShock Controller Found"); break;
    case 2: Serial.println("GuitarHero Controller Found"); break;
  }
}
void loop() {
  if(error == 1) return;
  ps2x.read_gamepad(false, vibrate);
  int nJoyL = ps2x.Analog(PSS_LX);
  nJoyL = map(nJoyL, 0, 255, 1023, -1023);
  int motor_right_speed = 1023;
  int motor_left_speed = 1023;
  if (nJoyL < 0) motor_right_speed = motor_right_speed + nJoyL;
  if (nJoyL > 0) motor_left_speed = motor_left_speed - nJoyL;
  if(ps2x.Button(PSB_R2)) {
    digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH);
    digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW);
    analogWrite(ENA, motor_right_speed); analogWrite(ENB, motor_left_speed);
  }
  if(ps2x.Button(PSB_L2)) {
    digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW);
    digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH);
    analogWrite(ENA, motor_right_speed); analogWrite(ENB, motor_left_speed);
  }
  if(!ps2x.Button(PSB_L2) && !ps2x.Button(PSB_R2)) {
    analogWrite(ENA, 0); analogWrite(ENB, 0);
  }
  delay(50);
}

Sketch #3 – Dois Sticks Analógicos (Direção Diferencial)

// PS2 Tank by Igor Fonseca @2019
#include 
#define ENA 3
#define MOTORA_1 4
#define MOTORA_2 5
#define MOTORB_1 8
#define MOTORB_2 7
#define ENB 6
PS2X ps2x;
int error = 0;
byte type = 0;
byte vibrate = 0;
void setup() {
  pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT);
  pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT);
  digitalWrite(ENA,0); digitalWrite(ENB,0);
  Serial.begin(57600);
  error = ps2x.config_gamepad(13,11,10,12, true, true);
  if(error == 0) Serial.println("Found Controller, configured successful");
  else if(error == 1) Serial.println("No controller found, check wiring or reset the Arduino");
  else if(error == 2) Serial.println("Controller found but not accepting commands");
  else if(error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it.");
  type = ps2x.readType();
  switch(type) {
    case 0: Serial.println("Unknown Controller type"); break;
    case 1: Serial.println("DualShock Controller Found"); break;
    case 2: Serial.println("GuitarHero Controller Found"); break;
  }
}
void loop() {
  if(error == 1) return;
  ps2x.read_gamepad(false, vibrate);
  int nJoyL = ps2x.Analog(PSS_LY);
  int nJoyR = ps2x.Analog(PSS_RY);
  nJoyL = map(nJoyL, 0, 255, 1023, -1023);
  nJoyR = map(nJoyR, 0, 255, -1023, 1023);
  if(nJoyR > 50) {
    digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW);
    analogWrite(ENA, 1023);
  }
  if(nJoyR < -50) {
    digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH);
    analogWrite(ENA, 1023);
  }
  if (abs(nJoyR) < 50) analogWrite(ENA, 0);
  if(nJoyL > 50) {
    digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW);
    analogWrite(ENB, 1023);
  }
  if(nJoyL < -50) {
    digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH);
    analogWrite(ENB, 1023);
  }
  if (abs(nJoyL) < 50) analogWrite(ENB, 0);
  delay(50);
}

Sketch #4 – Apenas Stick Esquerdo

// PS2 Tank by Igor Fonseca @2019
#include 
#define ENA 3
#define MOTORA_1 4
#define MOTORA_2 5
#define MOTORB_1 8
#define MOTORB_2 7
#define ENB 6
int motor_right_speed = 0;
int motor_left_speed = 0;
PS2X ps2x;
int error = 0;
byte type = 0;
byte vibrate = 0;
void setup() {
  pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT);
  pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT);
  digitalWrite(ENA,0); digitalWrite(ENB,0);
  Serial.begin(57600);
  error = ps2x.config_gamepad(13,11,10,12, true, true);
  if(error == 0) Serial.println("Found Controller, configured successful");
  else if(error == 1) Serial.println("No controller found, check wiring or reset the Arduino");
  else if(error == 2) Serial.println("Controller found but not accepting commands");
  else if(error == 3) Serial.println("Controller refusing to enter Pressures mode, may not support it.");
  type = ps2x.readType();
  switch(type) {
    case 0: Serial.println("Unknown Controller type"); break;
    case 1: Serial.println("DualShock Controller Found"); break;
    case 2: Serial.println("GuitarHero Controller Found"); break;
  }
}
void loop() {
  if(error == 1) return;
  ps2x.read_gamepad(false, vibrate);
  int nJoyX = ps2x.Analog(PSS_LX);
  int nJoyY = ps2x.Analog(PSS_LY);
  nJoyX = map(nJoyX, 0, 255, -1023, 1023);
  nJoyY = map(nJoyY, 0, 255, 1023, -1023);
  int nMotMixL, nMotMixR;
  float fPivYLimit = 1023.0;
  float nMotPremixL, nMotPremixR;
  int nPivSpeed;
  float fPivScale;
  if (nJoyY >= 0) {
    nMotPremixL = (nJoyX >= 0) ? 1023.0 : (1023.0 + nJoyX);
    nMotPremixR = (nJoyX >= 0) ? (1023.0 - nJoyX) : 1023.0;
  } else {
    nMotPremixL = (nJoyX >= 0) ? (1023.0 - nJoyX) : 1023.0;
    nMotPremixR = (nJoyX >= 0) ? 1023.0 : (1023.0 + nJoyX);
  }
  nMotPremixL = nMotPremixL * nJoyY / 1023.0;
  nMotPremixR = nMotPremixR * nJoyY / 1023.0;
  nPivSpeed = nJoyX;
  fPivScale = (abs(nJoyY) > fPivYLimit) ? 0.0 : (1.0 - abs(nJoyY) / fPivYLimit);
  nMotMixL = (1.0 - fPivScale) * nMotPremixL + fPivScale * (nPivSpeed);
  nMotMixR = (1.0 - fPivScale) * nMotPremixR + fPivScale * (-nPivSpeed);
  motor_left_speed = nMotMixL;
  motor_right_speed = nMotMixR;
  if (motor_right_speed > 50) {
    digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW);
  } else if (motor_right_speed < -50) {
    digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH);
  } else {
    digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,LOW);
  }
  if (motor_left_speed > 50) {
    digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH);
  } else if (motor_left_speed < -50) {
    digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW);
  } else {
    digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,LOW);
  }
  analogWrite(ENA, abs(motor_left_speed));
  analogWrite(ENB, abs(motor_right_speed));
  if (abs(motor_left_speed) > 50 || abs(motor_right_speed) > 50) Serial.println("Moving!");
  delay(50);
}

Esquemáticos

Tanque Robô Arduino Controlado por Joystick Sem Fio PS2
Tanque Robô Arduino Controlado por Joystick Sem Fio PS2

Processo de manufatura

  1. Construa um Robô de Streaming de Vídeo Controlado por Internet com Arduino e Raspberry Pi
  2. Unopad: Controlador MIDI Arduino Perfeito para Ableton Live
  3. Robô Desviador de Obstáculos com Servo: Construa com Arduino e HC-SR04
  4. Controlar Roomba Create 2 com Arduino e Android: Guia Passo a Passo
  5. Braço Robótico 6 GDL Controlado por Nunchuk com Arduino Mega
  6. Controle Dois Motores de Passo com Arduino Nano e Joystick – Tutorial Simples
  7. Volante Joystick Arduino Personalizado para Jogos
  8. Crie um Battle Bot Controlado Remotamente com um Controle PS2
  9. Controle Braço Robótico Arduino via App Android Dedicado
  10. Robô Comedor com Arduino Nano – Guia Passo a Passo