ESP32 - DIYables Bluetooth App Monitor

Overview

The Bluetooth Monitor example provides a wireless serial monitor interface accessible through the DIYables Bluetooth STEM app. Designed for ESP32 boards with support for both BLE (Bluetooth Low Energy) and Classic Bluetooth connections. Stream real-time status messages to the app, receive and process text commands, display system information, and debug your projects wirelessly — perfect for untethered monitoring, remote debugging, and system status displays.

This example supports two Bluetooth modes:

  • ESP32 BLE (Bluetooth Low Energy): Works on both Android and iOS
  • ESP32 Classic Bluetooth: Works on Android only. iOS does not support Classic Bluetooth. Use BLE if you need iOS support.
ESP32 Bluetooth Monitor Example - Real-Time Serial Monitor Interface Tutorial

Features

  • Real-Time Streaming: Send continuous status messages to the app display
  • Command Processing: Receive and handle text commands from the app
  • System Monitoring: Display uptime, free heap, CPU info, and more
  • LED Control: Built-in LED ON/OFF commands for quick testing
  • Periodic Updates: Automatic heartbeat and status messages at configurable intervals
  • BLE & Classic Bluetooth: Choose the Bluetooth mode that suits your project
  • Cross-Platform: BLE mode works on both Android and iOS; Classic Bluetooth works on Android
  • Low Power Option: BLE mode consumes less power than Classic Bluetooth

Hardware Used In This Tutorial

1×ESP-WROOM-32 Dev Module
1×Alternatively, ESP32 Uno-form board
1×Alternatively, ESP32 S3 Uno-form board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×Breadboard
1×Jumper Wires
1×Recommended: Screw Terminal Expansion Board for ESP32
1×Recommended: Breakout Expansion Board for ESP32
1×Recommended: Power Splitter for ESP32

Or you can buy the following kits:

1×DIYables ESP32 Starter Kit (ESP32 included)
1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links in this section are Amazon affiliate links, meaning we may earn a commission at no additional cost to you if you make a purchase through them. Additionally, some links direct you to products from our own brand, DIYables .

ESP32 Code

Quick Instructions

Follow these instructions step by step:

  • If this is your first time using the ESP32, refer to the tutorial on setting up the environment for ESP32 in the Arduino IDE.
  • Connect the ESP32 board to your computer using a USB cable.
  • Launch the Arduino IDE on your computer.
  • Select the appropriate ESP32 board and COM port.
  • Navigate to the Libraries icon on the left bar of the Arduino IDE.
  • Search "DIYables Bluetooth", then find the DIYables Bluetooth library by DIYables
  • Click Install button to install the library.
ESP32 DIYables Bluetooth library
  • You will be asked for installing some other library dependencies
  • Click Install All button to install all library dependencies.
ESP32 DIYables Bluetooth dependency

Choose one of the two Bluetooth modes below depending on your needs:

ESP32 Classic Bluetooth Code (works with app on Android only)

Note: Classic Bluetooth is NOT supported on iOS. If you need iOS support, use the BLE code below.

  • On Arduino IDE, Go to File Examples DIYables Bluetooth Esp32Bluetooth_Monitor example, or copy the above code and paste it to the editor of Arduino IDE
