ESP32 Arduino: Controlling a DC motor

In this tutorial we will check how to control a DC motor, using an ESP32 and the Arduino core. The tests shown on this tutorial were performed using an ESP32 board from DFRobot.


In this tutorial we will check how to control a DC motor, using an ESP32 and the Arduino core.

We will be using an ULN2803A integrated circuit to power the DC motor, since we cannot directly connect a digital pin of the ESP32 to the motor.

You can read more about the ULN2803A on its datasheet. You can also read a more detailed explanation on how the device works and how we can use it to control a DC motor on this previous tutorial.

Regarding the DC motor, I’ll be using a generic and cheap 5 V device. The tests shown on this tutorial were performed using an ESP32 board from DFRobot.

The electric schematic

Taking in consideration that the digital IO pins of the ESP32 can only source a maximum current of 40 mA [1], we cannot directly use them to control a DC motor.

Instead, we are going to use a ULN2803A integrated circuit to actually provide the current to the motor, while the ESP32 will simply control if the motor is running or stopped.

The connection diagram to control a DC motor from the ESP32 using an ULN2803A can be seen below at figure 1.

Schematic for controlling a DC motor with the ESP32, using a ULN2803A integrated circuit

Figure 1 – Electric diagram for controlling a DC motor with the ESP32 and a ULN2803A IC.

In short, the ULN2803A will act as a switch, which will turn on / off the connection of the motor to GND, depending on the state of the input pin labeled as In 1.

So, when the GPIO of the ESP32 is at a digital high value (VCC), the ULN2803A will connect the motor to GND, and thus the motor will be on. When the GPIO is at a digital low value (GND), then the motor will be disconnected from GND, and thus it will be off.

Furthermore, the ULN2803A can be controlled by 3.3 V inputs and provide higher voltages, allowing us to control a 5 V DC motor with the ESP32.

The code

The code for this tutorial will be very simple, since we basically only need to control the status (high or low) of a digital pin of the ESP32.

So, we will start by declaring as a global variable the number of the pin that will be connected to the DC motor.

In my case I’ll be using GPIO 13. Note that for the Beetle ESP32 board, which is the one I’m using, this maps to the pin labeled as D7.

int motorPin = 13;

After that, we need to initialize the pin as output, in the Arduino setup function. To do that, we simply need to call the pinMode function.

This function receives as first argument the number of the pin and as second argument a constant indicating the operating mode. So, we will pass the as first argument the value of the pin stored in our previously declared global variable and as second argument the constant OUTPUT.

void setup() {

  pinMode(motorPin, OUTPUT);


We will write the rest of our code in the Arduino main loop. We will first turn on the motor, wait some seconds, turn it off, wait some more seconds and then repeat.

So, to turn the motor on, we simply need to set the value of the ESP32 digital pin to high, which will make the motor run at full speed. We can set the digital level of a pin with a call to the digitalWrite function.

This function receives as first argument the number of the pin and as second argument a constant indicating the digital level to which the pin should be set.

Again, we will make use of our global variable that contains the pin number and pass it as first argument of the digitalWrite function. As second argument we will pass the constant HIGH.

digitalWrite(motorPin, HIGH);

After that we will wait 10 seconds, so the motor stays on for a bit. To introduce a delay in our program, we simply need to call the delay function, passing as input the number of milliseconds to wait.


After this, we will now turn off the motor and wait also for 10 seconds. We will use again the digitalWrite function but this time we will pass the constant LOW as second parameter.

digitalWrite(motorPin, LOW);

The final complete code can be seen below. Note that since we are writing our on / off logic inside the Arduino main loop, this part of the program will keep repeating continuously.

int motorPin = 13;

void setup() {

  pinMode(motorPin, OUTPUT);


void loop() {

  digitalWrite(motorPin, HIGH);
  digitalWrite(motorPin, LOW);


Testing the code

To test the code, simply compile it and upload it to your device, after having all the electric connections completed. When the code uploading procedure finishes, the motor should start moving and then stopping in 10 seconds intervals, as shown in the video below.

Related Posts



4 Replies to “ESP32 Arduino: Controlling a DC motor”

  1. Where in the world did you find out the pin numbers for the Arduino IDE for this board? I have no idea how to find them!?

    1. an Arduino boards package with configuration for your board has constants for pins which correspond to labels on the PCB. The constants are defined in pins_arduino.h file, which is applied only if you choose the corresponding board in Tools menu. In code you should use this constants as values for your constants, like for example const uint8_t LED1_PIN = D2;.

      If the boards package doesn’t have the board and you use generic settings, the you can study the schematics of the board to see which PCB pin goes to which MCU pin. Usually the logical pin numbers are labeled in schematics additionally to physical pin numbers of the chip.

      Note: The linked pins_arduino.h is for FireBeetle ESP32. The Beetle ESP32 is not defined in ESP32 boards package yet.

  2. Good day dear Declan Rixon – this is a great question – i like your question – and i must say – i have no glue. Can you help me please! Look forward

    1. Hi martin, it’s been a while since this happened but I think I looked at the documentation and traced the labels on the breakout board back to the GPIO## pins, so if a pin is attached to GPIO14 on the actual esp32 chip, then it is 14 in the Arduino IDE. This seems obvious now but I wish someone had told me so I didn’t have to figure it out the long way.

Leave a Reply