Control de luces y motor con PS4 Controller usando ESP32 – Parte 1

Este proyecto utiliza un ESP32 junto con un mando PS4 para controlar luces, motor y otras funciones. A lo largo de este tutorial explicaremos el código detallado, el hardware necesario y cómo implementar esta solución en tu vehículo DIY.


Materiales necesarios:

  • ESP32 (Wemos D1 Mini32 en este ejemplo).
  • Mando PS4.
  • Driver de motor BTS7960.
  • Luces LED y sus controladores.
  • Resistencias 1K.
  • Fuentes de alimentación según el diseño.
  • TIP120 o IRLZ44N x3 o más según sea necesario para controlar luces.
  • Visual Studio Code

Esquema de conexiones:

ComponentePin ESP32
Luces nocturnas y largasGPIO27
Intermitente derechoGPIO22
Intermitente izquierdoGPIO21
Amplificador BluetoothGPIO33
Luz traseraGPIO25
BTS7960 ENGPIO19
BTS7960 L_PWMGPIO26
BTS7960 R_PWMGPIO18
Batería (voltaje analógico)A0

Configuración del código

El siguiente código configura el ESP32 para recibir comandos del mando PS4 y controlar luces y el motor a través del driver BTS7960.

#include <PS4Controller.h>

// Pines para luces 
#define LUZ_NOCTURNA_Y_LARGAS 27 // Pin compartido para luces nocturnas y largas
#define INTERMITENTE_DERECHO 22
#define INTERMITENTE_IZQUIERDO 21
#define LUZ_TRASERA 25 // Pin para las luces traseras

#define AMPLIFICADOR_BLUETOOTH 33 // Pin para el amplificador Bluetooth

// Pines del BTS7960 (Motor)
#define BTS7960_L_PWM 26
#define BTS7960_R_PWM 18
#define BTS7960_EN 19

// Pin para medir la batería
#define PIN_BATERIA A0 // Pin analógico conectado a la batería

// Variables para luces
bool luzNocturnaActiva = false;
bool luzLargasActiva = false;
bool intermitenteDerechoActivo = false;
bool intermitenteIzquierdoActivo = false;
bool warningsActivos = false;
bool amplificadorActivo = false;
unsigned long tiempoIntermitente = 0;
bool estadoIntermitente = false;

// Variables para el control del motor
int velocidadMotor = 0;
int direccionActual = 0; // 0: detenido, 1: adelante, -1: atrás

// Variables para la batería
float voltajeBateria = 0.0;
const float VOLTAJE_MINIMO = 10.0; // Voltaje mínimo (batería vacía)
const float VOLTAJE_MAXIMO = 12.6; // Voltaje máximo (batería cargada)

// Configuración inicial
void setup() {
    Serial.begin(115200);

    // Configuración de pines
    pinMode(LUZ_NOCTURNA_Y_LARGAS, OUTPUT);
    pinMode(LUZ_TRASERA, OUTPUT);
    pinMode(INTERMITENTE_DERECHO, OUTPUT);
    pinMode(INTERMITENTE_IZQUIERDO, OUTPUT);
    pinMode(AMPLIFICADOR_BLUETOOTH, OUTPUT);
    pinMode(BTS7960_EN, OUTPUT);

    // Configurar PWM para BTS7960 y luces
    ledcSetup(0, 5000, 8);
    ledcAttachPin(BTS7960_L_PWM, 0);
    ledcSetup(1, 5000, 8);
    ledcAttachPin(BTS7960_R_PWM, 1);
    ledcSetup(2, 5000, 8); // PWM para luces nocturnas y largas
    ledcAttachPin(LUZ_NOCTURNA_Y_LARGAS, 2);
    ledcSetup(3, 5000, 8); // PWM para luces traseras
    ledcAttachPin(LUZ_TRASERA, 3);

//CAMBIAR LA MAC POR LA DEL EQUIPO DE ULTIMA CONEXION CON EL MANDO
    if (PS4.begin("XX:XX:XX:XX:XX:XX")) {
        Serial.println("Esperando conexión con el mando PS4...");
    } else {
        Serial.println("Error al iniciar la conexión Bluetooth.");
    }
}

// Función para controlar las luces nocturnas y largas
void controlarLuces(bool nocturna, bool largas) {
    if (largas) {
        ledcWrite(2, 233); // Aproximadamente 11V
    } else if (nocturna) {
        ledcWrite(2, 100); // Aproximadamente 8V
    } else {
        ledcWrite(2, 0); // Apagar las luces
    }
}

// Función para controlar las luces traseras. AJUSTAR PARAMETROS SEGUN VOLTAJES NECESARIOS
void controlarLuzTrasera(bool nocturna, bool parado) {
    if (parado) {
        Serial.println("Luces traseras: Modo freno activado");
        ledcWrite(3, 20); // PWM más alto para luz de freno
    } else if (nocturna) {
        Serial.println("Luces traseras: Modo nocturno");
        ledcWrite(3, 5); // PWM bajo para luz trasera en modo nocturno
    } else {
        Serial.println("Luces traseras: Apagadas");
        ledcWrite(3, 0); // Apagar luces traseras
    }
}