/* * DIYables Bluetooth Library - ESP32 Classic Bluetooth Monitor Example * Works with DIYables Bluetooth STEM app on Android * Note: Classic Bluetooth is NOT supported on iOS. Use BLE examples for iOS support. * * This example demonstrates the Bluetooth Monitor feature: * - Send real-time status messages to the mobile app * - Display system information and sensor readings * - Receive and process commands from the app * - Perfect for debugging and system monitoring * * Compatible Boards: * - ESP32 (all variants with Classic Bluetooth) * - ESP32-WROOM-32 * - ESP32-DevKitC * - ESP32-WROVER * * Note: Select "Huge APP (3MB No OTA/1MB SPIFFS)" partition scheme * in Arduino IDE: Tools > Partition Scheme * * Setup: * 1. Upload the sketch to your ESP32 * 2. Open Serial Monitor (115200 baud) to see connection status * 3. Use DIYables Bluetooth App to connect and view monitor output * * Tutorial: https://diyables.io/bluetooth-app * Author: DIYables */ #include <DIYables_BluetoothServer.h> #include <DIYables_BluetoothMonitor.h> #include <platforms/DIYables_Esp32Bluetooth.h> // Create Bluetooth instances DIYables_Esp32Bluetooth bluetooth("ESP32_Monitor"); DIYables_BluetoothServer bluetoothServer(bluetooth); // Create Monitor app instance DIYables_BluetoothMonitor bluetoothMonitor; // Variables for demo unsigned long lastUpdate = 0; const unsigned long UPDATE_INTERVAL = 3000; // Send update every 3 seconds int messageCount = 0; bool ledState = false; // ESP32 built-in LED (may vary by board) const int LED_PIN = 2; void setup() { Serial.begin(115200); delay(1000); Serial.println("DIYables Bluetooth - ESP32 Monitor Example"); // Initialize LED pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); // Initialize Bluetooth server with platform-specific implementation bluetoothServer.begin(); // Add monitor app to server bluetoothServer.addApp(&bluetoothMonitor); // Set up connection event callbacks bluetoothServer.setOnConnected([]() { Serial.println("Bluetooth connected!"); bluetoothMonitor.send("=== ESP32 Monitor Connected ==="); bluetoothMonitor.send("System Ready"); bluetoothMonitor.send("Type HELP for available commands"); bluetoothMonitor.send(""); }); bluetoothServer.setOnDisconnected([]() { Serial.println("Bluetooth disconnected!"); }); // Set up message handler for incoming commands bluetoothMonitor.onMonitorMessage([](const String& message) { Serial.print("Received command: "); Serial.println(message); handleCommand(message); }); Serial.println("Waiting for Bluetooth connection..."); } void handleCommand(const String& cmd) { if (cmd == "HELP") { bluetoothMonitor.send("Available Commands:"); bluetoothMonitor.send(" LED_ON - Turn LED on"); bluetoothMonitor.send(" LED_OFF - Turn LED off"); bluetoothMonitor.send(" STATUS - Show system status"); bluetoothMonitor.send(" HEAP - Show memory info"); bluetoothMonitor.send(" CLEAR - Clear monitor (if supported)"); bluetoothMonitor.send(" HELP - Show this help"); } else if (cmd == "LED_ON") { digitalWrite(LED_PIN, HIGH); ledState = true; bluetoothMonitor.send("✓ LED turned ON"); } else if (cmd == "LED_OFF") { digitalWrite(LED_PIN, LOW); ledState = false; bluetoothMonitor.send("✓ LED turned OFF"); } else if (cmd == "STATUS") { showStatus(); } else if (cmd == "HEAP") { bluetoothMonitor.send("=== Memory Info ==="); bluetoothMonitor.send("Free Heap: " + String(ESP.getFreeHeap()) + " bytes"); bluetoothMonitor.send("Min Free Heap: " + String(ESP.getMinFreeHeap()) + " bytes"); bluetoothMonitor.send("Heap Size: " + String(ESP.getHeapSize()) + " bytes"); bluetoothMonitor.send("==================="); } else if (cmd == "CLEAR") { bluetoothMonitor.send(""); } else { bluetoothMonitor.send("✗ Unknown command: " + cmd); bluetoothMonitor.send("Type HELP for available commands"); } } void showStatus() { bluetoothMonitor.send("=== System Status ==="); // LED Status bluetoothMonitor.send("LED State: " + String(ledState ? "ON" : "OFF")); // Uptime unsigned long uptime = millis() / 1000; bluetoothMonitor.send("Uptime: " + String(uptime / 3600) + "h " + String((uptime % 3600) / 60) + "m " + String(uptime % 60) + "s"); // ESP32-specific info bluetoothMonitor.send("Free Heap: " + String(ESP.getFreeHeap()) + " bytes"); bluetoothMonitor.send("CPU Freq: " + String(ESP.getCpuFreqMHz()) + " MHz"); bluetoothMonitor.send("Chip Model: " + String(ESP.getChipModel())); // Messages sent bluetoothMonitor.send("Messages Sent: " + String(messageCount)); bluetoothMonitor.send("===================="); } void sendPeriodicUpdate() { messageCount++; // Example of different message types if (messageCount % 3 == 0) { bluetoothMonitor.send("[INFO] Heartbeat #" + String(messageCount)); } else if (messageCount % 5 == 0) { bluetoothMonitor.send("[HEAP] Free: " + String(ESP.getFreeHeap()) + " bytes"); } else { bluetoothMonitor.send("[TIME] Uptime: " + String(millis() / 1000) + "s"); } Serial.print("Sent update #"); Serial.println(messageCount); } void loop() { // Handle Bluetooth server communications bluetoothServer.loop(); // Send periodic updates (only when connected) if (bluetooth.isConnected() && millis() - lastUpdate >= UPDATE_INTERVAL) { lastUpdate = millis(); sendPeriodicUpdate(); } delay(10); }
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Open the Serial Monitor
  • Check out the result on Serial Monitor. It looks like the below:
COM6
Send
DIYables Bluetooth - ESP32 Monitor Example Waiting for Bluetooth connection...
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

ESP32 BLE Code (works with app on both Android and iOS)

  • On Arduino IDE, Go to File Examples DIYables Bluetooth Esp32BLE_Monitor example, or copy the above code and paste it to the editor of Arduino IDE
/* * DIYables Bluetooth Library - ESP32 BLE Monitor Example * Works with DIYables Bluetooth STEM app on Android and iOS * * This example demonstrates the Bluetooth Monitor feature: * - Send real-time status messages to the mobile app * - Display system information and sensor readings * - Receive and process commands from the app * - Perfect for debugging and system monitoring * * Compatible Boards: * - ESP32-WROOM-32 * - ESP32-DevKitC * - ESP32-WROVER * - ESP32-S3 * - ESP32-C3 * - Any ESP32 board supporting BLE * * Note: Select "Huge APP (3MB No OTA/1MB SPIFFS)" partition scheme * in Arduino IDE: Tools > Partition Scheme * * Setup: * 1. Upload the sketch to your ESP32 * 2. Open Serial Monitor (115200 baud) to see connection status * 3. Use DIYables Bluetooth App to connect and view monitor output * * Tutorial: https://diyables.io/bluetooth-app * Author: DIYables */ #include <DIYables_BluetoothServer.h> #include <DIYables_BluetoothMonitor.h> #include <platforms/DIYables_Esp32BLE.h> // BLE Configuration const char* DEVICE_NAME = "ESP32BLE_Monitor"; const char* SERVICE_UUID = "19B10000-E8F2-537E-4F6C-D104768A1214"; const char* TX_UUID = "19B10001-E8F2-537E-4F6C-D104768A1214"; const char* RX_UUID = "19B10002-E8F2-537E-4F6C-D104768A1214"; // Create Bluetooth instances DIYables_Esp32BLE bluetooth(DEVICE_NAME, SERVICE_UUID, TX_UUID, RX_UUID); DIYables_BluetoothServer bluetoothServer(bluetooth); // Create Monitor app instance DIYables_BluetoothMonitor bluetoothMonitor; // Variables for demo unsigned long lastUpdate = 0; const unsigned long UPDATE_INTERVAL = 3000; int messageCount = 0; bool ledState = false; void setup() { Serial.begin(115200); delay(1000); Serial.println("DIYables Bluetooth - ESP32 BLE Monitor Example"); // Initialize built-in LED pinMode(2, OUTPUT); // ESP32 built-in LED is usually on GPIO 2 digitalWrite(2, LOW); // Initialize Bluetooth server with platform-specific implementation bluetoothServer.begin(); // Add monitor app to server bluetoothServer.addApp(&bluetoothMonitor); // Set up connection event callbacks bluetoothServer.setOnConnected([]() { Serial.println("Bluetooth connected!"); bluetoothMonitor.send("=== ESP32 BLE Monitor Connected ==="); bluetoothMonitor.send("System Ready"); bluetoothMonitor.send("Type HELP for available commands"); bluetoothMonitor.send(""); }); bluetoothServer.setOnDisconnected([]() { Serial.println("Bluetooth disconnected!"); }); // Set up message handler for incoming commands bluetoothMonitor.onMonitorMessage([](const String& message) { Serial.print("Received command: "); Serial.println(message); handleCommand(message); }); Serial.println("Waiting for Bluetooth connection..."); } void handleCommand(const String& cmd) { if (cmd == "HELP") { bluetoothMonitor.send("Available Commands:"); bluetoothMonitor.send(" LED_ON - Turn LED on"); bluetoothMonitor.send(" LED_OFF - Turn LED off"); bluetoothMonitor.send(" STATUS - Show system status"); bluetoothMonitor.send(" HEAP - Show free heap memory"); bluetoothMonitor.send(" HELP - Show this help"); } else if (cmd == "LED_ON") { digitalWrite(2, HIGH); ledState = true; bluetoothMonitor.send("LED turned ON"); } else if (cmd == "LED_OFF") { digitalWrite(2, LOW); ledState = false; bluetoothMonitor.send("LED turned OFF"); } else if (cmd == "STATUS") { showStatus(); } else if (cmd == "HEAP") { bluetoothMonitor.send("Free heap: " + String(ESP.getFreeHeap()) + " bytes"); } else { bluetoothMonitor.send("Unknown command: " + cmd); bluetoothMonitor.send("Type HELP for available commands"); } } void showStatus() { bluetoothMonitor.send("=== System Status ==="); bluetoothMonitor.send("LED State: " + String(ledState ? "ON" : "OFF")); unsigned long uptime = millis() / 1000; bluetoothMonitor.send("Uptime: " + String(uptime / 3600) + "h " + String((uptime % 3600) / 60) + "m " + String(uptime % 60) + "s"); bluetoothMonitor.send("Free Heap: " + String(ESP.getFreeHeap()) + " bytes"); bluetoothMonitor.send("Messages Sent: " + String(messageCount)); bluetoothMonitor.send("===================="); } void sendPeriodicUpdate() { messageCount++; if (messageCount % 3 == 0) { bluetoothMonitor.send("[INFO] Heartbeat #" + String(messageCount)); } else if (messageCount % 5 == 0) { bluetoothMonitor.send("[HEAP] Free: " + String(ESP.getFreeHeap()) + " bytes"); } else { bluetoothMonitor.send("[TIME] Uptime: " + String(millis() / 1000) + "s"); } Serial.print("Sent update #"); Serial.println(messageCount); } void loop() { bluetoothServer.loop(); if (bluetooth.isConnected() && millis() - lastUpdate >= UPDATE_INTERVAL) { lastUpdate = millis(); sendPeriodicUpdate(); } delay(10); }
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Open the Serial Monitor
  • Check out the result on Serial Monitor. It looks like the below:
