ESP32 - DIYables Bluetooth App Slider
The Bluetooth Slider example provides two independent slider controls accessible through the DIYables Bluetooth STEM app. Designed for ESP32 boards with support for both BLE (Bluetooth Low Energy) and Classic Bluetooth connections. Each slider offers values from 0-100, making them perfect for PWM control, brightness adjustment, motor speed control, and any application requiring analog-like control values.
This example supports two Bluetooth modes:
Dual Sliders: Two independent slider controls (0-100 range each)
Real-time Values: Instant value updates via Bluetooth communication
PWM Compatible: Values (0-100) easily mapped to analogWrite() functions
Visual Feedback: Real-time value display for each slider in the app
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
Configurable Range & Step: Customize slider range and step size at runtime
Or you can buy the following kits:
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 .
Follow these instructions step by step:
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.
Choose one of the two Bluetooth modes below depending on your needs:
Note: Classic Bluetooth is NOT supported on iOS. If you need iOS support, use the BLE code below.
#include <DIYables_BluetoothServer.h>
#include <DIYables_BluetoothSlider.h>
#include <platforms/DIYables_Esp32Bluetooth.h>
DIYables_Esp32Bluetooth bluetooth("ESP32_Slider");
DIYables_BluetoothServer bluetoothServer(bluetooth);
DIYables_BluetoothSlider bluetoothSlider(0, 100, 1);
int currentSlider1 = 0;
int currentSlider2 = 0;
const int PWM_PIN_1 = 16;
const int PWM_PIN_2 = 17;
const int PWM_CHANNEL_1 = 0;
const int PWM_CHANNEL_2 = 1;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("DIYables Bluetooth - ESP32 Slider Example");
ledcSetup(PWM_CHANNEL_1, 5000, 8);
ledcSetup(PWM_CHANNEL_2, 5000, 8);
ledcAttachPin(PWM_PIN_1, PWM_CHANNEL_1);
ledcAttachPin(PWM_PIN_2, PWM_CHANNEL_2);
bluetoothServer.begin();
bluetoothServer.addApp(&bluetoothSlider);
bluetoothServer.setOnConnected([]() {
Serial.println("Bluetooth connected!");
bluetoothSlider.send(currentSlider1, currentSlider2);
});
bluetoothServer.setOnDisconnected([]() {
Serial.println("Bluetooth disconnected!");
});
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
Serial.print("Slider 1: ");
Serial.print(slider1);
Serial.print(", Slider 2: ");
Serial.println(slider2);
int pwm1 = map(slider1, 0, 100, 0, 255);
int pwm2 = map(slider2, 0, 100, 0, 255);
ledcWrite(PWM_CHANNEL_1, pwm1);
ledcWrite(PWM_CHANNEL_2, pwm2);
});
bluetoothSlider.onGetConfig([]() {
bluetoothSlider.send(currentSlider1, currentSlider2);
Serial.print("App requested values - Sent: Slider1=");
Serial.print(currentSlider1);
Serial.print(", Slider2=");
Serial.println(currentSlider2);
});
Serial.println("Waiting for Bluetooth connection...");
}
void loop() {
bluetoothServer.loop();
delay(10);
}
DIYables Bluetooth - ESP32 Slider Example
Waiting for Bluetooth connection...
#include <DIYables_BluetoothServer.h>
#include <DIYables_BluetoothSlider.h>
#include <platforms/DIYables_Esp32BLE.h>
const char* DEVICE_NAME = "ESP32BLE_Slider";
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";
DIYables_Esp32BLE bluetooth(DEVICE_NAME, SERVICE_UUID, TX_UUID, RX_UUID);
DIYables_BluetoothServer bluetoothServer(bluetooth);
DIYables_BluetoothSlider bluetoothSlider(0, 100, 1);
int currentSlider1 = 0;
int currentSlider2 = 0;
const int PWM_PIN_1 = 16;
const int PWM_PIN_2 = 17;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("DIYables Bluetooth - ESP32 BLE Slider Example");
pinMode(PWM_PIN_1, OUTPUT);
pinMode(PWM_PIN_2, OUTPUT);
bluetoothServer.begin();
bluetoothServer.addApp(&bluetoothSlider);
bluetoothServer.setOnConnected([]() {
Serial.println("Bluetooth connected!");
bluetoothSlider.send(currentSlider1, currentSlider2);
});
bluetoothServer.setOnDisconnected([]() {
Serial.println("Bluetooth disconnected!");
});
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
Serial.print("Slider 1: ");
Serial.print(slider1);
Serial.print(", Slider 2: ");
Serial.println(slider2);
int pwm1 = map(slider1, 0, 100, 0, 255);
int pwm2 = map(slider2, 0, 100, 0, 255);
analogWrite(PWM_PIN_1, pwm1);
analogWrite(PWM_PIN_2, pwm2);
});
bluetoothSlider.onGetConfig([]() {
bluetoothSlider.send(currentSlider1, currentSlider2);
Serial.print("App requested values - Sent: Slider1=");
Serial.print(currentSlider1);
Serial.print(", Slider2=");
Serial.println(currentSlider2);
});
Serial.println("Waiting for Bluetooth connection...");
}
void loop() {
bluetoothServer.loop();
delay(10);
}
DIYables Bluetooth - ESP32 BLE Slider Example
Waiting for Bluetooth connection...
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_Slider" 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.

