Skip to main content

BATTLE BOTS

BATTLEBOTS - ¡It´s fighting time! - Robot de Lucha Controlado por ESP32 y PS4#

Descripción del Proyecto#

BattleBots es un proyecto de robótica en el que vamos a construir un robot de lucha que posteriormente controlaremos con el mando de una PlayStation 4 (PS4). Esta comunicación será posible gracias al uso de una placa ESP32.

Los combates de robots son luchas uno contra uno, donde la victoria será para el robot que consiga empujar al oponentes fuera del área de juego o, si es posible, inhabilitarlo.

Componentes Principales#

  1. ESP32: Microcontrolador utilizado como cerebro del robot. Gestiona la comunicación con el mando PS4 y controla los motores del robot.
  2. LN298: Driver de motores de corriente continua utilizado para gestionar el voltaje que le llega a los motores y, por tanto, su velocidad y dirección de giro.
  3. Motores con escobillas (brushed): los robots contarán con 2 o 4 motores para poder moverse. Son motores de 12V que giran a 500 rpm.
  4. Servo motor para crear peligrosas armas de destrucción. Podréis usar como máximo un servo motor.
  5. Step-down: o placa reductora de voltaje, necesaria para alimentar con la batería de 11V los servos (que son de 6V).
  6. Batería: Batería de 11V y 2200 mA para proporcionar energía al robot durante las peleas.

Pasos#

A continuación tenéis el esquema eléctrico del proyecto:

Esquema

Si decidís incluir más motores en vuestro robot, tendréis que modificar este esquema para incluirlos. No es algo complejo, pero corre de vuestra cuenta.

Código para el robot con servomotor#

#include <PS4Controller.h>
#include <ESP32Servo.h>
// El LN298 utiliza 3 pines para controlar cada motor (PIN_MOTOR_A_VEL,
// PIN_MOTOR_A_DIR_1, PIN_MOTOR_A_DIR_2) y (PIN_MOTOR_B_VEL, PIN_MOTOR_B_DIR_1,
// PIN_MOTOR_B_DIR_2) Por tanto tiene 6 entradas, 3 para cada motor, que le
// indican el voltaje y la polaridad que debe enviar a cada motor.
// Tiene 4 salidas, 2 para cada motor, por las que envía el voltaje
// correspondiente en cada momento.
const int PIN_MOTOR_A_VEL = 15;
const int PIN_MOTOR_A_DIR_1 = 16;
const int PIN_MOTOR_A_DIR_2 = 17;
const int PIN_MOTOR_B_VEL = 21;
const int PIN_MOTOR_B_DIR_1 = 18;
const int PIN_MOTOR_B_DIR_2 = 19;
const int PIN_SERVO = 27;
Servo miServo;
// Esta función la usaremos para mandar un mensaje por el monitor serie que nos indique
// cuando se ha conectado el mando.
void onConnect()
{
Serial.println("¡Mando conectado!.");
}
// Esta función la usaremos para mandar un mensaje por el monitor serie que nos indique
// cuando se ha desconectado el mandovoid onDisConnect().
void onDisConnect()
{
Serial.println("¡Mando desconectado!.");
}
// Esta función le indica a la placa ESP32 la configuración de sus pines. En ella declaramos
// qué pines serán de entrada y cuáles de salida.
void setUpPinModes()
{
pinMode(PIN_MOTOR_A_VEL, OUTPUT);
pinMode(PIN_MOTOR_A_DIR_1, OUTPUT);
pinMode(PIN_MOTOR_A_DIR_2, OUTPUT);
pinMode(PIN_MOTOR_B_VEL, OUTPUT);
pinMode(PIN_MOTOR_B_DIR_1, OUTPUT);
pinMode(PIN_MOTOR_B_DIR_2, OUTPUT);
pinMode(PIN_SERVO, OUTPUT);
}
// La función notify() es esencial, ya que es un callback que se activa
// automáticamente cada vez que se produce un cambio en el estado del mando,
// como presionar o soltar un botón. Esto posibilita una respuesta dinámica
// del programa a eventos externos sin bloquear el flujo principal de ejecución.
//
// En notify(), se obtienen los valores de los dos joysticks y de los botones
// R1 y R2 del mando. El joystick izquierdo controla la dirección y velocidad
// del primer motor, mientras que el joystick derecho controla el segundo motor.
// Los botones R1 y R2 se utilizan para accionar el servo motor en uno u otro sentido.
void notify()
{
int leftJoystickY = PS4.LStickY(); // Valor del eje Y del joystick izquierdo.
int rightJoystickY = PS4.RStickY(); // Valor del eje Y del joystick derecho.
bool R1 = PS4.R1(); // Estado del botón R1 [bool: true or false].
bool R2 = PS4.R2(); // Estado del botón R2 [bool: true or false].
// Control del motor izquierdo.
if(rightJoystickY > 0)
{
analogWrite(PIN_MOTOR_A_VEL, 2 * rightJoystickY); // Control de velocidad del motor izquierdo en sentido positivo.
digitalWrite(PIN_MOTOR_A_DIR_1, LOW);
digitalWrite(PIN_MOTOR_A_DIR_2, HIGH); // Dirección de giro del motor izquierdo.
}
else
{
analogWrite(PIN_MOTOR_A_VEL, abs(2 * rightJoystickY)); // Control de velocidad del motor izquierdo en sentido negativo.
digitalWrite(PIN_MOTOR_A_DIR_1, HIGH);
digitalWrite(PIN_MOTOR_A_DIR_2, LOW);
}
// Control del motor derecho.
if(leftJoystickY > 0)
{
analogWrite(PIN_MOTOR_B_VEL, 2 * leftJoystickY); // Control de velocidad del motor derecho en sentido positivo.
digitalWrite(PIN_MOTOR_B_DIR_1, LOW);
digitalWrite(PIN_MOTOR_B_DIR_2, HIGH); // Dirección de giro del motor derecho.
}
else
{
analogWrite(PIN_MOTOR_B_VEL, abs(2 * leftJoystickY)); // Control de velocidad del motor derecho en sentido negativo.
digitalWrite(PIN_MOTOR_B_DIR_1, HIGH);
digitalWrite(PIN_MOTOR_B_DIR_2, LOW);
}
// Control del servo con los botones R1 y R2.
if(R1)
{
miServo.write(90); // Mover el servo a la posición 90 grados.
}
if(R2)
{
miServo.write(0); // Mover el servo a la posición 0 grados.
}
}
// La librería PS4Controller.h nos permite crear un "objeto" que rastrea
// el estado del mando. Este objeto PS4 almacPIN_MOTOR_A_VEL toda la información relevante
// sobre el mismo. Luego, utilizando el método "attach", asignamos una serie de
// funciones a este objeto. La función PS4.attach(notify) se emplea para asociar
// la función notify() con la biblioteca PS4Controller, permitiendo que notify()
// se active cada vez que se reciban datos del controlador PS4. Esta asociación
// no interrumpe el flujo principal del programa, sino que desencadPIN_MOTOR_A_VEL una acción
// específica cuando se produce un evento determinado, como la recepción de datos
// del controlador PS4. De manera similar, PS4.attachOnConnect(onConnect) se
// activará cuando el controlador PS4 se conecte a la ESP32.
void setup() {
setUpPinModes();
miServo.attach(PIN_SERVO); // para indicarle en qué pin hemos conectado el servo.
miServo.write(0); // inicializamos el servo en la posición 0º.
Serial.begin(115200);
PS4.attach(notify);
PS4.attachOnConnect(onConnect);
PS4.attachOnDisconnect(onDisConnect);
PS4.begin();
Serial.println("Ready.");
}
void loop()
{
}

La función notify() lo que nos permite es no sobrecargar el flujo de información entre la ESP32 y el mando PS4. Podría parecer más sencillo meter en el loop() todas las instrucciones que aparecen en notify() como hemos hecho en las prácticas anteriores, de tal manera que en cada iteración del loop se compruebe el estado de los botones del mando y se manden las instrucciones necesarias a los motores. Pero esto hace trabajar al micro innecesariamente, porque en cada una de las iteraciones tendrá que ver el estado de cada boton del mando con el flujo de datos que eso implica. Utilizando un callback conseguimos que esa comprobación solo se realice cuando haya algún cambio en el mando, reduciéndo drásticamente el flujo de datos y el trabajo del micro. Parece una tontería pero el bucle loop() se realiza muchos miles de veces por segundo.

Contribuciones#

Las contribuciones al proyecto son bienvenidas. Si encuentras algún problema o tienes ideas para mejorar el robot, no dudes en abrir un problema o enviar una solicitud de extracción.

Licencia#

Este proyecto está bajo la licencia MIT..