Electrónica y programación para prototipo con ESP32, LCD, Controladoras de Motor paso a paso y transistor para motor DC y resistencia de sellado.
Categoría: ESP32
-
Conectar dos placas ESP32 con Bluetooth

Ultima actualización: 7/5/2025
Primeros pasos con ESP32 Bluetooth Low Energy (BLE) en Arduino IDE – Bluetooth de Bajo Consumo de Energía

El ESP32 cuenta con con Bluetooth Clásico y Bluetooth Low Energy (BLE)
Esta publicación es una introducción a BLE con el ESP32.
En esta sección: ¿Qué es BLE y para qué se puede usar?
También algunos ejemplos con el ESP32 usando Arduino IDE.
¿Qué es Bluetooth de baja energía?
Bluetooth Low Energy, BLE para abreviar, es una variante de ahorro de energía de Bluetooth. La aplicación principal de BLE es la transmisión a corta distancia de pequeñas cantidades de datos (bajo ancho de banda).A diferencia de Bluetooth Clásico, que siempre está activado, BLE permanece en modo de suspensión constantemente, excepto cuando se inicia una conexión.
Comparado con Bluetooth clásico, Bluetooth Low Energy está diseñado para proporcionar un bajo consumo de energía, manteniendo un rango de alcance de comunicación similar.
Esto hace que consuma muy poca energía. BLE consume aproximadamente 100 veces menos energía que Bluetooth (según el caso de uso).
Además, BLE admite no solo la comunicación punto a punto, sino también el modo de transmisión y la red de malla.
Servidor y cliente BLE
Con Bluetooth Low Energy, hay dos tipos de dispositivos: el servidor y el cliente.
El ESP32 puede actuar como cliente o como servidor. El servidor anuncia su existencia, por lo que otros dispositivos pueden encontrarlo y contiene datos que el cliente puede leer. El cliente escanea los dispositivos cercanos y, cuando encuentra el servidor que está buscando, establece una conexión y escucha los datos entrantes. Esto se llama comunicación punto a punto.
Hay otros modos de comunicación posibles, como el modo de transmisión y la red de malla.
GATT
GATT significa Atributos Genéricos y define una estructura de datos jerárquica que está expuesta a los dispositivos BLE conectados. Esto significa que GATT define la forma en que dos dispositivos BLE envían y reciben mensajes estándar. Comprender esta jerarquía es importante porque facilitará la comprensión de cómo usar BLE con el ESP32.

Perfil: colección estándar de servicios para un caso de uso específico;
Servicio: recopilación de información relacionada, como lecturas de sensores, nivel de batería, frecuencia cardíaca, etc.;
Característica: es donde se guardan los datos reales en la jerarquía (valor);
Descriptor: metadatos sobre los datos;
Propiedades: describe cómo se puede interactuar con el valor característico. Por ejemplo: leer, escribir, notificar, difundir, indicar, etc.
En nuestro ejemplo, crearemos un servicio con dos características.
Uno para la temperatura y otro para la humedad.
Las lecturas reales de temperatura y humedad se guardan en el valor bajo sus características. Cada característica tiene la propiedad de notificación, de modo que notifique al cliente cada vez que cambien los valores.
UUI
Cada servicio, característica y descriptor tiene un UUID (Universally Unique Identifier). Un UUID es un número único de 128 bits (16 bytes).
Por ejemplo:
55072829-bc9e-4c53-938a-74a6d4c78776
Hay UUID abreviados para todos los tipos, servicios y perfiles especificados en el SIG (Bluetooth Special Interest Group).
Si su aplicación necesita su propio UUID, puede generarlo utilizando este sitio web generador de UUID.
En resumen, el UUID se utiliza para identificar información de manera única. Por ejemplo, puede identificar un servicio particular proporcionado por un dispositivo Bluetooth.
Conectando el ESP32
Este ejemplo funcionaría para cualquier placa de desarrollo actual con ESP-32. En este caco se utilizaron las siguientes placas:

