Today we’ll see a few ways of interfacing servo motors to the ESP32 microcontroller and controlling them with code, with a potentiometer, and over WiFi.

Introduction

We have already looked at both the ESP32 microcontroller and at using analog servo motors, and today we’ll put both of them together. We’ll see how to interface and control servo motors with the ESP32 and we’ll take advantage of the microcontrollers’ WiFi capabilities to control a servo with a web-based interface.

As you’ll soon see, controlling a servo motor with the ESP32 is quite similar to using an Arduino, with the added advantage of the ESP32’s wealth of ports and capabilities.

Servos & ESP32

Controlling an analog servo motor, which is the type of servo motors most commonly used by hobbyists, is a task that most microcontrollers have no problem performing.  Arduino’s, for example, have no problem controlling servos and the Arduino IDE even comes with a built-in servo motor library and a few bits of sample code to get you started.

Servo Motors & ESP32

So why use an ESP32, especially as most Arduino’s are less expensive?  Depending upon your application there may be no reason, or there may be several. Here are a few:

  • The ESP32 has a wealth of I/O ports, more than most Arduino’s.
  • The ESP32 has analog outputs as well as analog inputs.
  • There are built-in sensors in the ESP32, including a hall-effect sensor.
  • The ESP32 has I/O pins that can be used as touch switches
  • It has a lot of PWM output pins, so it can drive several servo motors.
  • It has built-in WiFi and Bluetooth capabilities.

The latter reason is why many people choose the ESP32 over an Arduino for controlling servo motors. Built-in WiFi and Bluetooth open the door to all sorts of remote control possibilities. 

Servo Motors

Servo motors are geared DC motors that have an integrated servomechanism with a feedback loop to allow precise positioning of the motor shaft. A high gear ratio allows a small servo to have an impressive torque rating. 

Most servos are limited in rotation to either 180 or 270 degrees, with 180-degree servo motors being more common.   There are specially modified servo motors that can rotate beyond 360-degrees, but we won’t be working with those today.

Servo motors come in a wide range of sizes and can be controlled either with an analog PWM signal or with a digital I/O signal. The inexpensive servos we use for hobbyist applications are usually analog servo motors, which are the types we will be using today.

Servo Motors

A very common and inexpensive servo motor is the SG90. It’s a small plastic-gear servo that has become a standard for experimenting and is also used in a lot of RC hobby applications. It has a “cousin”, the MG90, which has similar specifications but uses metal gears.

The SG90, like most servo motors, can be powered from 5-6 volts, so servo motors are great for battery-powered applications.

Servo Motor Connections

Most analog servo motors like the SG90 use a 3-wire color-coded cable for interfacing. Although the color-coding is not an official standard many manufacturers use the same colored wires:

  • Orange – The PWM servo control input. This is a logic-level signal, and most servo motors can accept 3.3-volt logic as well as 5-volt logic.  Some models, especially 270-degree rotation servos,  use a White wire for this connection.
  • Red – The servo motor power supply input. Generally 5-6 volts DC, but be sure to check first.
  • Brown – The ground connection. On some servo motors, this is a Black wire.

Servo Motor Pinout - Normal

Most servo motor cables terminate in a 3-pin Dupont female connector.  You can use jumper wires to connect this to a solderless breadboard.

Servo Positioning

Analog servo motors use PWM, or Pulse Width Modulation, to control the motor shaft position. 

The PWM signal is usually about 50Hz, which is a period of 20ms. Within that period the pulse width is varied, a shorter pulse positions the servo towards the zero-degree mark while a longer one moves the motor shaft towards the 180 (or 270) degree position.

The pulse is continually applied to the control lead on the motor, locking the shaft into the desired position.

If you’d like a more detailed overview of servo motor operation check out the article Using Servo Motors with the Arduino

ESP32 PWM

Most microcontrollers can be used to generate PWM signals and the ESP32 is certainly no exception. In fact, the ESP32 has the capability of controlling 16 PWM outputs independently.

One thing to note about the ESP32, however, is that many of the GPIO pins have multiple functions.  So when selecting a PWM pin to use with your servo motor you’ll want to be sure that you don’t need one of the pins other functions in your design.

Even with that slight restriction, there are still several PWM pins available to drive servo motors, LEDs, and many other devices.

ESP32Servo Library

The Arduino IDE comes with a built-in servo motor control library, which is appropriately named “Servo”. Unfortunately, it won’t work with the ESP32.

