Si ya armaste el UNIT Robot Escalador V1 y quieres controlarlo de forma inalámbrica mediante Bluetooth BLE utilizando la UNIT Pulsar ESP32-C6, en este tutorial aprenderás a crear una interfaz web interactiva para controlar el movimiento del robot, activar la turbina y comunicarte en tiempo real utilizando tecnología Web Bluetooth desde tu computadora o smartphone compatible.
Al finalizar este tutorial podrás:
- Bases necesarias para desarrollar futuros proyectos de robótica móvil, IoT y control inalámbrico mediante BLE.
- Controlar el UNIT Robot Escalador V1 mediante Bluetooth BLE utilizando la UNIT Pulsar ESP32-C6.
- Conectar el robot desde una interfaz web interactiva compatible con tecnología Web Bluetooth.
- Enviar comandos inalámbricos de avance, retroceso y giro en tiempo real.
- Activar o desactivar la turbina brushless directamente desde la interfaz web.
- Comprender cómo se comunican el firmware del ESP32-C6 y una página desarrollada en HTML, CSS y JavaScript.
- Implementar una función de seguridad tipo watchdog, capaz de detener automáticamente los motores si se pierde la comunicación BLE.
MATERIALES
¡Manos a la obra! Antes de empezar, asegúrate de tener a la mano los siguientes materiales:
- UNIT Robot Escalador V1
- Fuente Conmutada 12V 30A
- Par Cables XT60 12AWG 15cm
- Cables de Silicona Flexible Negro 16 AWG 13A
- Cables de Silicona Flexible Rojo 16 AWG 13A
DESARROLLO
¡Listo! Ahora sí, comencemos con el tutorial. Sigue los pasos que se indican a continuación.
1- Armado del UNIT Robot Escalador
Antes de comenzar con este tutorial es importante que el UNIT Robot Escalador V1 ya se encuentre correctamente armado y funcionando mediante control WiFi. Esto asegurará que tanto los motores, la turbina brushless, el ESC y la electrónica del robot estén operando adecuadamente antes de implementar el control mediante Bluetooth BLE.
Si aún no has realizado el armado y programación inicial del robot, te recomendamos seguir primero los siguientes tutoriales para completar correctamente la construcción y configuración del proyecto:
Ensamble del UNIT Robot Escalador V1 (Pared y Techo)
Programación UNIT Robot Escalador
2- Configuración de entorno de programación
Para trabajar correctamente con las librerías de Bluetooth BLE en Arduino IDE es necesario tener instaladas las tarjetas ESP32 de Espressif Systems, ya que estas incluyen las librerías y dependencias necesarias para utilizar el Bluetooth BLE integrado en la UNIT Pulsar ESP32-C6.
Si tienes instaladas versiones antiguas, incompatibles o paquetes ESP32 de otros desarrolladores, es muy probable que aparezcan errores de compilación relacionados con BLE, librerías faltantes o conflictos internos del framework.
Uno de los errores más comunes es:
fatal error: esp_gatts_api.h: No such file or directory
Para evitar este tipo de problemas, te recomendamos seguir los siguientes pasos y verificar que las tarjetas ESP32 instaladas en Arduino IDE correspondan únicamente a las oficiales de Espressif Systems.
- Valida o Agrega las placas de ESP32 de Espressif a URLs adicionales de Arduino IDE

- Instala las placas ESP32 de Espressif desde el Gestor de placas de Arduino IDE
- Después de agregar la URL a preferencias dirígete a la pestaña Herramientas > Placa > Gestor de placas, busca “ESP32 de Espressif” e instala las placas.
- Espera a que se termine de instalar todas las tarjetas el proceso puede tardar.

