ESP32 S3 UNO - DIYables Bluetooth App Joystick
Overview
This ESP32 S3 Uno Bluetooth joystick tutorial shows you how to turn your phone into a wireless 2D controller for the ESP32 S3 Uno form board. The DIYables Bluetooth STEM app sends live X and Y values from -100 to +100 over BLE, so you can steer a robot, aim a pan-tilt servo mount or drive motors from your phone.
In this tutorial, you will:
- Install the DIYables Bluetooth library in the Arduino IDE
- Upload a BLE joystick sketch to the ESP32 S3 Uno
- Connect the DIYables Bluetooth App from Android or iOS
- Read X/Y joystick values in the Serial Monitor
- Use the values to control motors, servos and LEDs
※ NOTE THAT:
The ESP32 S3 Uno supports only BLE (Bluetooth Low Energy). It has no Classic Bluetooth radio, so the BluetoothSerial version of this example does not work on it. The good news: BLE works with the DIYables Bluetooth App on both Android and iOS, and you do not need to pair the board first.

Features
The joystick app gives you a simple way to send two values at the same time. This makes it a natural fit for anything that moves in two directions.
Two Axes
You get an X axis and a Y axis. Each one goes from -100 to +100, and the center is (0, 0).
Live Updates
While you drag your finger, the app keeps sending new positions over Bluetooth. Your sketch gets each one right away.
Auto-Return and Sensitivity
You can make the stick jump back to the center when you let go. You can also set a minimum movement, so tiny finger shakes do not flood your code with updates.
Android and iOS, No Pairing
Because the ESP32 S3 Uno uses BLE, the same sketch works with both phone systems. You just scan and connect inside the app. BLE also uses less power than Classic Bluetooth.
Hardware Preparation
| 1 | × | 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 |
Or you can buy the following kits:
| 1 | × | DIYables Sensor Kit (18 sensors/displays) |
Additionally, some of these links are for products from our own brand, DIYables .
ESP32 S3 Uno Pinout
The main example needs no wiring, but the project examples below use the Uno header pins. This pinout diagram shows each header pin (D2, D9, A0…) and its GPIO number.

ESP32 S3 Uno Code
The sketch below sets up a BLE server on the ESP32 S3 Uno and adds the joystick app to it. You do not need to wire anything for this first test. The board only needs the USB cable.
Detailed Instructions
- New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
- Connect the board to your computer with a USB Type-C cable.
- Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
- Set the partition scheme. Go to Tools > Partition Scheme and pick "Huge APP (3MB No OTA/1MB SPIFFS)". The Bluetooth library is large and does not fit in the default app space.
- Open Library Manager. Click the Libraries icon on the left bar of the Arduino IDE.
- Find the library. Search "DIYables Bluetooth" and look for the DIYables Bluetooth library by DIYables.
- Install it. Click the Install button.
- Search for DIYables Bluetooth created by DIYables and click the Install button.
- Install the dependencies. When the IDE asks about other libraries, click Install All.
- Tip: If the upload does not start, hold the BOOT button, press RESET, then release BOOT and try again.
ESP32 S3 Uno BLE Code (works with the app on Android and iOS)
This sketch creates a BLE device named ESP32BLE_Joystick and waits for the app. Each time you move the joystick, the callback saves the X and Y values and prints them. When the app opens the joystick screen, the onGetConfig() callback sends the last saved position back, so the app shows the right place.
- Load the example. In the Arduino IDE, go to File Examples DIYables Bluetooth Esp32BLE_Joystick, or copy the code below into the editor.
- Upload. Click the Upload button to send the code to the ESP32 S3 Uno.
- Open the Serial Monitor and set it to 115200 baud.
- Check the output. You should see:
Mobile App
Now the board is waiting, and your phone becomes the controller. With BLE there is no pairing step in the phone settings. You connect from inside the app.
- Open the DIYables Bluetooth App.
- Allow the permissions the first time you open it:
- Nearby Devices (Android 12+) or Bluetooth (iOS) - needed to scan and connect
- Location (Android 11 and below only) - older Android versions need it to scan for BLE devices
- Turn on Bluetooth on your phone.
- Scan. On the home screen, tap the Connect button. The app looks for nearby BLE devices.