There are many servo motor control libraries available for the ESP32, many of which emulate the Arduino Servo library while adding new functionality.

I’ve chosen to use the ESP32Servo Library by Kevin Harrington. This library duplicates the functionality of the original Arduino Servo library while adding a few extra features of its own.

IDE Setup

In order to work with ESP32 boards in the Arduino IDE, you are going to need to add a new Board Manager into the IDE. You’ll then use that new Board Manager to import the ESP32 boards and software examples.

You’ll need to open the Preferences box, which you’ll find under the File menu item, and then add the following location to the “Additional Boards Manager URLs” box:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

After doing that and restarting the IDE you can go into the Boards Manager, which you’ll find under the Tools/Boards menu item, and search for ESP32. You should see an entry for “esp32 by Espressif Systems”. Highlight this entry and click on the Install button. 

For more detailed instructions see my ESP32 introductory article.

Library Installation

You can install the ESP32Servo Library directly from within your Arduino IDE using the Library Manager.

Open the Library Manager, which you’ll find under the Sketch/Include Library/Manage Libraries menu item.

Type “ESP32Servo” into the search box. From the displayed libraries select the ESP32Servo library, when you do the OK button will appear. Click that button to install the library.

Once the library is installed open your File/Examples menu and scroll down to the section for ESP32Servo. You’ll see a number of examples, some with familiar names. The ones that look familiar are modified versions of the example sketches from the Arduino Servo Library.

We are going to test out a couple of those sketches right now, but before we do we’ll need to get our ESP32 and servo motor all hooked up.

ESP32 Servo Hookup

For our first two experiments you’ll need the following parts:

  • An ESP32 WROOM based module. You don’t need to use the same module I used, just make sure you have a pinout diagram of your module handy so that you can wire to the correct pins.
  • A Servo Motor. I used an SG90, but any small analog servo motor will work. You can fine-tune the servo position in the code for just about any servo motor.
  • A Potentiometer. I used a 10k linear pot, but any value from 5k upwards should work. Just make sure it is a linear-taper pot, i.e. it is at half-value when the shaft is turned to the halfway point.
  • A Servo Power Supply. I always advocate powering motors with a power supply independent of the microcontroller. The servos usually need 5-6 volts. A 4-cell AA or AAA battery pack makes a great power supply for a servo motor.

For our experiments, you can just power the ESP32 using the USB connection to your computer. To run the circuit away from the computer you can use it’s 5-volt or 3.3-volt power pins to power it independently.

Here is the hookup, if your module has a different pinout then just make sure to use GPIO pin 18 for the PWM output. If you would like to use a different PWM-capable pin you’ll need to change the code to match.

ESP32 Servo Hookup

For my tests, I elected to use a breadboard power supply to supply the motor voltage with 5-volts. You can also use a 6-volt battery or other suitable supply to power the motor.

Make sure you use 3.3-volts on the connection to the potentiometer and not 5-volts.

Servo Motor & ESP32 with Breadboard Power Supply

Once you have it all wired up connect it to your computer with the USB cable.

Example 1 – Sweep

The two examples we are going to look at are both updated versions of classic Arduino sketches. You won’t need to write any code, as these example sketches were included when you installed the ESP32Servo library.

The function of the Sweep sketch is pretty simple, it sweeps the servo motor shaft from zero to 180 degrees and then back to zero. It repeats this as long as it is powered up.

The only modifications made to the Sweep sketch from the original are the changes necessary to use the ESP32Servo library instead of the Arduino Servo library.

After including the ESP32Servo library we define an object called “myservo” to represent the servo motor.  We also define the GPIO pin that the control input for the servo is connected to.

In the setup you will note the timer allocation statements, something you will need to do when using the ESP32Servo library. 

We then define the frequency that we will be using to drive the servo control. 50Hz is pretty standard, but you can play with this value to improve servo performance.

Then we attach our servo object to the servo motor. You’ll notice three parameters here:

  • The servo GPIO pin number.
  • The minimum pulse width, which should drive the servo to the zero position.
  • The maximum pulse width, which should drive the servo to its maximum position, typically 180 degrees.

The loop is very simple and consists of two for-loop counters. One counts from 0 to 180 and steps the servo in one direction, the other steps it in reverse back to the zero point. We then repeat everything.

Hook everything up, load up the code and take a look at it working. You should see the servo sweep back and forth.