PROGRAMACIÓN
Una vez que validaste o instalaste correctamente las tarjetas ESP32 de Espressif Systems en Arduino IDE, y además ya tienes ensamblado y funcionando mediante WiFi el UNIT Robot Escalador V1, podemos continuar con la programación del proyecto utilizando Bluetooth BLE.
Es importante comprender que este sistema se compone de dos partes principales que trabajan en conjunto para lograr el control inalámbrico del robot.
Por un lado, tenemos el programa desarrollado en Arduino IDE, el cual será cargado en la UNIT Pulsar ESP32-C6. Este firmware permitirá que la tarjeta funcione como un servidor Bluetooth BLE, encargado de generar la señal Bluetooth y gestionar toda la comunicación inalámbrica para recibir y enviar información en tiempo real, permitiendo controlar los movimientos del robot escalador.
Por otro lado, desarrollaremos una interfaz web BLE utilizando HTML, CSS y JavaScript, la cual se ejecutará directamente desde el navegador web. Esta interfaz será la encargada de buscar, detectar y conectarse al dispositivo BLE, además de enviar los comandos necesarios para controlar el robot de forma visual e interactiva desde una computadora o smartphone compatible.
Gracias a la integración entre ambas partes, se crea un sistema completo de control inalámbrico, aprovechando las capacidades Bluetooth BLE de la UNIT Pulsar ESP32-C6 y las funciones Web Bluetooth del navegador.
Ahora sí, continúa con los siguientes pasos para comenzar la programación.
Programar la UNIT Pulsar ESP32-C6
Este código permite que la UNIT Pulsar ESP32-C6 funcione como un servidor Bluetooth BLE, al que una interfaz web puede conectarse para enviar comandos de control de forma inalámbrica. Con este programa es posible controlar el UNIT Robot Escalador V1, enviando instrucciones para avanzar, retroceder, girar a la izquierda y girar a la derecha.
Además, el código permite activar o desactivar la turbina brushless, utilizando un botón desde la interfaz web. También incorpora una función de seguridad tipo watchdog, que detiene automáticamente los motores si el robot deja de recibir comandos durante cierto tiempo, ayudando a evitar movimientos no deseados en caso de pérdida de conexión BLE.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <ESP32Servo.h>
// ======================
// Definición de pines TB6612FNG
// ======================
#define PWMA 5
#define AIN1 3
#define AIN2 4
#define PWMB 15
#define BIN1 20
#define BIN2 21
#define STBY 19
// ======================
// ESC
// ======================
Servo ESC;
const int vel_min = 1000;
const int vel_max = 1900;
#define ESC_PIN 9
// ======================
// LED
// ======================
#define LED_PIN 6
bool ledState = false;
// ======================
// Watchdog
// ======================
bool motorsActive = false;
unsigned long lastCommandTime = 0;
const unsigned long WATCHDOG_TIMEOUT_MS = 1200;
// ======================
// BLE UUIDs
// ======================
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" // Write
#define CHARACTERISTIC_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" // Notify
BLEServer* pServer = nullptr;
BLECharacteristic* pTxCharacteristic = nullptr;
bool deviceConnected = false;
bool oldDeviceConnected = false;
// ======================
// Prototipos
// ======================
void forwardMove();
void backwardMove();
void leftMove();
void rightMove();
void stopMotors();
void processCommand(String cmd);
void sendStatus(String msg);
void toggleLED_ESC();
// ======================
// Callbacks del servidor BLE
// ======================
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) override {
deviceConnected = true;
Serial.println("BLE cliente conectado");
stopMotors();
sendStatus("connected");
}
void onDisconnect(BLEServer* pServer) override {
deviceConnected = false;
Serial.println("BLE cliente desconectado");
stopMotors();
}
};
// ======================
// Callback de escritura BLE
// ======================
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic* pCharacteristic) override {
String cmd = pCharacteristic->getValue().c_str();
cmd.trim();
if (cmd.length() > 0) {
Serial.print("BLE cmd: ");
Serial.println(cmd);
lastCommandTime = millis();
processCommand(cmd);
}
}
};
// ======================
// Setup
// ======================
void setup() {
Serial.begin(115200);
delay(500);
Serial.println();
Serial.println("======================================");
Serial.println("Iniciando UNIT ROBOT ESCALADOR BLE");
Serial.println("======================================");
// Pines motores
pinMode(AIN1, OUTPUT);
pinMode(AIN2, OUTPUT);
pinMode(BIN1, OUTPUT);
pinMode(BIN2, OUTPUT);
pinMode(STBY, OUTPUT);
pinMode(PWMA, OUTPUT);
pinMode(PWMB, OUTPUT);
pinMode(LED_PIN, OUTPUT);
// Habilitar driver
digitalWrite(STBY, HIGH);
// Velocidad máxima fija
digitalWrite(PWMA, HIGH);
digitalWrite(PWMB, HIGH);
// Estado inicial LED
digitalWrite(LED_PIN, LOW);
ledState = false;
// ESC
ESC.setPeriodHertz(50);
ESC.attach(ESC_PIN, vel_min, vel_max);
ESC.writeMicroseconds(vel_min);
Serial.println("Armando ESC...");
delay(5000);
stopMotors();
lastCommandTime = millis();
// ======================
// BLE
// ======================
BLEDevice::init("UNIT ROBOT BLE");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService* pService = pServer->createService(SERVICE_UUID);
// Característica TX
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
// Característica RX
BLECharacteristic* pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_RX,
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->start();
Serial.println("BLE listo");
Serial.println("Nombre BLE: UNIT ROBOT BLE");
Serial.println("Esperando cliente...");
}
// ======================
// Loop
// ======================
void loop() {
// Watchdog de movimiento
if (motorsActive && (millis() - lastCommandTime > WATCHDOG_TIMEOUT_MS)) {
Serial.println("Watchdog: sin comandos recientes, deteniendo motores");
stopMotors();
sendStatus("stop");
}
// Reconectar advertising si se desconecta
if (!deviceConnected && oldDeviceConnected) {
delay(300);
pServer->startAdvertising();
Serial.println("Reiniciando advertising BLE...");
oldDeviceConnected = deviceConnected;
}
if (deviceConnected && !oldDeviceConnected) {
oldDeviceConnected = deviceConnected;
}
// Mensaje alive cada segundo
static unsigned long lastAlive = 0;
if (millis() - lastAlive >= 1000) {
if (deviceConnected) {
sendStatus("alive");
}
lastAlive = millis();
}
}
// ======================
// Procesar comandos
// ======================
void processCommand(String cmd) {
if (cmd == "fwd") {
forwardMove();
sendStatus("fwd");
} else if (cmd == "back") {
backwardMove();
sendStatus("back");
} else if (cmd == "left") {
leftMove();
sendStatus("left");
} else if (cmd == "right") {
rightMove();
sendStatus("right");
} else if (cmd == "stop") {
stopMotors();
sendStatus("stop");
} else if (cmd == "toggle-led") {
toggleLED_ESC();
} else if (cmd == "ping") {
sendStatus("pong");
} else {
sendStatus("cmd_unknown");
}
}
// ======================
// Funciones de movimiento
// ======================
void backwardMove() {
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, LOW);
digitalWrite(BIN1, HIGH);
digitalWrite(BIN2, LOW);
motorsActive = true;
Serial.println("Retroceder");
}
void forwardMove() {
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
motorsActive = true;
Serial.println("Avanzar");
}
void leftMove() {
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, HIGH);
digitalWrite(BIN1, HIGH);
digitalWrite(BIN2, LOW);
motorsActive = true;
Serial.println("Giro izquierda");
}
void rightMove() {
digitalWrite(AIN1, HIGH);
digitalWrite(AIN2, LOW);
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, HIGH);
motorsActive = true;
Serial.println("Giro derecha");
}
void stopMotors() {
digitalWrite(AIN1, LOW);
digitalWrite(AIN2, LOW);
digitalWrite(BIN1, LOW);
digitalWrite(BIN2, LOW);
motorsActive = false;
Serial.println("Motores detenidos");
}
// ======================
// Toggle estable LED + ESC
// ======================
void toggleLED_ESC() {
ledState = !ledState;
if (ledState) {
digitalWrite(LED_PIN, HIGH);
ESC.writeMicroseconds(vel_max);
Serial.println("ESC ACTIVADO");
sendStatus("led_on");
} else {
digitalWrite(LED_PIN, LOW);
ESC.writeMicroseconds(vel_min);
Serial.println("ESC DESACTIVADO");
sendStatus("led_off");
}
}
// ======================
// Enviar notificación BLE
// ======================
void sendStatus(String msg) {
if (deviceConnected && pTxCharacteristic != nullptr) {
pTxCharacteristic->setValue(msg.c_str());
pTxCharacteristic->notify();
}
}
Para cargar el código en la tarjeta, considera lo siguiente:
- No necesitas instalar librerías adicionales para Bluetooth BLE, ya que al instalar las tarjetas ESP32 de Espressif Systems estas incluyen lo necesario para trabajar con BLE.
- Sí necesitas instalar la librería ESP32Servo, ya que se utiliza para controlar la señal PWM del ESC encargado de activar la turbina brushless.
- Antes de compilar el código, selecciona la tarjeta en Arduino IDE:
Herramientas > Placa > ESP32 > ESP32C6 Dev Module
- Conecta la UNIT Pulsar ESP32-C6 a tu computadora mediante USB.
- Selecciona el Puerto COM correspondiente en Arduino IDE.
- Compila el código dando clic en el botón Verificar (✔️).
- Si aparece un error, revisa que tengas correctamente instaladas las tarjetas ESP32 de Espressif Systems.
- Asegúrate de no tener librerías BLE externas instaladas, ya que pueden generar conflictos con las librerías BLE incluidas en el framework ESP32.
- Si el código compila correctamente, haz clic en Subir (⬆️) para cargarlo a la tarjeta.
- Espera a que finalice la carga. Cuando el programa se haya cargado correctamente, la tarjeta estará lista para funcionar como dispositivo Bluetooth BLE con el nombre:
UNIT ROBOT BLE
Una vez cargado el programa, el robot podrá enlazarse desde la interfaz web BLE para comenzar las pruebas de control inalámbrico.
Programación de la interfaz web BLE
La interfaz web BLE es una página desarrollada con HTML, CSS y JavaScript que permite conectarse al UNIT Robot Escalador V1 directamente desde el navegador mediante tecnología Web Bluetooth, sin necesidad de instalar aplicaciones móviles adicionales.
Su objetivo es proporcionar una forma visual e interactiva de controlar el robot en tiempo real, permitiendo enviar comandos inalámbricos hacia la UNIT Pulsar ESP32-C6 para controlar el movimiento del robot y activar la turbina brushless mediante Bluetooth BLE.

