ESP8266: Controlling a motor with the ULN2803A

The objective of this post is to explain how to control a motor, including its speed, using an ESP8266 and an ULN2803A integrated circuit.


Since the digital pins of a microcontroller can only source a limited amount of current (in the case of the ESP8266, 12 mA maximum [1]), we can’t directly use them to control a DC motor. So, we are going to use an ULN2803A to be able to supply the current needed for the motor to move.

The connection diagram for this tutorial is very simple and can be seen in figure 1. We are just using a digital pin of the ESP8266 to control the ULN2803A and thus, the motor.


Figure 1 – Connection diagram to control the DC motor with an ESP8266 and the ULN2803A.

As stated in a previous post, the ULN will act as as switch, turning on or off the connection of the motor to GND when the corresponding input pin of the IC is at a HIGH or LOW voltage, respectively. Naturally, this HIGH or LOW voltage is controlled by the ESP8266.

This way, the current needed for the motor to operate is provided by a 5V power supply and sinked in the ULN2803, and the ESP8266 doesn’t get damaged. Since the ULN2803A can be controlled by 3.3 V signals [2], it will work fine with the ESP8266.



In order to control the motor we will only need to use a digital pin of the microcontroller and thus no library needs to be included. So, we will only initialize the pin as an output pin.

int motorPin = 5; //Pin that will control the motor

void setup() {

pinMode(motorPin, OUTPUT);  //Initialize the pin as output pin



The main loop

The code to control the motor is very simple, as we will see below.

To control if the motor is on or off, we just need to change the values of the digital pin from HIGH to LOW. This way, it will be set to either run at full speed or stopped.

digitalWrite(motorPin,HIGH);  //Turn on the motor at full speed
digitalWrite(motorPin,LOW);  //Turn off the motor

Now, if we want to control the speed of the motor, we can use PWM, by calling the analogWrite function. This function receives as inputs the pin where to generate the PWM signal and the duty cycle of the signal. We just need to remember from the previous post that the default range of values of duty cycle for the ESP8266 implementation is between 0 and 1023.

For the value 0, the pin of the ESP8266 that controls the ULN2803A will always be at 0 V (GND), and thus no voltage will be applied to the motor. For the value of 1023, the voltage of the ESP8266 pin will always be 3.3 V and thus the ULN2803A will output 5V.

For any intermediate value between 0 and 1023, the duty cycle of the square wave produced by the ESP8266 will be replicated by the ULN2803A and thus the motor will have a simulated analog voltage between 0 and 5V, which will make its speed vary accordingly.

So, we would call the AnalogWrite function as seen bellow for an intermediate value.

analogWrite(motorPin, 950);

We need to keep in mind that there’s a minimum voltage value for the motor to start rotating. Thus, it’s normal that, at low values of duty cycle, it stays stopped and only after a threshold (that will depend on the motor used) it will start spinning.

The final code can be seen bellow. In this case, we first turn off the motor at full speed and then turn it off, by using the digitalWrite function. Then, we start from 0 V and gradually increment the voltage applied until 5 V, by using the analogWrite function.

Once achieving the 5 V, we then gradually reduce the voltage again to 0 V. Also, a call to the analogWrite function with a value of 0 for the duty cycle is made in the end of the loop because this needs to be done to disable the PWM on the pin. Otherwise, the next calls to the digitalWrite functions would not work. You can check more details on the previous post.

void loop(){

digitalWrite(motorPin,HIGH); //Turn on the motor at full speed
digitalWrite(motorPin,LOW); //Turn off the motor

int i;
for ( i=0; i<1023;i=i+5){

analogWrite(motorPin,i);  //Gradually increase the speed


for (; i>0;i=i-5){

analogWrite(motorPin,i);  //Gradually decrease the speed


analogWrite(motorPin,0); //Disable PWM


The final result is shown in the video bellow. As stated before, just after a certain duty cycle the simulated analog voltage gets high enough for the motor to start moving. So, the noise that is heard before the motor starts is the result of applying a voltage to its terminals that is not enough to make it move.



Related Posts


Related content






Technical details

  • ESP8266 libraries: v2.3.0.

3 Replies to “ESP8266: Controlling a motor with the ULN2803A”

    1. Hi!

      No, this code / hardware is just for uni-directional control of the motor.

      In order to do that the easiest way is probably using a H-Bridge :).

      The code would need to be different.

      Best regards,
      Nuno Santos


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s