ESP32 Servo Sweep Test

When I did this it worked, but not very well. My servo motor did indeed sweep, but it wasn’t a full 180-degrees. More like about half that.

The way to fix this is to modify the sketch and change the values for the minimum and maximum time. Every servo is different so you can experiment to find the best fit for your motor. For the SG90 I was using the values of 500 and 2400 seemed to work.

Example 2 – Knob

Knob is another “classic” Arduino sketch, it’s entire purpose is to allow you to position a servo motor using a potentiometer.  If that was ALL you wanted to do then using a microcontroller is a bit of an overkill, but of course, this is just a demonstration!

As with the Sweep sketch Knob has been modified to support the ESP32Servo library instead of the original Arduino library. It has also been adjusted to account for the increased resolution of the ESP32’s analog to digital converters (ADC) over the Arduino’s.

The servo motor object is created and attached exactly as it was in the previous sketch.

Note the value of 4096 for ADC_Max, it represents the maximum value for the analog to digital converter. By default, the ESP32 uses a 12-bit A/D converter. 

In the loop, all we do is read the potentiometer position by obtaining a value from the A/D converter. This is mapped to a range of 0-180.

We then use this value to write to the servo object, which moves the servo motor to the desired position.

ESP32 Servo Knob Sketch

Run the sketch and twist the potentiometer. You should observe the servo motor moving when you move the potentiometer.

Multiple Servos with PCA9685

The ESP32 has the capability of driving 16 PWM channels, so you can drive several servo motors directly.  Some ESP32 Servo libraries only support a limited number of motors, however, the ESP32Servo library that we are using will support all 16 PWM pins.

However, bear in mind that the GPIO pins that support PWM also have other functions, some of which you might need in your project. 

You also might need MORE than 16 servo motors for a project as wild as it might sound. A “robot spider” with eight legs and three degrees of freedom per leg would need 24 servo motors, give it four degrees of freedom and the number goes up to 32.

Or you may want to minimize the number of connections to the ESP32, or locate your motors away (but not too far away) from the microcontroller.

All of these requirements sound like a good fit for the PCA9685.

PCA9685 16-Channel PWM Module

The PCA96845 is a 16-channel PWM controller module that can be used with servo motors, LEDs, and pretty well anything that you can control with a PWM pulse.

The module is an I2C device, so all of the work of timing and producing PWM signals is done onboard, freeing the host device (the ESP32 in this case) from having to deal with it.

This device has six selectable address bits, and you can cascade up to 62 of them on the same I2C bus.  This would allow you to control up to 992 servo motors! 

PCA9685 Modules

You can buy the device assembled or as a board with headers and terminals that you solder in yourself, allowing you more flexibility in incorporating the PCA9685 into your project.

The connections on the PCA9685 module are duplicated on each end, making it easy to use multiple modules.  By using right-angled Dupont male and female connectors you could “daisy chain” the modules. Just make sure to select a unique I2C address for each module. 

As I don’t have 992 servo motors in stock in the workshop at the moment I’ll confine myself to one module and two servo motors, but the coding principles can be extended to any number of modules and servo motors.

ESP32 PCA9685 Hookup

The PCA9685 is an I2C device and can operate with either 3.3 or 5-volt logic and power. We will be using 3.3-volt logic and will power the module from the ESP32.

ESP32 PCA9685 Servo Hookup

The I2C connections to the ESP32 are as follows:

  1. SDA – IO21
  2. SCL – IO22

Actually you can use any two pins on the ESP32 for your I2C connections and define them in software. GPIO pins 21 and 22 are the default if new pins are not declared.

You’ll note the use of pullup resistors for the I2C data and clock lines. As we are using 3.3-volt logic you should use values in the 2.4k to 3.3k neighborhood.

I connected my servo motors to connectors 0 and 12, but you can choose any two you like, and you may add more servo motors.  When you look at the code you’ll see how to define your motor hookup and how to address each motor.

For a power supply, I used a battery-holder with four type AA batteries. Any 5 or 6-volt power supply should suffice, especially if you are using small SG90 servo motors as I did.

ESP32 PCA9685 Code

A great source for obtaining PCA9685 modules is Adafruit, and if you know Adafruit then you’ll know that they don’t sell anything without creating extensive documentation, articles, code samples, and libraries. The PCA9685 is no different, so we will be using an Adafruit library that works with both the Arduino and the ESP32.

