ESP32 S3 UNO - Button - Servo Motor

This ESP32 S3 Uno button servo motor tutorial shows you how to wire a push button and a servo motor to the ESP32 S3 Uno form board and control the servo with Arduino code. Each press of the button moves the servo to 90 degrees, and the next press moves it back to 0 degrees. You will write the button control servo motor code twice: once in the simple way, and once with debouncing so every press is read correctly.

In this tutorial, you will:

  1. Wire a button and a servo motor to the ESP32 S3 Uno
  2. Detect a button press with digitalRead() and INPUT_PULLUP
  3. Rotate a servo motor with the ESP32Servo library
  4. Add button debouncing with the ezButton library
ESP32 S3 Uno button servo motor

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-mount Button with Cap
1×Breadboard-mount Button Kit
1×Panel-mount Push Button
1×Push Button Module
1×Servo Motor
1×Breadboard
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Buy Note: For controlling multiple servo motors, use the PCA9685 16 Channel PWM Servo Driver Module to save MCU pins and simplify wiring.

Overview of Servo Motor and Button

This project joins two simple parts: a button as the input and a servo motor as the output. If one of them is new to you, read its own tutorial first. They explain the pinout, how each part works, and how to program it.

Servo motor

A servo turns its arm to an exact angle, from 0 to 180 degrees, based on a PWM signal from the board. See the ESP32 S3 Uno - Servo Motor tutorial.

Button

A push button connects two pins when you press it. With the internal pull-up resistor, the pin reads HIGH when the button is released and LOW when it is pressed. See the ESP32 S3 Uno - Button tutorial.

ESP32 S3 Uno Pinout

The image below shows the pinout diagram of the ESP32 S3 Uno form board. Use it to find the Uno header pins (D7, D9, 5V…) and their GPIO numbers when you wire the button and the servo.

ESP32 S3 Uno pinout diagram

Wiring Diagram

Connect the button to D7 and GND, and the servo signal wire to D9, as shown below. The servo takes its power from the 5V pin.

The wiring diagram between ESP32 S3 Uno Button Servo Motor

This image is created using Fritzing. Click to enlarge image

Component Pin ESP32 S3 Uno Pin
Button pin 1 D7 (GPIO14)
Button pin 2 GND
Servo VCC (red) 5V
Servo GND (brown or black) GND
Servo Signal (orange or yellow) D9 (GPIO46)

WARNING

D9 is GPIO46, a boot strapping pin on the ESP32 S3 Uno. The board reads this pin at power-up to pick its boot mode. A servo signal wire is normally safe here, but if the board does not boot or cannot upload code, unplug the servo signal wire from D9, upload, and then plug it back in.

※ NOTE THAT:

The servo runs from 5V, but the ESP32 S3 Uno only sends a 3.3V control signal to it. This is fine, because the signal goes OUT of the board. Most hobby servos read a 3.3V signal without problems. The button is wired to GND, so no 5V ever reaches an ESP32 S3 Uno pin.

ESP32 S3 Uno Code - Button Controls Servo Motor Without Debouncing

The sketch below reads the button on D7 (GPIO14) and remembers its last state. When the state changes from HIGH to LOW, it knows the button was just pressed, so it flips the angle between 0 and 90 degrees and sends the new angle to the servo on D9 (GPIO46).

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-button-servo-motor */ #include <ESP32Servo.h> #define BUTTON_PIN 14 // The ESP32 S3 Uno pin D7 (GPIO14) connected to button's pin #define SERVO_PIN 46 // The ESP32 S3 Uno pin D9 (GPIO46) connected to servo motor's pin Servo servo; // create servo object to control a servo int angle = 0; // the current angle of servo motor int lastButtonState; // the previous state of button int currentButtonState; // the current state of button void setup() { Serial.begin(9600); // initialize serial pinMode(BUTTON_PIN, INPUT_PULLUP); // set ESP32 S3 Uno pin to input pull-up mode servo.attach(SERVO_PIN); // attaches the servo on pin D9 (GPIO46) to the servo object servo.write(angle); currentButtonState = digitalRead(BUTTON_PIN); } void loop() { lastButtonState = currentButtonState; // save the last state currentButtonState = digitalRead(BUTTON_PIN); // read new state if(lastButtonState == HIGH && currentButtonState == LOW) { Serial.println("The button is pressed"); // change angle of servo motor if(angle == 0) angle = 90; else if(angle == 90) angle = 0; // control servo motor arccoding to the angle servo.write(angle); } }

The ESP32 S3 Uno cannot use the standard Servo.h library. The code uses ESP32Servo.h instead, which has the same attach() and write() functions, so the rest of the logic stays the same.

Detailed Instructions

  1. New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
  2. Wire it up as shown in the diagram.
  3. Connect the board to your computer with a USB Type-C cable.
  4. Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
  5. Install the ESP32Servo library. Open the Library Manager, search for ESP32Servo, and install the one by Kevin Harrington.
  6. Copy the code above and paste it into Arduino IDE.
  7. Upload the code by clicking the Upload button.
  8. Press the button a few times and watch the servo arm swing between 0 and 90 degrees.
  9. Open the Serial Monitor at 9600 baud to see a message for every press.
  10. Tip: If the servo shakes or the board resets when the servo moves, power the servo from a separate 5V supply and connect its GND to the board GND.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