Heltec ESP32 Lora V2, LolinD32, NodeMCU ESP32S Sketch para Servidor BLE
#define LED_BUILTIN 2 #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #define temperatureCelsius #define BLE_server "ESP32_Server" #define SERVICE_UUID "huecat23-6d3c-4a17-a71f-ece2e6075f9b" BLECharacteristic dhtTemperatureCelsiusCharacteristics("huecat23-c85e-4596-9bd9-015e2eaa4888", BLECharacteristic::PROPERTY_NOTIFY); BLEDescriptor dhtTemperatureCelsiusDescriptor(BLEUUID((uint16_t)0x2902)); BLECharacteristic dhtHumidityCharacteristics("huecat23-4a2f-4cf3-96e6-38b79be71a61", BLECharacteristic::PROPERTY_NOTIFY); BLEDescriptor dhtHumidityDescriptor(BLEUUID((uint16_t)0x2903)); bool device_connected = false; class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { device_connected = true; }; void onDisconnect(BLEServer* pServer) { device_connected = false; } }; void setup() { Serial.begin(115200); BLEDevice::init(BLE_server); BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *dhtService = pServer->createService(SERVICE_UUID); dhtService->addCharacteristic(&dhtTemperatureCelsiusCharacteristics); dhtTemperatureCelsiusDescriptor.setValue("DHT Temperature (Celsius)"); dhtTemperatureCelsiusCharacteristics.addDescriptor(new BLE2902()); dhtService->addCharacteristic(&dhtHumidityCharacteristics); dhtHumidityDescriptor.setValue("DHT humidity"); dhtHumidityCharacteristics.addDescriptor(new BLE2902()); dhtService->start(); pServer->getAdvertising()->start(); Serial.println("Esperando a Cliente Bluetooth"); } void loop() { //Timer cada 5 segundos: envía la info por bluetooth static unsigned long enviaDato; if (millis() > enviaDato + 5000) { enviaDato = millis(); ///////////////////////////////// if (device_connected) { //Datos de prueba float temp = 25; float hum = 88; static char temperature_celsius[7]; dtostrf(temp, 6, 2, temperature_celsius); dhtTemperatureCelsiusCharacteristics.setValue(temperature_celsius); dhtTemperatureCelsiusCharacteristics.notify(); Serial.print("Temperatura: "); Serial.print(temp); Serial.print(" *C"); static char humidity[7]; dtostrf(hum, 6, 2, humidity); dhtHumidityCharacteristics.setValue(humidity); dhtHumidityCharacteristics.notify(); Serial.print(" Humedad: "); Serial.print(hum); Serial.println(" %"); } } //Parpadeo del LED static unsigned long parpadeo; if (millis() > parpadeo + 80) { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); parpadeo = millis(); } }Sketch para el Cliente BLE
#include "BLEDevice.h" #include "heltec.h" #include "Arduino.h" SSD1306Wire display(0x3c, SDA_OLED, SCL_OLED, RST_OLED); //128_64 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define temperatureCelsius #define BLE_server "ESP32_Server" // Generador de UUIDs: // https://www.uuidgenerator.net/ //*********************************** //BLE ID UNICO PARA SERVICIO static BLEUUID dhtServiceUUID("huecat23-6d3c-4a17-a71f-ece2e6075f9b"); //*********************************** //BLE ID UNICO PARA CARACTERÍSTICA (TEMPERATURA) static BLEUUID temperatureCharacteristicUUID("huecat23-c85e-4596-9bd9-015e2eaa4888"); //BLE ID UNICO PARA CARACTERÍSTICA (HUMEDAD) static BLEUUID humidityCharacteristicUUID("huecat23-4a2f-4cf3-96e6-38b79be71a61"); /* //*********************************** //BLE ID UNICO PARA SERVICIO static BLEUUID dhtServiceUUID("d29181ad-6d3c-4a17-a71f-ece2e6075f9b"); //*********************************** //BLE ID UNICO PARA CARACTERÍSTICA (TEMPERATURA) static BLEUUID temperatureCharacteristicUUID("ea4963df-c85e-4596-9bd9-015e2eaa4888"); //BLE ID UNICO PARA CARACTERÍSTICA (HUMEDAD) static BLEUUID humidityCharacteristicUUID("b61decbb-4a2f-4cf3-96e6-38b79be71a61"); */ static boolean bleConectado = false; static boolean connected = false; static BLEAddress *pServerAddress; static BLERemoteCharacteristic* temperatureCharacteristic; static BLERemoteCharacteristic* humidityCharacteristic; const uint8_t notificationOn[] = {0x1, 0x0}; const uint8_t notificationOff[] = {0x0, 0x0}; bool conectarAServidor(BLEAddress pAddress) { BLEClient* pClient = BLEDevice::createClient(); pClient->connect(pAddress); Serial.println("Conectado al Servidor"); BLERemoteService* pRemoteService = pClient->getService(dhtServiceUUID); if (pRemoteService == nullptr) { Serial.print("Failed to find our service UUID: "); Serial.println(dhtServiceUUID.toString().c_str()); return (false); } temperatureCharacteristic = pRemoteService->getCharacteristic(temperatureCharacteristicUUID); humidityCharacteristic = pRemoteService->getCharacteristic(humidityCharacteristicUUID); if (temperatureCharacteristic == nullptr || humidityCharacteristic == nullptr) { Serial.print("Failed to find our characteristic UUID"); return false; } Serial.println(" Characteristics Found!"); temperatureCharacteristic->registerForNotify(temperatureNotifyCallback); humidityCharacteristic->registerForNotify(humidityNotifyCallback); } class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { if (advertisedDevice.getName() == BLE_server) { advertisedDevice.getScan()->stop(); pServerAddress = new BLEAddress(advertisedDevice.getAddress()); bleConectado = true; Serial.println("Dispositivo encontrado. Conectando..."); } } }; static void temperatureNotifyCallback(BLERemoteCharacteristic*pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { String informarTemperatura = ""; informarTemperatura = "Temperatura: "; informarTemperatura += (char*)pData; informarTemperatura += " *C"; imprimirConAltura(informarTemperatura, 20); ////// IMPRIME OLED Y SERIAL ////// } static void humidityNotifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { String informarHumedad = "Humedad: "; informarHumedad += (char*)pData; informarHumedad += " %"; //imprimirConAltura(informarHumedad, 28); ////// IMPRIME OLED Y SERIAL ////// Serial.println(informarHumedad); } void setup() { Serial.begin(115200); Serial.println("\nESP-32--B-BLE-CLIENTE"); ///////////////////////////////////////// PARA PANTALLA OLED initHeltecEsp32(); //Inicializaciones correspondientes a modelo Pantalla OLED elegido. imprimirConAltura("Comenzando conexión BLE ( Cliente)", 0); ////// IMPRIME OLED Y SERIAL ////// BLEDevice::init(""); BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->start(30); } void loop() { if (bleConectado == true) { if (conectarAServidor(*pServerAddress)) { String conectando = "Conectado servidor BLE."; imprimirConAltura(conectando, 8); ////// IMPRIME OLED Y SERIAL ////// temperatureCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); humidityCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notificationOn, 2, true); connected = true; } else { String conectando_error = "Falló conexión Servidor BLE"; imprimirConAltura(conectando_error, 8); ////// IMPRIME OLED Y SERIAL ////// } bleConectado = false; } delay(1000); } //Basado en ejemplo Heltec OLED_rotate.ino void VextON(void) { pinMode(Vext, OUTPUT); digitalWrite(Vext, LOW); } void VextOFF(void) //Vext default OFF { pinMode(Vext, OUTPUT); digitalWrite(Vext, HIGH); } void initHeltecEsp32() { VextON(); delay(100); display.init(); display.clear(); display.display(); display.setContrast(1); display.setTextAlignment(TEXT_ALIGN_CENTER); display.clear(); display.display(); display.screenRotate(ANGLE_0_DEGREE); display.setFont(ArialMT_Plain_16); display.drawString(64, 32 - 16 / 2, "HUE CAT"); //ROTATE_0 display.display(); delay(400); display.clear(); display.display(); display.screenRotate(ANGLE_90_DEGREE); display.setFont(ArialMT_Plain_10); display.drawString(32, 64 - 10 / 2, "HUE CAT"); //ROTATE_90 display.display(); delay(400); display.clear(); display.display(); display.screenRotate(ANGLE_180_DEGREE); display.setFont(ArialMT_Plain_16); display.drawString(64, 32 - 16 / 2, "HUE CAT"); //ROTATE_180 display.display(); delay(400); display.clear(); display.display(); display.screenRotate(ANGLE_270_DEGREE); display.setFont(ArialMT_Plain_10); display.drawString(32, 64 - 10 / 2, "HUE CAT"); //ROTATE_270 display.display(); delay(400); display.clear(); display.display(); display.screenRotate(ANGLE_0_DEGREE); display.setFont(ArialMT_Plain_16); display.drawString(64, 32 - 16 / 2, "HUE CAT"); //ROTATE_0 display.display(); delay(500); display.clear(); display.display(); display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_10); } void imprimirConAltura(String stringToPrint, int alturaAImprimir) { //Imprime en monitor serie y display Serial.print("OLED->" + stringToPrint); display.drawString(0, alturaAImprimir, stringToPrint); display.display(); } -
Arduino IDE: Compilar código para ESP32/ESP8266
Arduino IDE es un compilador que hace que insertar lógica en lenguaje C sea muy fácil, sobre todo si la placa que compras es marca Arduino pues viene con el “CORE” pre-instalado.
Cuando utilizamos placas de otros fabricante o incluso microcontroladores que no se encuentran en estas placas marca Arduino, tenemos muchas veces a disposición Frameworks de diversos fabricantes, como es el caso de los microcontroladores ESPRESSIF: ESP8266 y ESP32
Luego de tener instalado el driver del FTDI en nuestro ordenador, se procede a decirle al “Arduino IDE” desde qué dirección cargar placas adicionales.
Archivo > Preferencias