Here is the sketch I used to control the two servo motors using the ESP32 and the PCA9685.

The code makes use of an Adafruit library for the PCA9685, the Adafruit PWM Servo Driver library. You can obtain this directly within your Library Manager, just as you did with the ESP32Servo library.

We also use the Wire library, which is the built-in library for working with I2C.

As with our previous sketches we need to calculate some values to represent the minimum and maximum pulse width for our servo motors. Unlike the previous sketches we don’t specify this time period in microseconds but instead in “ticks”.

So what is a “tick”?

A tick is a time period used by the PCA9685.  On the PCA9685 you specify a pulse frequency in Hz. Each cycle of the pulse is divided into 4096 periods called “ticks”.

To make the pulse have a 50% duty-cycle you would hold it HIGH for the first 2048 ticks and then low for the remaining 2048 ticks.  For a 25% duty-cycle you would keep it HIGH for only 1024 ticks.

So the constants SERVOMIN and SERVOMAX represent the number of ticks in the minimum and maximum pulse widths.

Next, we define connections for our individual servo motors. As I connected my first motor on connector 0 and my second one on connector 12 I used 0 and 12, you can, of course, connect to any of the 16 connectors and define your motors accordingly.

I also defined a couple of variables to be used to represent the servo position.

In the Setup, we initialize the Serial Monitor, note the baud rate which is typical of ESP32 projects.  We also print to the monitor.

Then we initialize the PCA9685 and set its PWM frequency to 50Hz. You can experiment with this to improve your servo performance if you wish.

In the Loop, I got lazy and essentially copied the Sweep example twice! The difference here is that I’m driving the two servo motors and alternating between them. 

The key to understanding this part of the code is to see how the position data is written to the servo motor.  The setPWM function from the Adafruit library is used to position the motor. It has three parameters:

  • The Servo connector number, from 0 to 15
  • The Starting Tick for the pulse. In this example it is always set to 0.
  • The Ending Tick for the pulse. 

The tick values are determined using a map command against the SERVOMIN and SERVOMAX values.

ESP32 Servo & PCA9685

Hook everything up and load the code and then reset the ESP32. You should observe the two motors alternating through sweeps.

Web Remote Controlled Servo

Probably the greatest attraction of using an ESP32 with a servo motor is the potential for developing a remote control system using the ESP32s Bluetooth or WiFi.

Creating a remote control requires a two-way conversation between the users’ browser and the web server created by the ESP32. Traffic back from the browser can take several forms, from simple GET requests on the URL line to AJAX.   The ESP32 returns HTTP traffic to the web browser.

Here is a very simple web-based control for a servo motor. It has one control, a slider, whose purpose is to control the position or angle of the servo shaft.

ESP32 Web Server Hookup

If you have the breadboard still set up from our first experiments you can use it as-is. 

ESP32 Remote Servo Hookup

The only difference with the wiring is that we are no longer using the potentiometer, so you may remove it if you wish.

Make sure you know your WiFi SSID and password, as you’ll be needing it when coding. The ESP32 only supports 2.4GHz WiFi.

ESP32 Web Server Code

One of the best resources for ESP32 information on the web is the Random Nerd Tutorials website.  These folks (Rui and Sara Santos) are so good that Espressif, the company that manufactures the ESP32, refers to them on their blog as a source of quality ESP32 information.

I’ve used their site many times in my own ESP32 research, the following sketch is a blatant copy of one that Rui Santos wrote for Random Nerd Tutorials. I’ve only modified it in two slightly significant ways:

  • I changed the servo library to the ESP32Servo library, as Rui was using a different one.
  • I styled the page a bit differently.  Mine is blue!

The sketch is not only a great example of controlling a servo motor with a web-based interface, it’s a great example of controlling really anything with a web-based interface.  

The sketch starts a web server and creates a webpage that has a slider control. Sliding the control to a different position causes that position to be sent back to the ESP32 using AJAX. The ESP32 then positions the servo motor accordingly.

You could use the same arrangement to send numerical data to control almost anything, and of course you could add more controls using the same technique.

Here is the sketch:

The sketch makes use of the built-in WiFi Library for connectivity, as well as the ESP32Servo library.

You’ll need to supply your wifi credentials, remember that the ESP32 only works on 2.4GHz wifi.

In the Setup, we get the servo prepared and set the PWM frequency as well as the minimum and maximum points of travel, as we did before.

We then start the serial monitor, which will be needed to determine the IP address assigned to our ESP32 web server.

We connect to the wifi network using the supplied credentials and report the progress on the serial monitor. The assigned IP address is printed so that we can use a web browser to see our control.

In the loop, we listen for clients, which occur when someone loads or modifies our web page. When a client connection is detected we serve a web page and monitor for data sent back from the client.

The data being sent back will come from a slider control, which is being used to set the servo motor position.  When the slider is moved its position value is sent back to the web server.

This value is embedded in GET data in two parts, which are combined and converted to an integer to position the servo using the servo library functions. 

Once this is done we print the value to the serial monitor and then close the client connection. We then end the loop and start listening for another client connection.

ESP32 Web Server HTML

You can modify the sketch to style the website any way you want to, although for your first test I’d advise sticking with this code until you can at least verify that everything is working.

The HTML in the code is not that easy to read, as it is entered in the way the webserver will send it as opposed to a more human-readable fashion. 

So here is the HTML portion of the code in a more conventional format.

You can save the above as an HTML file if you like and then open it in your browser. Experiment with the CSS style settings to see the effects.

Once you have it looking the way you want, make note of the changed values, and adjust the sketch accordingly.

ESP32 Web Server Testing

Testing and troubleshooting the web-based interface is best done with both a web browser and the Arduino IDE Serial Monitor. 

You’ll need to use the IDE to begin. Start or reset the ESP32 and look at the boot message. You should see the ESP32 attempt to connect to your WiFi network using the credentials you supplied.

ESP32 WiFi IP Address

If the device fails to connect, reset it and try again, often the DHCP server in the router times out on the first try. 

If it connects then you’ll see the IP address assigned to the ESP32 printed on the Serial Monitor. Make note of that address, as it’s the one you’ll need to point your web browser to.

If you still can’t connect go back and check the network name and password you supplied.  Restarting your router may help if everything else fails.

Once you are connected you should see a screen with a slider. Above the slider is some test displaying the current servo position in degrees.

Move the slider and observe your servo motor, if all is working well it will move. 

ESP32 Web-based Servo Control

Watch the Serial Monitor when you move the slider. You will notice that for every move the client opens and closes a connection and passes a variable, which is displayed in the Serial Monitor. That variable should be the position of the slider. The variable is fed to the servo, moving it into position. 

Experiment with the code, change the colors and see if you can add a second servo to the system.

Conclusion

The ESP32 offers a number of servo motor control possibilities. With its wealth of GPIO pins and the ability to drive a large number of servos, as well as the built-in WiFi and Bluetooth, it can certainly make a good fit for any servo motor control project.

And don’t overlook another advantage of the ESP32 – it’s performance. This is an advanced microcontroller that can run at speeds up to 20 times faster than an Arduino, and it’s a 32-bit dual-core device as well.  

One advanced use for servos with an ESP32 would be object or face tracking. Two ESP32-driven servo motors could operate a pan-and-tilt platform with a camera that tracks objects or faces. 

Knowing how to interface servo motors to an ESP32 is a skill that is sure to pay off. I can’t wait to see what you design!

 

Resources

Code for this article – All of the code for the article in a ZIP file.

ESP32Servo Library – The ESP32 Servo Library by John Bennett.

Adafruit PWM Servo Library – Adafruit Library for controlling PCA9685

WiFi Servo Control – WiFi Servo Control on Random Nerd Tutorials

 

 

Using Servo Motors with ESP32
Summary
Servo Motors with the ESP32
Article Name
Servo Motors with the ESP32
Description
Learn how to use the ESP32 to drive servo motors. We will see how to use the ESP32Servo Library, drive multiple motors with the PCA9685 I2C module, and control a servo motor with a web-based interface.
Author
Publisher Name
DroneBot Workshop
Publisher Logo
Tagged on:

If you have a question...

Comments about this article are encouraged and appreciated. However, due to the large volume of comments that I receive, it may not be possible for me to answer you directly here on the website.

You are much more likely to get answers to technical questions by making a post on the DroneBot Workshop Forum. Your post will be seen not only by myself, but by a large group of tech enthusiasts who can quickly answer your question. You may also add code samples, images and videos to your forum posts.

Having said that, please feel free to leave constructive comments here. Your input is always welcome. Please note that all comments may be held for moderation.

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x