COM6
Send
DIYables Bluetooth - ESP32 BLE Monitor Example Waiting for Bluetooth connection...
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

Mobile App

  • Install the DIYables Bluetooth App on your smartphone: Android | iOS
  • If you are using the ESP32 Classic Bluetooth code, you need to pair the ESP32 with your Android phone before opening the app:
    • Go to your phone's Settings > Bluetooth
    • Make sure Bluetooth is turned on
    • Your phone will scan for available devices
    • Find and tap "ESP32_Monitor" in the list of available devices
    • Confirm the pairing request (no PIN required)
    • Wait until it shows "Paired" under the device name
  • If you are using the ESP32 BLE code, no pairing is needed. Just proceed to the next step.
  • Open the DIYables Bluetooth App
  • When opening the app for the first time, it will ask for permissions. Please grant the following:
    • Nearby Devices permission (Android 12+) / Bluetooth permission (iOS) - required to scan and connect to Bluetooth devices
    • Location permission (Android 11 and below only) - required by older Android versions to scan for BLE devices
  • Make sure Bluetooth is turned on on your phone
  • On the home screen, tap the Connect button. The app will scan for both BLE and Classic Bluetooth devices.
DIYables Bluetooth App - Home Screen with Scan Button
  • Find and tap your device in the scan results to connect:
    • For Classic Bluetooth: tap "ESP32_Monitor"
    • For BLE: tap "ESP32BLE_Monitor"
  • Once connected, the app automatically goes back to the home screen. Select the Monitor app from the app menu.