- Connect. Tap "ESP32BLE_Joystick" in the scan list.
- Open the Joystick app. After it connects, the app returns to the home screen. Tap Joystick in the app menu.

※ NOTE THAT:
You can tap the settings icon on the home screen to hide or show apps. For more details, read the DIYables Bluetooth App User Manual.
- Move the joystick in any direction.

- Watch the Serial Monitor. The X/Y values show up in real time:
Creative Customization - Adapt the Code to Your Project
The basic sketch only prints numbers. The parts below show the library functions you will use to turn those numbers into real actions on the ESP32 S3 Uno.
Configure Auto-Return and Sensitivity
The constructor takes two settings. The first one turns auto-return on or off. The second one is the smallest change (in percent) that sends a new update. You can also change both while the sketch runs and read them back.
Handle Joystick Position Changes
All your control code goes into the onJoystickValue() callback. It gets X (left to right) and Y (down to up) each time the stick moves.
Handle Configuration Request from App
When the app opens the joystick screen, it asks the ESP32 S3 Uno for the current values. Answer in onGetConfig() so the app draws the stick in the right place.
Send Values to App
Data can also go the other way. The ESP32 S3 Uno can push a position or a short text message to the app at any time.
Handle Connection Events
It is smart to know when the phone connects or leaves. For a moving robot, the disconnect event is the right place to stop the motors.
How to Use the Joystick
Knowing the value range helps you map the joystick to your hardware. Here is what the app shows and what the numbers mean.
App Interface Controls
The screen has a round joystick pad that you touch and drag. Under it, the app shows the current X value and Y value, each from -100 to +100.
Value Ranges
| Axis | Minimum | Center | Maximum |
|---|---|---|---|
| X | -100 (full left) | 0 | +100 (full right) |
| Y | -100 (full down) | 0 | +100 (full up) |
When you do not touch the stick (or when auto-return is on and you let go), the position is (0, 0).
Programming Examples
These short examples show common ways to use the joystick values. All pins use the Uno header positions, with the ESP32 S3 Uno GPIO number in the code.
Basic Joystick Handler
This is the smallest useful handler. It saves the latest position and prints it.
Two-Wheel Robot Control
A two-wheel robot turns by running its wheels at different speeds. The code mixes X (turn) and Y (speed) into a left and a right speed. Each motor gets one PWM pin for speed and one pin for direction: left PWM on D9 (GPIO46), right PWM on D10 (GPIO10), left direction on D7 (GPIO14) and right direction on D8 (GPIO21).
WARNING
D9 (GPIO46) is a boot strapping pin on the ESP32 S3 Uno. If the motor driver pulls this pin HIGH while the board starts, the board may not boot or may not accept new code. If you have upload or boot problems, unplug the wire from D9, then upload or reset again.
Pan-Tilt Servo Control
The X value turns the pan servo and the Y value moves the tilt servo. The map() function changes -100..+100 into 0..180 degrees. On the ESP32 S3 Uno, use the ESP32Servo library (by Kevin Harrington) instead of Servo.h. The pan servo signal goes to D9 (GPIO46) and the tilt servo signal goes to D10 (GPIO10).
WARNING
The pan servo uses D9 (GPIO46), a boot strapping pin. Power the servos from their own 5V supply (with a shared GND), and keep the signal wire off D9 while you upload if the board will not boot. The ESP32 S3 Uno sends a 3.3V signal, which most hobby servos accept.
LED Matrix Direction Indicator
Four LEDs show which way the stick points. An LED turns on only when the value goes past a threshold of 30, so small moves near the center do nothing. The LEDs connect to D2 (GPIO18), D3 (GPIO17), D4 (GPIO19) and D5 (GPIO20), each through a 220 ohm resistor.
Advanced Programming Techniques
Raw joystick values are fine for a test. For a real machine, you usually want smoother and safer control. These three tricks help.
Dead Zone Filter
A finger never rests exactly at the center. The dead zone treats any value close to zero as zero, so motors do not creep.
Speed Ramping
A sudden jump from 0 to full speed can make a robot jerk or tip over. Here the callback only stores a target, and loop() moves the real value toward it a little at a time.
Magnitude and Angle Calculation
Sometimes you want "how far" and "which way" instead of X and Y. The distance from the center gives a speed, and atan2() gives the angle in degrees.
Hardware Integration Examples
These two examples show bigger builds. They are starting points; add your own motor driver code where needed.
Mecanum Wheel Robot
A mecanum robot has four wheels and can slide sideways. Each wheel gets its own mix of X and Y. Here the four motor PWM signals use D2 (GPIO18), D3 (GPIO17), D4 (GPIO19) and D5 (GPIO20).
Stepper Motor Position Control
With the AccelStepper library, the joystick sets the speed of two stepper motors, one per axis. The X driver uses STEP on D2 (GPIO18) and DIR on D3 (GPIO17). The Y driver uses STEP on D4 (GPIO19) and DIR on D5 (GPIO20).
Why BLE Only on the ESP32 S3 Uno?
Some boards offer two Bluetooth modes: BLE and Classic Bluetooth. The ESP32 S3 Uno chip has only BLE, so this page uses only the Esp32BLE_Joystick example. The table shows what this means for your project.
| Feature | BLE on the ESP32 S3 Uno |
|---|---|
| iOS support | Yes |
| Android support | Yes |
| Power use | Low |
| Range | about 30-100 m in open space |
| Pairing | Not needed, connect inside the app |
| Best for | Battery projects and cross-platform control |
The Classic Bluetooth sketch (Esp32Bluetooth_Joystick, which uses BluetoothSerial) will not compile or run on this board. Always pick the BLE example.
Project Ideas
A joystick fits any project that moves in two directions. Here are some ideas to try with the ESP32 S3 Uno.
Robotics Projects
Build a Bluetooth differential drive robot, a mecanum or omni-wheel robot, a robotic arm joint controller or a simple drone ground station.
Camera Projects
Control a pan-tilt camera mount, a motorized camera slider or a remote security camera.
Game Projects
Make a Bluetooth game controller, a maze game or an LED matrix game like Snake or Pong.
Industrial Projects
Try a CNC jog controller, a motorized stage or a small crane or winch.
Integration with Other Bluetooth Apps
The joystick works well together with other apps from the same library. You add more than one app to the same Bluetooth server.
Combine with Bluetooth Slider
The joystick sets the direction, and a slider sets the top speed.
Combine with Bluetooth Monitor
The joystick drives the motors, and the monitor shows live data on your phone.
Next Steps
When the joystick works well, try these other DIYables Bluetooth App examples on the ESP32 S3 Uno:
- Bluetooth Slider - for exact analog value control
- Bluetooth Digital Pins - for simple on/off control
- Bluetooth Monitor - for watching joystick values on your phone
- Multiple Bluetooth Apps - for mixing the joystick with sliders and other controls
Support
If you get stuck, these places can help:
- Read the library API reference
- Visit the DIYables tutorials
- Ask in the Arduino community forums
FAQ
Does the ESP32 S3 Uno support Classic Bluetooth for this joystick example?
No. The ESP32 S3 Uno has only BLE (Bluetooth Low Energy). Sketches that use BluetoothSerial, like Esp32Bluetooth_Joystick, will not work. Use the Esp32BLE_Joystick example, which works with the app on both Android and iOS.
Can I use the DIYables Bluetooth joystick on an iPhone with the ESP32 S3 Uno?
Yes. iOS supports BLE, and the ESP32 S3 Uno uses BLE. Install the DIYables Bluetooth App from the App Store, tap Connect and pick ESP32BLE_Joystick. No pairing in the phone settings is needed.
Why do I need the "Huge APP" partition scheme?
The BLE stack and the DIYables Bluetooth library make the sketch large. The default partition gives only about 1.2 MB for your program, so the upload can fail with a "sketch too big" error. "Huge APP (3MB No OTA/1MB SPIFFS)" gives about 3 MB, but you lose over-the-air updates.
Is the UNO R4 code the same as the ESP32 S3 Uno code?
The joystick logic is the same, but the setup is different. The UNO R4 WiFi uses the DIYables_ArduinoBLE.h platform and 9600 baud. The ESP32 S3 Uno uses DIYables_Esp32BLE.h and 115200 baud. For servos, the ESP32 S3 Uno needs the ESP32Servo library instead of Servo.h.
Can I connect 5V motor drivers and servos to the ESP32 S3 Uno pins?
The ESP32 S3 Uno pins work at 3.3V and are not 5V tolerant. Sending 3.3V signals out to a 5V motor driver or servo usually works. But never send a 5V signal back into an ESP32 S3 Uno pin. Use a level shifter or a voltage divider for that.
What if my robot needs more pins than the Uno headers give?
The ESP32 S3 Uno has two extra rows of holes with more GPIOs: GPIO15 and GPIO16 (I/O, PWM, analog), GPIO45 and GPIO35 to GPIO42 (I/O, PWM), and GPIO47/GPIO48 (output only, PWM). Solder pin headers to them and write the GPIO number in your code. For extra motor PWM or direction pins, GPIO35 to GPIO42 are a good choice. Be careful with two groups of pins. First, GPIO47 and GPIO48 may run at 1.8V instead of 3.3V on some modules (mostly ones with "V" in the name, like R8V or R16V), so 3.3V devices can be damaged or act strangely. Second, GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.
Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| No COM port shows up in Arduino IDE | USB driver missing or charge-only cable | Install the CP210x or CH340 driver, use a data USB cable, or hold BOOT while you press RESET |
| "Sketch too big" error when compiling | Default partition scheme is too small for the Bluetooth library | Set Tools > Partition Scheme to "Huge APP (3MB No OTA/1MB SPIFFS)" |
| Compile error about BluetoothSerial | Classic Bluetooth example was used | Use the Esp32BLE_Joystick example because the ESP32 S3 Uno has BLE only |
| App cannot find ESP32BLE_Joystick | Sketch not running, phone Bluetooth off or missing permission | Check the Serial Monitor for "Waiting for Bluetooth connection...", turn on Bluetooth, allow Nearby Devices, and on Android 11 or older turn on Location |
| Joystick moves but nothing happens | Callback not set or Serial Monitor at wrong baud | Check that onJoystickValue() is set in setup() and set the Serial Monitor to 115200 baud |
| Values jump or look erratic | Sensitivity too low or no dead zone | Call setSensitivity(10.0) and add a dead zone filter in the callback |
| Connection drops often | Too far away, BLE interference or weak power | Move the phone closer, turn off other BLE devices nearby and use a good USB cable or power supply |
| Motors keep running after release | Auto-return off or no stop on disconnect | Call setAutoReturn(true), add a dead zone and stop the motors in setOnDisconnected() |
| Board does not boot or upload with motors or servos wired | Wire on D9 (GPIO46) holds the boot strapping pin at the wrong level | Unplug the D9 wire while you upload or reset, then plug it back in |
| Board resets when motors start | Motors take power from the board | Power motors and servos from a separate supply and connect all GND wires together |
Debug Tips
Add this helper to your sketch and call it from the joystick callback. It prints the raw values, the distance from the center and the angle, so you can see what the app really sends.