Find and tap your device in the scan results to connect:
Once connected, the app automatically goes back to the home screen. Select the Slider app from the app menu.
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.
Now look back at the Serial Monitor on Arduino IDE. You will see:
Bluetooth connected!
Slider 1: 50, Slider 2: 30
Slider 1: 75, Slider 2: 30
Slider 1: 75, Slider 2: 60
Slider 1: 100, Slider 2: 85
Configure initial slider positions:
int currentSlider1 = 25;
int currentSlider2 = 50;
DIYables_BluetoothSlider bluetoothSlider(0, 255, 5);
bluetoothSlider.setRange(0, 255);
bluetoothSlider.setStep(5);
int currentMin = bluetoothSlider.getMin();
int currentMax = bluetoothSlider.getMax();
int currentStep = bluetoothSlider.getStep();
When the app connects and opens the Slider screen, it requests the slider configuration from ESP32. You can use the onGetConfig() callback to send the current slider values to the app at that moment:
bluetoothSlider.onGetConfig([]() {
bluetoothSlider.send(currentSlider1, currentSlider2);
Serial.println("App requested config - sent current values");
});
You can send slider values from ESP32 to the app (e.g., to update the app's slider positions):
bluetoothSlider.send(currentSlider1, currentSlider2);
bluetoothSlider.send(50);
You can detect when the app connects or disconnects from the ESP32:
bluetoothServer.setOnConnected([]() {
Serial.println("Bluetooth connected!");
bluetoothSlider.send(currentSlider1, currentSlider2);
});
bluetoothServer.setOnDisconnected([]() {
Serial.println("Bluetooth disconnected!");
});
if (bluetoothServer.isConnected()) {
}
The slider interface in the DIYables Bluetooth App provides:
Slider 1: First control slider with value display
Slider 2: Second control slider with value display
Value Display: Real-time numeric values for both sliders
Each slider provides:
void setup() {
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
Serial.println("Slider 1: " + String(slider1) + ", Slider 2: " + String(slider2));
});
}
const int PWM_PIN_1 = 16;
const int PWM_PIN_2 = 17;
void setup() {
pinMode(PWM_PIN_1, OUTPUT);
pinMode(PWM_PIN_2, OUTPUT);
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
int pwm1 = map(slider1, 0, 100, 0, 255);
int pwm2 = map(slider2, 0, 100, 0, 255);
analogWrite(PWM_PIN_1, pwm1);
analogWrite(PWM_PIN_2, pwm2);
Serial.println("LED1 Brightness: " + String(pwm1) +
", LED2 Brightness: " + String(pwm2));
});
}
const int PWM_PIN_1 = 16;
const int PWM_PIN_2 = 17;
const int PWM_CHANNEL_1 = 0;
const int PWM_CHANNEL_2 = 1;
void setup() {
ledcSetup(PWM_CHANNEL_1, 5000, 8);
ledcSetup(PWM_CHANNEL_2, 5000, 8);
ledcAttachPin(PWM_PIN_1, PWM_CHANNEL_1);
ledcAttachPin(PWM_PIN_2, PWM_CHANNEL_2);
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
int pwm1 = map(slider1, 0, 100, 0, 255);
int pwm2 = map(slider2, 0, 100, 0, 255);
ledcWrite(PWM_CHANNEL_1, pwm1);
ledcWrite(PWM_CHANNEL_2, pwm2);
Serial.println("LED1 Brightness: " + String(pwm1) +
", LED2 Brightness: " + String(pwm2));
});
}
#include <ESP32Servo.h>
Servo servo1, servo2;
void setup() {
servo1.attach(16);
servo2.attach(17);
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
int angle1 = map(slider1, 0, 100, 0, 180);
int angle2 = map(slider2, 0, 100, 0, 180);
servo1.write(angle1);
servo2.write(angle2);
Serial.println("Servo1: " + String(angle1) + "°, Servo2: " + String(angle2) + "°");
});
}
const int MOTOR1_PWM = 16;
const int MOTOR1_DIR1 = 18;
const int MOTOR1_DIR2 = 19;
const int MOTOR2_PWM = 17;
const int MOTOR2_DIR1 = 21;
const int MOTOR2_DIR2 = 22;
void setup() {
pinMode(MOTOR1_PWM, OUTPUT);
pinMode(MOTOR1_DIR1, OUTPUT);
pinMode(MOTOR1_DIR2, OUTPUT);
pinMode(MOTOR2_PWM, OUTPUT);
pinMode(MOTOR2_DIR1, OUTPUT);
pinMode(MOTOR2_DIR2, OUTPUT);
digitalWrite(MOTOR1_DIR1, HIGH);
digitalWrite(MOTOR1_DIR2, LOW);
digitalWrite(MOTOR2_DIR1, HIGH);
digitalWrite(MOTOR2_DIR2, LOW);
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
int pwm1 = map(slider1, 0, 100, 0, 255);
int pwm2 = map(slider2, 0, 100, 0, 255);
analogWrite(MOTOR1_PWM, pwm1);
analogWrite(MOTOR2_PWM, pwm2);
Serial.println("Motor1: " + String(slider1) + "%, " +
"Motor2: " + String(slider2) + "%");
});
}
const int RED_PIN = 16;
const int GREEN_PIN = 17;
const int BLUE_PIN = 18;
void setup() {
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
int redValue = map(slider1, 0, 100, 0, 255);
int blueValue = map(slider2, 0, 100, 0, 255);
int greenValue = (redValue + blueValue) / 2;
analogWrite(RED_PIN, redValue);
analogWrite(GREEN_PIN, greenValue);
analogWrite(BLUE_PIN, blueValue);
Serial.println("RGB - R:" + String(redValue) +
" G:" + String(greenValue) +
" B:" + String(blueValue));
});
}
class SliderSmoother {
private:
int currentValue = 0;
int targetValue = 0;
unsigned long lastUpdate = 0;
const int SMOOTH_RATE = 2;
public:
void setTarget(int target) {
targetValue = target;
}
int getCurrentValue() {
return currentValue;
}
bool update() {
if (millis() - lastUpdate > 10) {
bool changed = false;
if (currentValue < targetValue) {
currentValue = min(currentValue + SMOOTH_RATE, targetValue);
changed = true;
} else if (currentValue > targetValue) {
currentValue = max(currentValue - SMOOTH_RATE, targetValue);
changed = true;
}
lastUpdate = millis();
return changed;
}
return false;
}
};
SliderSmoother smoother1, smoother2;
void setup() {
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
smoother1.setTarget(slider1);
smoother2.setTarget(slider2);
});
}
void loop() {
bluetoothServer.loop();
bool changed1 = smoother1.update();
bool changed2 = smoother2.update();
if (changed1 || changed2) {
analogWrite(16, map(smoother1.getCurrentValue(), 0, 100, 0, 255));
analogWrite(17, map(smoother2.getCurrentValue(), 0, 100, 0, 255));
}
}
void setupThresholdControl() {
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
const int LOW_THRESHOLD = 33;
const int MEDIUM_THRESHOLD = 66;
if (slider1 < LOW_THRESHOLD) {
digitalWrite(18, LOW);
digitalWrite(19, LOW);
digitalWrite(21, LOW);
} else if (slider1 < MEDIUM_THRESHOLD) {
digitalWrite(18, HIGH);
digitalWrite(19, LOW);
digitalWrite(21, LOW);
} else {
digitalWrite(18, HIGH);
digitalWrite(19, HIGH);
digitalWrite(21, HIGH);
}
analogWrite(16, map(slider2, 0, 100, 0, 255));
});
}
const int PRESETS[][2] = {
{0, 0},
{25, 50},
{50, 50},
{100, 50},
{100, 100}
};
void applyPreset(int presetNumber) {
if (presetNumber >= 0 && presetNumber < 5) {
currentSlider1 = PRESETS[presetNumber][0];
currentSlider2 = PRESETS[presetNumber][1];
analogWrite(16, map(currentSlider1, 0, 100, 0, 255));
analogWrite(17, map(currentSlider2, 0, 100, 0, 255));
bluetoothSlider.send(currentSlider1, currentSlider2);
Serial.println("Applied preset " + String(presetNumber) +
": " + String(currentSlider1) + ", " + String(currentSlider2));
}
}
const int LED_STRIP_PIN = 16;
const int NUM_LEDS = 30;
void setupLEDStrip() {
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
uint8_t brightness = map(slider1, 0, 100, 0, 255);
uint8_t hue = map(slider2, 0, 100, 0, 255);
Serial.println("LED Strip - Brightness: " + String(brightness) +
", Hue: " + String(hue));
});
}
const int FAN1_PIN = 16;
const int FAN2_PIN = 17;
void setupFanControl() {
pinMode(FAN1_PIN, OUTPUT);
pinMode(FAN2_PIN, OUTPUT);
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
currentSlider1 = slider1;
currentSlider2 = slider2;
int pwm1 = map(slider1, 0, 100, 0, 255);
int pwm2 = map(slider2, 0, 100, 0, 255);
int fan1Speed = (pwm1 > 50) ? map(pwm1, 50, 255, 100, 255) : 0;
int fan2Speed = (pwm2 > 50) ? map(pwm2, 50, 255, 100, 255) : 0;
analogWrite(FAN1_PIN, fan1Speed);
analogWrite(FAN2_PIN, fan2Speed);
Serial.println("Fan1: " + String(slider1) + "%, " +
"Fan2: " + String(slider2) + "%");
});
}
| Feature | BLE (Esp32BLE_Slider) | Classic Bluetooth (Esp32Bluetooth_Slider) |
| iOS Support | ? Yes | ? No |
| Android Support | ? Yes | ? Yes |
| Power Consumption | Low | Higher |
| Range | ~30-100m | ~10-100m |
| Data Rate | Lower | Higher |
| Pairing Required | No (auto-connect) | Yes (manual pairing) |
| Best For | Battery-powered, cross-platform | High throughput, Android-only |
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. Sliders not responding
Check Bluetooth connection status in the app
Verify connection in Serial Monitor
Try disconnecting and reconnecting
3. Values not reaching full range
Check slider range configuration: DIYables_BluetoothSlider(min, max, step)
Verify value mapping in callback function
Check Serial Monitor for actual values received
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
Check Serial Monitor for disconnect/reconnect messages
5. PWM output not working
Verify pins support PWM on your ESP32 variant
For ESP32: Use ledcSetup/ledcAttachPin/ledcWrite for hardware PWM
Check hardware connections and load requirements
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
Add comprehensive debugging:
void debugSliderValues(int slider1, int slider2) {
Serial.println("=== Slider Debug ===");
Serial.println("Slider 1: " + String(slider1) + "%");
Serial.println("Slider 2: " + String(slider2) + "%");
Serial.println("PWM 1: " + String(map(slider1, 0, 100, 0, 255)));
Serial.println("PWM 2: " + String(map(slider2, 0, 100, 0, 255)));
Serial.println("===================");
}
Room lighting brightness control via Bluetooth
RGB color mixing interface
LED strip animation speed control
Wireless stage lighting control
Wireless volume control
Tone/equalizer control
Sound effect intensity
Wireless climate control (heating/cooling intensity)
Bluetooth window blind position control
Irrigation system flow control
Use sliders for speed limits and joystick for direction:
int maxSpeed = 100;
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
maxSpeed = slider1;
});
bluetoothJoystick.onJoystickValue([](int x, int y) {
int scaledX = map(x, -100, 100, -maxSpeed, maxSpeed);
int scaledY = map(y, -100, 100, -maxSpeed, maxSpeed);
controlRobot(scaledX, scaledY);
});
Use sliders to control PWM and digital pins for on/off:
bluetoothSlider.onSliderValue([](int slider1, int slider2) {
if (digitalRead(18) == HIGH) {
analogWrite(16, map(slider1, 0, 100, 0, 255));
} else {
analogWrite(16, 0);
}
if (digitalRead(19) == HIGH) {
analogWrite(17, map(slider2, 0, 100, 0, 255));
} else {
analogWrite(17, 0);
}
});
After mastering the Bluetooth Slider example, try:
Bluetooth Joystick - For 2D directional control
Bluetooth Digital Pins - For discrete on/off control
Bluetooth Monitor - For debugging slider values
Multiple Bluetooth Apps - Combining sliders with other controls