DIYables Bluetooth App - Home Screen with Monitor App

Note: You can tap the settings icon on the home screen to hide/show apps on the home screen. For more details, see the DIYables Bluetooth App User Manual.

  • You will see status messages streaming in the monitor display
  • Type LED_ON in the input field and tap Send — the built-in LED on the ESP32 will turn ON, and the monitor will display a confirmation message
DIYables Bluetooth App - Monitor Screen

Now look back at the Serial Monitor on Arduino IDE. You will see:

COM6
Send
Bluetooth connected! Sent update #1 Sent update #2 Received command: HELP Received command: STATUS
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • Type commands in the app (HELP, STATUS, LED_ON, LED_OFF, HEAP) and watch the responses

Creative Customization - Adapt the Code to Your Project

Send Messages to App

Use the send() method to stream text messages to the monitor display:

// Send simple messages bluetoothMonitor.send("System initialized"); bluetoothMonitor.send("Sensor reading: 25.3°C"); // Send formatted data bluetoothMonitor.send("[INFO] Heartbeat #" + String(count)); bluetoothMonitor.send("[WARN] Temperature high: " + String(temp) + "°C"); bluetoothMonitor.send("[ERROR] Sensor disconnected"); // Send system information bluetoothMonitor.send("Free Heap: " + String(ESP.getFreeHeap()) + " bytes"); bluetoothMonitor.send("Uptime: " + String(millis() / 1000) + " seconds");

Receive Commands from App

Use the onMonitorMessage() callback to receive commands typed in the Monitor app and react to them:

bluetoothMonitor.onMonitorMessage([](const String& message) { Serial.print("Received command: "); Serial.println(message); if (message == "HELP") { bluetoothMonitor.send("Available Commands:"); bluetoothMonitor.send(" LED_ON - Turn LED on"); bluetoothMonitor.send(" LED_OFF - Turn LED off"); bluetoothMonitor.send(" STATUS - Show system status"); bluetoothMonitor.send(" HEAP - Show memory info"); } else if (message == "LED_ON") { digitalWrite(LED_BUILTIN, HIGH); bluetoothMonitor.send("LED turned ON"); } else if (message == "LED_OFF") { digitalWrite(LED_BUILTIN, LOW); bluetoothMonitor.send("LED turned OFF"); } else if (message == "STATUS") { bluetoothMonitor.send("System is running normally"); bluetoothMonitor.send("Uptime: " + String(millis() / 1000) + "s"); } else if (message == "HEAP") { bluetoothMonitor.send("Free Heap: " + String(ESP.getFreeHeap()) + " bytes"); } else { bluetoothMonitor.send("Unknown command: " + message); } });

You can add as many custom commands as you need by adding more else if blocks. For example, add RELAY_ON / RELAY_OFF to control a relay, or READ to trigger a sensor reading — any word you type in the app becomes a command.