La interfaz cuenta con botones de control para:
- Avanzar
- Retroceder
- Girar a la izquierda
- Girar a la derecha
- Activar o desactivar la turbina brushless
Además, incorpora indicadores visuales que muestran el estado de conexión BLE y los eventos que ocurren en tiempo real, como:
- Robot conectado
- Robot desconectado
- Movimiento activo
- Robot detenido
- Turbina activada
- Turbina desactivada
Una de las ventajas de esta interfaz es que utiliza eventos táctiles y de mouse compatibles con dispositivos móviles y computadoras, permitiendo controlar el robot simplemente manteniendo presionados los botones de dirección desde el navegador.
La comunicación entre la interfaz web y la UNIT Pulsar ESP32-C6 se realiza mediante servicios y características BLE, donde la página web:
- Busca dispositivos Bluetooth compatibles.
- Se conecta automáticamente al servicio BLE del robot.
- Envía comandos inalámbricos en tiempo real.
- Recibe notificaciones y estados desde el ESP32-C6.
Gracias a esta integración entre Web Bluetooth y la UNIT Pulsar ESP32-C6, es posible crear un sistema moderno de control inalámbrico para proyectos de robótica móvil, IoT y automatización utilizando únicamente un navegador web compatible como:
- Google Chrome
- Microsoft Edge
- Opera
Preferentemente en dispositivos Android o computadoras con soporte Bluetooth BLE.
Descarga de la interfaz web
Cómo usar la interfaz paso a paso
1. Descargar y preparar el archivo
- Descarga el archivo comprimido (.ZIP)
- Descomprímelo en tu computadora
- Ubica el archivo .HTML
2. Abrir la interfaz
- Abre el archivo con un navegador compatible como:
- Google Chrome
- Microsoft Edge
También puedes:
- Enviar el archivo a tu celular (por USB, correo o nube)
- Abrirlo directamente desde el navegador del teléfono
3. Conectarse al Bluetooth BLE
- Presiona el botón “Conectar” en la interfaz
- Selecciona UNIT ROBOT BLE en la lista de dispositivos
- Acepta el permiso de conexión del navegador
4. Controlar y visualizar datos
Una vez conectado podrás:
- Avanzar
- Retroceder
- Girar a la izquierda
- Girar a la derecha
- Activar o desactivar la turbina
⚠️ Consideraciones importantes
- Utiliza navegadores compatibles con Web Bluetooth (Chrome o Edge)
- Es necesario aceptar los permisos de conexión
- Mantén activado el Bluetooth en tu dispositivo
En el siguiente video tienes la referencia para realizar los pasos anteriores
CONCLUSIÓN
En este tutorial aprendiste a controlar el UNIT Robot Escalador V1 mediante Bluetooth BLE utilizando la UNIT Pulsar ESP32-C6 y una interfaz web interactiva desarrollada con HTML, CSS y JavaScript.
A lo largo del tutorial configuraste el entorno de programación en Arduino IDE, cargaste el firmware BLE en la tarjeta ESP32-C6 y desarrollaste una interfaz capaz de conectarse inalámbricamente al robot mediante tecnología Web Bluetooth, permitiendo controlar sus movimientos y activar la turbina en tiempo real desde un navegador compatible.
Además, comprendiste cómo funciona la comunicación entre el navegador y el ESP32-C6 mediante servicios y características BLE, así como la importancia de implementar funciones de seguridad como el watchdog, encargado de detener automáticamente el robot si se pierde la conexión o dejan de enviarse comandos.
Gracias a este proyecto ahora cuentas con una excelente base para continuar desarrollando aplicaciones de robótica móvil, IoT, automatización y control inalámbrico utilizando Bluetooth BLE. También puedes expandir fácilmente el sistema agregando nuevas funciones como sensores, monitoreo de batería, cámaras, modos autónomos o control desde dispositivos móviles.
Ahora es momento de experimentar, modificar el código y seguir creando nuevos proyectos con el potencial del Bluetooth BLE y la UNIT Pulsar ESP32-C6 🚀

