#include <Servo.
h>
#include <NewPing.h>
// Pines
#define sensorIzquierdo 2
#define sensorDerecho 3
#define boton 4
#define motorIzquierdo 5
#define motorDerecho 6
#define echo 16 // A2
#define trigger 17 // A3
// Distancias
#define distanciaMaxima 40
#define distanciaMinima 5
// Velocidades calibradas
const int PARADO = 90;
const int ADELANTE_I = 180;
const int ADELANTE_D = 0;
const int ATRAS_I = 0;
const int ATRAS_D = 180;
const int GIRO_IZQUIERDA = 60;
const int GIRO_DERECHA = 120;
// Objetos y variables
Servo servoIzquierdo;
Servo servoDerecho;
NewPing sonar(trigger, echo, distanciaMaxima);
boolean modoCombate = false;
int estadoSensorDerecho;
int estadoSensorIzquierdo;
int cm;
unsigned long tiempoAnterior = 0;
unsigned long intervalo = 100;
String accionActual = "Parado";
// Estado evasión
enum EstadoEvasion { SIN_EVASION,
RETROCEDIENDO, REUBICANDO };
EstadoEvasion estadoEvasion = SIN_EVASION;
unsigned long tiempoEvasion = 0;
const unsigned long duracionRetroceso = 300;
const unsigned long duracionReubicar = 300;
void setup() {
pinMode(boton, INPUT_PULLUP);
pinMode(sensorDerecho, INPUT);
pinMode(sensorIzquierdo, INPUT);
pinMode(echo, INPUT);
pinMode(trigger, OUTPUT);
[Link](motorIzquierdo);
[Link](motorDerecho);
[Link](9600);
[Link]("ROBOT PREPARADO...");
[Link]("Presione el botón para
comenzar el combate");
}
void loop() {
leerBoton();
leerSensores();
if (!modoCombate) {
Parado();
estadoEvasion = SIN_EVASION;
} else {
unsigned long tiempoActual = millis();
// Si está en evasión, gestionamos su
máquina de estados
if (estadoEvasion != SIN_EVASION) {
manejarEvasion(tiempoActual);
return; // Mientras esté evadiendo, no
hace otras acciones
}
// Comportamiento normal
if (tiempoActual - tiempoAnterior >=
intervalo) {
tiempoAnterior = tiempoActual;
if (estadoSensorDerecho == LOW ||
estadoSensorIzquierdo == LOW) {
iniciarEvasion(tiempoActual);
} else if (cm > distanciaMinima && cm <=
distanciaMaxima) {
AtaqueInteligente();
accionActual = "Ataque";
intervalo = 200;
} else {
BuscarEnemigo();
accionActual = "Buscar";
intervalo = 100;
}
}
}
}
void leerBoton() {
static bool estadoAnterior = HIGH;
bool estadoActual = digitalRead(boton);
if (estadoAnterior == HIGH && estadoActual
== LOW) {
modoCombate = !modoCombate;
delay(500); // Antirebote
if (modoCombate) {
[Link]("ENTRANDO EN MODO
COMBATE");
delay(4500); // Cuenta regresiva antes
del inicio
} else {
[Link]("ENTRANDO EN MODO
REPOSO");
}
}
estadoAnterior = estadoActual;
}
void leerSensores() {
estadoSensorDerecho =
digitalRead(sensorDerecho);
estadoSensorIzquierdo =
digitalRead(sensorIzquierdo);
int cm1 = sonar.convert_cm([Link]());
delay(10);
int cm2 = sonar.convert_cm([Link]());
if (cm1 >= distanciaMinima && cm1 <=
distanciaMaxima &&
cm2 >= distanciaMinima && cm2 <=
distanciaMaxima) {
cm = (cm1 + cm2) / 2;
} else {
cm = 0;
}
}
// ================= MOVIMIENTOS
===================
void Parado() {
[Link](PARADO);
[Link](PARADO);
}
void Avanzar() {
[Link](ADELANTE_I);
[Link](ADELANTE_D);
}
void Retroceder() {
[Link](ATRAS_I);
[Link](ATRAS_D);
}
void GirarDerecha() {
[Link](GIRO_DERECHA);
[Link](GIRO_DERECHA);
}
void GirarIzquierda() {
[Link](GIRO_IZQUIERDA);
[Link](GIRO_IZQUIERDA);
}
// =============== ACCIONES
=======================
void AtaqueInteligente() {
[Link]("ATACANDO AGRESIVAMENTE");
Avanzar();
}
void BuscarEnemigo() {
[Link]("BUSCANDO AL OPONENTE...");
Avanzar(); // Puedes cambiar por giro si lo
deseas
}
// =========== EVASIÓN CON millis
=================
void iniciarEvasion(unsigned long
tiempoActual) {
[Link]("EVASIÓN INICIADA:
RETROCEDIENDO");
Retroceder();
estadoEvasion = RETROCEDIENDO;
tiempoEvasion = tiempoActual;
}
void manejarEvasion(unsigned long
tiempoActual) {
switch (estadoEvasion) {
case RETROCEDIENDO:
if (tiempoActual - tiempoEvasion >=
duracionRetroceso) {
[Link]("EVASIÓN: REUBICANDO");
GirarDerecha(); // Puedes ajustar la
dirección si lo deseas
estadoEvasion = REUBICANDO;
tiempoEvasion = tiempoActual;
}
break;
case REUBICANDO:
if (tiempoActual - tiempoEvasion >=
duracionReubicar) {
[Link]("EVASIÓN COMPLETA");
estadoEvasion = SIN_EVASION;
Parado();
}
break;
case SIN_EVASION:
default:
break;
}
}