Handle Connection Events

You can detect when the app connects or disconnects from the ESP32:

bluetoothServer.setOnConnected([]() { Serial.println("Bluetooth connected!"); bluetoothMonitor.send("=== ESP32 Monitor Connected ==="); bluetoothMonitor.send("System Ready"); bluetoothMonitor.send("Type HELP for available commands"); }); bluetoothServer.setOnDisconnected([]() { Serial.println("Bluetooth disconnected!"); }); if (bluetoothServer.isConnected()) { bluetoothMonitor.send("Status update"); }

How to Use the Monitor

App Interface Controls

The monitor interface in the DIYables Bluetooth App provides:

  • Message Display: Scrollable list of received messages with auto-scroll
  • Text Input: Type commands at the bottom
  • Send Button: Tap to send the typed command to ESP32

Built-in Commands

The example code includes these built-in commands:

  • HELP ? Shows all available commands
  • LED_ON ? Turns the built-in LED on
  • LED_OFF ? Turns the built-in LED off
  • STATUS ? Shows system status (LED state, uptime, heap, messages sent)
  • HEAP ? Shows detailed memory information

Programming Examples

Basic Status Streaming

unsigned long lastUpdate = 0; const unsigned long UPDATE_INTERVAL = 3000; int messageCount = 0; void loop() { bluetoothServer.loop(); if (bluetooth.isConnected() && millis() - lastUpdate >= UPDATE_INTERVAL) { lastUpdate = millis(); messageCount++; // Rotate between different status messages if (messageCount % 3 == 0) { bluetoothMonitor.send("[INFO] Heartbeat #" + String(messageCount)); } else if (messageCount % 5 == 0) { bluetoothMonitor.send("[HEAP] Free: " + String(ESP.getFreeHeap()) + " bytes"); } else { bluetoothMonitor.send("[TIME] Uptime: " + String(millis() / 1000) + "s"); } } delay(10); }

Sensor Data Logger

#include <DHT.h> DHT dht(4, DHT22); unsigned long lastSensorRead = 0; const unsigned long SENSOR_INTERVAL = 5000; void setup() { dht.begin(); bluetoothMonitor.onMonitorMessage([](const String& message) { if (message == "READ") { readAndSendSensorData(); } else if (message == "INTERVAL") { bluetoothMonitor.send("Sensor interval: " + String(SENSOR_INTERVAL / 1000) + "s"); } }); } void readAndSendSensorData() { float temp = dht.readTemperature(); float hum = dht.readHumidity(); if (!isnan(temp) && !isnan(hum)) { bluetoothMonitor.send("Temp: " + String(temp, 1) + "°C | Humidity: " + String(hum, 1) + "%"); } else { bluetoothMonitor.send("[ERROR] Failed to read sensor"); } } void loop() { bluetoothServer.loop(); if (bluetooth.isConnected() && millis() - lastSensorRead >= SENSOR_INTERVAL) { lastSensorRead = millis(); readAndSendSensorData(); } delay(10); }

Multi-Sensor Dashboard

void sendDashboard() { bluetoothMonitor.send("========== DASHBOARD =========="); bluetoothMonitor.send("Temp: " + String(readTemperature(), 1) + "°C"); bluetoothMonitor.send("Humidity: " + String(readHumidity(), 0) + "%"); bluetoothMonitor.send("Light: " + String(analogRead(34))); bluetoothMonitor.send("Battery: " + String(readBatteryVoltage(), 2) + "V"); bluetoothMonitor.send("Heap: " + String(ESP.getFreeHeap()) + " bytes"); unsigned long uptime = millis() / 1000; bluetoothMonitor.send("Uptime: " + String(uptime / 3600) + "h " + String((uptime % 3600) / 60) + "m " + String(uptime % 60) + "s"); bluetoothMonitor.send("==============================="); }

GPIO Pin Monitor

const int MONITOR_PINS[] = {16, 17, 18, 19, 21, 22}; const int NUM_PINS = 6; int lastPinStates[6] = {0}; void setup() { for (int i = 0; i < NUM_PINS; i++) { pinMode(MONITOR_PINS[i], INPUT_PULLUP); lastPinStates[i] = digitalRead(MONITOR_PINS[i]); } bluetoothMonitor.onMonitorMessage([](const String& message) { if (message == "PINS") { for (int i = 0; i < NUM_PINS; i++) { int state = digitalRead(MONITOR_PINS[i]); bluetoothMonitor.send("Pin " + String(MONITOR_PINS[i]) + ": " + String(state ? "HIGH" : "LOW")); } } }); } void loop() { bluetoothServer.loop(); // Detect pin changes and report for (int i = 0; i < NUM_PINS; i++) { int state = digitalRead(MONITOR_PINS[i]); if (state != lastPinStates[i]) { lastPinStates[i] = state; if (bluetooth.isConnected()) { bluetoothMonitor.send("[PIN] GPIO " + String(MONITOR_PINS[i]) + " changed to " + String(state ? "HIGH" : "LOW")); } } } delay(10); }

Advanced Programming Techniques

Categorized Logging

enum LogLevel { LOG_INFO, LOG_WARN, LOG_ERROR, LOG_DEBUG }; void sendLog(LogLevel level, const String& message) { String prefix; switch (level) { case LOG_INFO: prefix = "[INFO] "; break; case LOG_WARN: prefix = "[WARN] "; break; case LOG_ERROR: prefix = "[ERROR] "; break; case LOG_DEBUG: prefix = "[DEBUG] "; break; } bluetoothMonitor.send(prefix + message); } // Usage: sendLog(LOG_INFO, "System started"); sendLog(LOG_WARN, "Battery low: " + String(voltage, 2) + "V"); sendLog(LOG_ERROR, "Sensor read failed"); sendLog(LOG_DEBUG, "Loop time: " + String(loopTime) + "ms");

Command-Based Configuration

int sensorInterval = 3000; bool verboseMode = false; bluetoothMonitor.onMonitorMessage([](const String& message) { String cmd = message; cmd.toUpperCase(); if (cmd.startsWith("SET INTERVAL ")) { sensorInterval = cmd.substring(13).toInt() * 1000; bluetoothMonitor.send("Interval set to " + String(sensorInterval / 1000) + "s"); } else if (cmd == "VERBOSE ON") { verboseMode = true; bluetoothMonitor.send("Verbose mode enabled"); } else if (cmd == "VERBOSE OFF") { verboseMode = false; bluetoothMonitor.send("Verbose mode disabled"); } else if (cmd == "CONFIG") { bluetoothMonitor.send("Interval: " + String(sensorInterval / 1000) + "s"); bluetoothMonitor.send("Verbose: " + String(verboseMode ? "ON" : "OFF")); } });

Hardware Integration Examples

Watchdog Monitor

unsigned long lastLoopTime = 0; unsigned long maxLoopTime = 0; int warningCount = 0; void loop() { unsigned long loopStart = millis(); bluetoothServer.loop(); // Your application code here performTasks(); unsigned long loopTime = millis() - loopStart; if (loopTime > maxLoopTime) { maxLoopTime = loopTime; } if (loopTime > 100) { // Warn if loop takes >100ms warningCount++; if (bluetooth.isConnected()) { bluetoothMonitor.send("[WARN] Slow loop: " + String(loopTime) + "ms"); } } delay(10); }

BLE vs Classic Bluetooth - Which to Choose?

FeatureBLE (Esp32BLE_Monitor)Classic Bluetooth (Esp32Bluetooth_Monitor)
iOS Support? Yes? No
Android Support? Yes? Yes
Power ConsumptionLowHigher
Range~30-100m~10-100m
Data RateLowerHigher
Pairing RequiredNo (auto-connect)Yes (manual pairing)
Best ForBattery-powered, cross-platformHigh throughput, Android-only

Troubleshooting

Common Issues

1. Cannot find the device in the app

  • Make sure the ESP32 is powered on and the sketch is uploaded
  • For BLE: Ensure your phone's Bluetooth and Location are enabled
  • For Classic Bluetooth: Pair the device first in phone's Bluetooth settings
  • Check that the correct partition scheme is selected (Huge APP)

2. Messages not appearing in the monitor

  • Check Bluetooth connection status in the app
  • Verify connection in Serial Monitor
  • Ensure messages are being sent with bluetoothMonitor.send()
  • Try disconnecting and reconnecting

3. Commands not being received

  • Verify the onMonitorMessage() callback is set up correctly
  • Check Serial Monitor for received commands
  • Ensure the monitor app screen is selected in the mobile app

4. Connection drops frequently

  • Move closer to the ESP32 (reduce distance)
  • For BLE: Check for interference from other BLE devices
  • For Classic Bluetooth: Ensure stable power supply to ESP32
  • Reduce message frequency if sending too fast

5. Messages appear garbled or truncated

  • Keep individual messages short (under 200 characters)
  • Add small delays between rapid sends
  • Check free heap memory for buffer issues

6. Sketch too large / not enough space

  • In Arduino IDE, go to Tools > Partition Scheme and select "Huge APP (3MB No OTA/1MB SPIFFS)" or "No OTA (Large APP)"
  • The default partition scheme only provides ~1.2MB for app code, which is not enough for Bluetooth libraries
  • This setting gives ~3MB by sacrificing the OTA (over-the-air update) partition

Debug Tips

Add comprehensive debugging:

void debugMonitorStatus() { Serial.println("=== Monitor Debug ==="); Serial.println("Connected: " + String(bluetooth.isConnected())); Serial.println("Messages sent: " + String(messageCount)); Serial.println("Free Heap: " + String(ESP.getFreeHeap())); Serial.println("====================="); }

Project Ideas

Debugging Projects

  • Wireless serial monitor replacement
  • Remote sensor data viewer
  • Real-time variable inspection
  • System performance monitoring

Monitoring Projects

  • Weather station data display
  • Home automation system status
  • Industrial sensor monitoring
  • IoT device health dashboard

Logging Projects

  • Event logger with timestamps
  • Sensor data recording
  • Error tracking and alerting
  • Performance profiling

Education Projects

  • Learn Bluetooth communication
  • Practice serial-like messaging
  • Understand embedded system monitoring
  • Build custom debugging tools

Integration with Other Bluetooth Apps

Combine with Bluetooth Chat

Use Monitor for continuous output and Chat for interactive commands:

// Monitor streams sensor data automatically void loop() { if (bluetooth.isConnected() && millis() - lastUpdate >= 3000) { bluetoothMonitor.send("[SENSOR] " + String(readSensor())); } } // Chat handles interactive commands bluetoothChat.onChatMessage([](const String& message) { if (message == "read") { bluetoothChat.send("Value: " + String(readSensor())); } });

Combine with Bluetooth Slider

Use Monitor to display slider values in real time:

bluetoothSlider.onSliderValue([](int slider1, int slider2) { bluetoothMonitor.send("Slider1=" + String(slider1) + "% Slider2=" + String(slider2) + "%"); bluetoothMonitor.send("PWM1=" + String(map(slider1, 0, 100, 0, 255)) + " PWM2=" + String(map(slider2, 0, 100, 0, 255))); });

Next Steps

After mastering the Bluetooth Monitor example, try:

  1. Bluetooth Chat - For two-way interactive messaging
  2. Bluetooth Table - For structured data display
  3. Bluetooth Plotter - For graphical data visualization
  4. Multiple Bluetooth Apps - Combining monitor with other controls

Support

For additional help:

※ OUR MESSAGES