Puedes compilar este código con Arduino IDE https://arduino.esp8266.com/stable/package_esp8266com_index.json
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Si quieres tener instalados los firmwares de ambos microcontroladores, puedes separar los link con una “,”
https://arduino.esp8266.com/stable/package_esp8266com_index.json, https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Ver https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md para más detalles.
¿Cómo verificar si el microcontrolador se instaló correctamente?
Ahora que ha instalado ESP32 en su “Arduino IDE”, si desea saber si desea instalar ESP32/8266 en Arduino IDE correctamente o no. Puede verificarlo usando un ejemplo simple ya disponible en Arduino IDE para la placa de desarrollo ESP32 para Internet de las cosas. Cuando instala la biblioteca ESP32 en Arduino IDE, estos ejemplos también se instalan.Se pueden seguir estos pasos:
1. conectar tu placa con una computadora a través de un cable USB.
2. Conectar la placa con una computadora, seleccione la placa que está utilizando.
Hay muchos tipos de placas ESP32/8266 disponibles en el mercado. Suelo preferir la versión de ALIExpress Wemos D32 que incluye AUTOFLASH. Pero puedes usar cualquier tablero que quieras. Para seleccionar la placa, ir a herramientas>Placas, clic en el módulo de Desarrollo. Imagen a continuación:

Ahora selección del puerto:

Ahora subir el Sketch (Control+U)

-
¿Cómo funciona el wifiManager? para ESP32/ESP8266
La librería WiFiManager simplifica el proceso de configuración y gestión de conexiones WiFi en los módulos ESP32 y ESP8266. Proporciona una forma fácil de configurar y almacenar las credenciales de red WiFi, permitiendo que los dispositivos se conecten a las redes de manera autónoma y se recuperen de forma automática en caso de desconexiones.

El “WiFiManager” es una biblioteca diseñada para facilitar la configuración y administración del Wi-Fi en dispositivos IoT basados en los microcontroladores ESP32 y ESP8266. Esta biblioteca ofrece una forma conveniente de crear un portal de configuración basado en la web, lo que permite a los usuarios ingresar las credenciales de Wi-Fi sin necesidad de cargar un nuevo código en el dispositivo.
El proceso de funcionamiento del WiFiManager se puede describir en los siguientes pasos:
- Inclusión de la biblioteca: En primer lugar, es necesario incluir la biblioteca WiFiManager en el proyecto. Esto se puede realizar descargando e instalando la biblioteca desde el administrador de bibliotecas de Arduino IDE o mediante el uso de un gestor de paquetes como PlatformIO.
- Creación de una instancia del WiFiManager: Se crea una instancia del objeto WiFiManager en el código del proyecto.
#include <WiFiManager.h> WiFiManager wifiManager;
Inicialización y conexión:
Antes de utilizar el WiFiManager, es necesario inicializarlo y conectarlo al punto de acceso Wi-Fi existente. Si se encuentran credenciales de Wi-Fi almacenadas previamente, el dispositivo se conectará automáticamente. En caso contrario, se iniciará el portal de configuración.
void setup() { // Inicializar el WiFiManager wifiManager.autoConnect("MiDispositivo"); // Resto del código de configuración o funcionalidad }En el ejemplo anterior, “MiDispositivo” es el nombre del punto de acceso que se creará si no se encuentran credenciales de Wi-Fi almacenadas. Este nombre puede modificarse según las preferencias del usuario.
Portal de configuración:
Si no se encuentran credenciales de Wi-Fi almacenadas, el WiFiManager iniciará un portal de configuración. Esto implica que el ESP32/ESP8266 actuará como un punto de acceso Wi-Fi al cual es posible conectarse desde un dispositivo móvil o una computadora.
Al conectarse a este punto de acceso, se abrirá automáticamente una página de configuración basada en la web, donde los usuarios pueden ingresar las credenciales de su red Wi-Fi. Una vez que las credenciales se ingresen y envíen, el ESP32/ESP8266 se conectará a la red Wi-Fi especificada y recordará estas credenciales para futuros usos.
Almacenamiento de la configuración:
Después de que el WiFiManager se conecte exitosamente a la red Wi-Fi especificada, almacenará las credenciales en la memoria no volátil del dispositivo (por ejemplo, en el ESP32/ESP8266). Esto permite que las credenciales se utilicen en las próximas ejecuciones, sin necesidad de ingresarlas nuevamente cada vez que se reinicie el dispositivo.
-
Placa OLED TTGO LoRa32 SX1276
LoRa es una tecnología inalámbrica versátil y eficiente en energía que se utiliza comúnmente en aplicaciones de IoT, seguimiento remoto y comunicaciones de larga distancia. Su capacidad para alcanzar distancias significativas con bajo consumo de energía la hace adecuada para una variedad de casos de uso en los que se requiere una conectividad inalámbrica confiable y de bajo costo.

TTGO LoRa32 SX1276 OLED es una placa de desarrollo ESP32 con un chip LoRa integrado y una pantalla OLED SSD1306 de 0,96 pulgadas. En esta guía, le mostraremos cómo: enviar y recibir paquetes LoRa (comunicación punto a punto) y usar la pantalla OLED con Arduino IDE.
Utilizando Arduino IDE para la comunicación LoRa y la pantalla OLED SSD1306 de 0,96 pulgadas. Asegúrate de que ya tengas Arduino IDE instalado en tu computadora antes de empezar.
Paso 1: Preparación del Hardware
Asegurarse de que la placa TTGO LoRa32 SX1276 OLED esté correctamente conectada al ordenador a través de un cable USB.
Paso 2: Instalación del Soporte de ESP32 en Arduino IDE
- Abrir Arduino IDE.
- “Archivo” -> “Preferencias”.
- En la sección “URLs adicionales de tarjetas de gestor de tarjetas”, agregar la siguiente URL, clic en
https://dl.espressif.com/dl/package_esp32_index.json- “Herramientas” -> “Placa” -> “Gestor de tarjetas…”
- Busca “esp32” e instala el soporte para ESP32 de Espressif.
Paso 3: Instalación de las Bibliotecas Necesarias
Para utilizar LoRa y la pantalla OLED, se debe instalar las siguientes bibliotecas:
- Biblioteca ESP32 LoRa: “Herramientas” -> “Gestor de Bibliotecas…”, buscar “ESP32 LoRa”. Instala la biblioteca proporcionada por Sandeep Mistry.
- Biblioteca Adafruit SSD1306: “Herramientas” -> “Gestor de Bibliotecas…”, buscar “Adafruit SSD1306”. Instalar la biblioteca de Adafruit.
Paso 4: Código de Ejemplo para la Comunicación LoRa
A continuación, un ejemplo de código básico para enviar y recibir datos LoRa entre dos placas TTGO LoRa32 SX1276 OLED.
#include <Wire.h> #include <Adafruit_SSD1306.h> #include <SPI.h> #include <LoRa.h> #define OLED_RESET -1 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { if (!LoRa.begin(433E6)) { Serial.println("Error initializing LoRa."); while (1); } display.begin(SSD1306_I2C_ADDRESS, OLED_RESET); display.display(); delay(2000); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 0); display.print("LoRa Sender"); display.display(); delay(2000); } void loop() { display.clearDisplay(); display.setCursor(0, 0); display.print("Sending LoRa..."); display.display(); // Enviar un mensaje LoRa.beginPacket(); LoRa.print("¡Hola, mundo!"); LoRa.endPacket(); delay(10000); // Esperar 10 segundos antes de enviar el siguiente mensaje } -
Enviar información a ThingSpeak desde ESP32/ESP8266
Este fantástico módulo que cuesta menos que una hamburguesa en España, no solo tiene bluetooth, dos núcleos y sensores touch… sino que también tiene Wi-Fi!

Así que aprovecharemos esta funcionalidad para enviar datos a la nube, a un broker Mqtt. Mqtt es un estándar de comunicaciones muy eficientes originalmente de la industria del petróleo, ahora Liberado y disponible para para casas, industrias, y millones de proyectos IoT
Asegúrate de tener instalado el CORE del ESP32/ESP8266
-
ESP32 / ESP8266 Escribir en una Base de datos MySQL usando PHP y Arduino IDE
Este artículo pretende explicar cómo conectar un módulo con un ESP32/ESP8266 a un servidor WEB que reciba los datos.
El microcontrolador será el cliente de una “página WEB”, accederá con información a un vínculo para insertar información en una Base de Datos
Actualizado: 2/7/2025
CONTEXTO
Insertar datos directamente en una base MySQL desde un microcontrolador resulta sencillo, pero puede presentar riesgos de seguridad y escalabilidad. Como alternativa, se puede usar una API REST o un broker MQTT. Este artículo muestra un enfoque con PHP y HTTP, con medidas básicas de protección.
-
Manual de configuración para Wi-Fi en microcontoladores ESP8266 y ESP32: Creación de un driver LED
Melange con Argie incorporó un sistema de configuración de sus dispositivos a través de tecnología Wi-Fi desarrollado por HUE CAT