// Función para controlar el motor con BTS7960
void controlarMotor(int direccion, int velocidad) {
    velocidad = constrain(velocidad, 0, 255);
    digitalWrite(BTS7960_EN, HIGH);

    if (direccion == 1) { // Adelante
        ledcWrite(0, velocidad);
        ledcWrite(1, 0);
    } else if (direccion == -1) { // Atrás
        ledcWrite(0, 0);
        ledcWrite(1, velocidad);
    } else { // Detenido
        digitalWrite(BTS7960_EN, LOW);
        ledcWrite(0, 0);
        ledcWrite(1, 0);
    }
}

// Manejar intermitentes y warnings
void manejarIntermitentes() {
    unsigned long tiempoActual = millis();

    if (warningsActivos) {
        if (tiempoActual - tiempoIntermitente >= 500) {
            tiempoIntermitente = tiempoActual;
            estadoIntermitente = !estadoIntermitente;
            digitalWrite(INTERMITENTE_DERECHO, estadoIntermitente ? HIGH : LOW);
            digitalWrite(INTERMITENTE_IZQUIERDO, estadoIntermitente ? HIGH : LOW);
        }
    } else {
        if (intermitenteDerechoActivo) {
            if (tiempoActual - tiempoIntermitente >= 500) {
                tiempoIntermitente = tiempoActual;
                estadoIntermitente = !estadoIntermitente;
                digitalWrite(INTERMITENTE_DERECHO, estadoIntermitente ? HIGH : LOW);
            }
        } else {
            digitalWrite(INTERMITENTE_DERECHO, LOW);
        }

        if (intermitenteIzquierdoActivo) {
            if (tiempoActual - tiempoIntermitente >= 500) {
                tiempoIntermitente = tiempoActual;
                estadoIntermitente = !estadoIntermitente;
                digitalWrite(INTERMITENTE_IZQUIERDO, estadoIntermitente ? HIGH : LOW);
            }
        } else {
            digitalWrite(INTERMITENTE_IZQUIERDO, LOW);
        }
    }
}

// Loop principal
void loop() {
    if (PS4.isConnected()) {
        // Luces nocturnas (Circle)
        if (PS4.Circle()) {
            luzNocturnaActiva = !luzNocturnaActiva;
            if (!luzNocturnaActiva) luzLargasActiva = false; // Apagar largas si nocturnas se desactivan
            controlarLuces(luzNocturnaActiva, luzLargasActiva);
            Serial.println(luzNocturnaActiva ? "Luces nocturnas encendidas" : "Luces nocturnas apagadas");
            delay(200);
        }

        // Luces largas (Square)
        if (PS4.Square()) {
            luzLargasActiva = !luzLargasActiva;
            if (luzLargasActiva) {
                controlarLuces(false, true); // Activar largas
            } else {
                controlarLuces(luzNocturnaActiva, false); // Volver a nocturnas si estaban activas
            }
            Serial.println(luzLargasActiva ? "Luces largas encendidas" : "Luces largas apagadas");
            delay(200);
        }

        // Intermitentes (R1 y L1)
        if (PS4.R1()) {
            intermitenteDerechoActivo = !intermitenteDerechoActivo;
            Serial.println(intermitenteDerechoActivo ? "Intermitente derecho activado" : "Intermitente derecho desactivado");
            delay(200);
        }
        if (PS4.L1()) {
            intermitenteIzquierdoActivo = !intermitenteIzquierdoActivo;
            Serial.println(intermitenteIzquierdoActivo ? "Intermitente izquierdo activado" : "Intermitente izquierdo desactivado");
            delay(200);
        }
        if (PS4.Triangle()) {
            warningsActivos = !warningsActivos;
            Serial.println(warningsActivos ? "Warnings activados" : "Warnings desactivados");
            delay(200); // Evitar rebotes
        }

        // Regular velocidad con R2 y L2
        int valorR2 = PS4.R2Value(); // Rango de 0 a 255
        int valorL2 = PS4.L2Value(); // Rango de 0 a 255

        if (valorR2 > 0) {
            direccionActual = 1; // Adelante
            velocidadMotor = valorR2;
        } else if (valorL2 > 0) {
            direccionActual = -1; // Atrás
            velocidadMotor = valorL2;
        } else {
            direccionActual = 0; // Detenido
            velocidadMotor = 0;
        }

        controlarMotor(direccionActual, velocidadMotor);

        // Controlar luces traseras
        bool frenoActivo = (direccionActual == 0 && velocidadMotor == 0);
        controlarLuzTrasera(luzNocturnaActiva, frenoActivo);

        // Manejar intermitentes
        manejarIntermitentes();
    } else {
        Serial.println("Mando desconectado. Esperando conexión...");
        delay(1000);
    }
}



Configuración en PlatformIO

El archivo platformio.ini contiene la configuración necesaria para este proyecto:

[env:wemos_d1_mini32]
platform = espressif32
board = wemos_d1_mini32
framework = arduino

; Configurar el monitor serial a 115200
monitor_speed = 115200

; Dependencias necesarias
lib_deps =
    https://github.com/aed3/PS4-esp32.git

Resultado final

Con esta configuración, el ESP32 puede:

  • Activar y desactivar luces nocturnas y largas mediante el botón circulo y cuadrado del mando PS4.
  • Controlar intermitentes y warnings con los botones L1, R1 y triángulo.
  • Ajustar la dirección y velocidad del motor con R2 y L2.

Esta implementación es ideal para proyectos de vehículos DIY, proporcionando un sistema de control sencillo pero completo.


https://youtu.be/fK-i0rwnWNA

Para más proyectos, visita nuestra web principal.

About Author

Artículos recomendados

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *