ESP8266: Controlling a DC motor

Introduction

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

Hardware

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.

Connection diagram to control the DC motor with an ESP8266 and the ULN2803A.
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.

Setup

In order to control the DC 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 DC 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
delay(5000);
digitalWrite(motorPin,LOW);  //Turn off the motor
delay(2000);

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
  delay(5000);
  digitalWrite(motorPin, LOW); //Turn off the motor
  delay(2000);

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

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

  }

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

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

  }

  analogWrite(motorPin, 0); //Disable PWM

}

The complete code

The complete code can be seen in the snippet below.

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

void setup() {

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

}

void loop() {

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

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

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

  }

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

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

  }

  analogWrite(motorPin, 0); //Disable PWM

}

Testing the code

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

References

[1] http://bbs.espressif.com/viewtopic.php?t=139

[2] http://www.ti.com/lit/ds/symlink/uln2803a.pdf

Technical details

  • ESP8266 libraries: v2.3.0.

3 thoughts on “ESP8266: Controlling a DC motor”

  1. Pingback: Buying cheap electronics at eBay: part 3 | techtutorialsx

  2. Pingback: Buying cheap electronics at eBay: part 3 | techtutorialsx

    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

    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

Discover more from techtutorialsx

Subscribe now to keep reading and get access to the full archive.

Continue reading