The button is pressed The button is pressed The button is pressed The button is pressed
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

※ NOTE THAT:

This simple code does not always work well. A real button contact bounces for a few milliseconds, so one press can look like several presses, and the servo may move twice or not at all. Debouncing fixes this. Writing debounce code by hand is hard for beginners, but the ezButton library makes it easy.

ESP32 S3 Uno Code - Button Controls Servo Motor With Debouncing

This version does the same job, but the ezButton library filters out the contact bounce. It ignores any change shorter than 50 milliseconds, so one press always counts as one press. To learn why debouncing matters, read the ESP32 S3 Uno - Button Debounce tutorial.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-button-servo-motor */ #include <ESP32Servo.h> #include <ezButton.h> #define BUTTON_PIN 14 // The ESP32 S3 Uno pin D7 (GPIO14) connected to button's pin #define SERVO_PIN 46 // The ESP32 S3 Uno pin D9 (GPIO46) connected to servo motor's pin ezButton button(BUTTON_PIN); // create ezButton object that attach to pin D7 (GPIO14); Servo servo; // create servo object to control a servo int angle = 0; // the current angle of servo motor void setup() { Serial.begin(9600); // initialize serial button.setDebounceTime(50); // set debounce time to 50 milliseconds servo.attach(SERVO_PIN); // attaches the servo on pin D9 (GPIO46) to the servo object servo.write(angle); } void loop() { button.loop(); // MUST call the loop() function first if(button.isPressed()) { Serial.println("The button is pressed"); // change angle of servo motor if(angle == 0) angle = 90; else if(angle == 90) angle = 0; // control servo motor arccoding to the angle servo.write(angle); } }

Notice that button.loop() must run at the start of every loop() pass. It updates the button state, and then button.isPressed() tells you if a new press has happened.

Detailed Instructions

  1. Install the ezButton library. See How To.
  2. Copy the code and open it in Arduino IDE.
  3. Upload the code to the ESP32 S3 Uno by clicking the Upload button.
  4. Press the button several times.
  5. Watch the servo move once for every press, with no double moves.
  6. Tip: You can change the debounce time in button.setDebounceTime(). Try a higher value if your button is old or noisy.

Video Tutorial

Watch the video below to see this ESP32 S3 Uno project step by step.

FAQ

Can the ESP32 S3 Uno power a servo motor directly?

A small servo like the SG90 can run from the 5V pin when the board is powered by USB. Bigger servos draw more current and can make the board reset. For those, use an external 5V supply and connect its GND to the ESP32 S3 Uno GND.

Why does the code use ESP32Servo.h instead of Servo.h?

The standard Servo library only supports AVR and some other Arduino boards, not the ESP32 S3 Uno. The ESP32Servo library by Kevin Harrington uses the PWM hardware of the board but keeps the same functions. Your UNO R4 servo code works after you change only the include line and the pin numbers.

Does the servo work with the 3.3V signal from the ESP32 S3 Uno?

Yes, most hobby servos accept a 3.3V control signal. The servo still gets 5V for power on its red wire. Only the signal wire goes to the GPIO pin, and that signal goes out of the board, so no level shifter is needed.

Why do I need debouncing for the button?

The metal contacts in a button bounce for a short time when you press it. The board is fast enough to see these bounces as many presses. Without debouncing, the servo can move twice or stay in the same place after one press.

Can I use a different pin for the servo instead of D9?

The wiring diagram uses D9 (GPIO46), which is a boot strapping pin. It works in most cases, but if you have boot or upload problems, you can move the signal wire to another PWM pin such as D5 (GPIO20). Then change SERVO_PIN in the code to 20.

What if my project 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 use them and write the GPIO number in code. For extra buttons, use GPIO35 to GPIO42, not GPIO47/GPIO48, because those two are output only. For extra servos, GPIO15, GPIO16 or GPIO35 to GPIO42 work well. Be careful with two things. First, GPIO47/GPIO48 may run at 1.8V instead of 3.3V on some modules (especially 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 board not in upload mode Install the CP210x or CH340 driver. Or hold BOOT, press RESET, then release BOOT and upload again
Upload fails or board does not boot The servo signal on D9 (GPIO46) affects the boot strapping pin Unplug the servo signal wire from D9 during upload, then plug it back in
Compile error "Servo.h - No such file" The code uses the AVR Servo library Install the ESP32Servo library and use #include
Compile error about ezButton.h The ezButton library is not installed Install ezButton from the Library Manager
Servo does not move at all Wrong wiring or no power to the servo Check that red goes to 5V, brown to GND and the signal wire to D9
Servo jitters or the board resets The servo draws too much current from USB Power the servo from an external 5V supply and join the GNDs
One press moves the servo twice Button contact bounce Use the debouncing code with the ezButton library
Button press is never detected Button not wired to GND or wrong pin Wire one button leg to D7 (GPIO14) and the other leg to GND

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!