Controlling speed of DC Motors using Arduino

This is part 4 of my “Building Robots using Arduino” tutorial series, explaining how you can create robots using Arduino.

In this article we will see how we can control the speed of the DC motor using Arduino.

Recap

Last week, I explained how we can control the direction of DC motors using the H-Bridge L293D IC.

This week we will see how we can control the speed of the motor as well using the IC. Also I will talk about how we can encapsulate the entire logic into an Arduino Library.

Analog Write

Before we go ahead, we need to know about analogWrite function in Arduino.

In Arduino, the analogWrite function allows you to generate a PWM wave in a pin. If you have tried out the LED fade example in Arduino, then you already know how to use it. If not, then checkout the PWM tutorial from Arduino reference.

This function takes a value between 0 and 255 and doesn’t work on all pins in Arduino. In Arduino Uno, it works on pins 3, 5, 6, 9, 10 and 11.

Controlling Speed of DC Motors

To control the speed of the motor, all we need to do is to replace digitalWrite function on L293D enable pins to analogWrite. The speed of the motor depends on value that was passed to the analogWrite function. Remember the value can be between 0 and 255. If you pass 0, then the motor will stop and if you pass 255 then it will run at full speed. If you pass a value between 1 and 254, then the speed of the motor will vary accordingly.

Circuit

You can just reuse the same circuit from last week.

Remember, I asked you to connect the enable pins of H-bridge to pins 10 and 11 of Arduino. This is because pins 10 and 11 are PWM pins.

Code

You just have to replace the function digitalWrite with analogWrite in last weeks code. The value you pass to analogWrite function will decide the speed of the motor.

Here is the modified sketch that you can use to change the direction as well as the speed of the DC motors.

Library

I have encapsulated the logic of changing directions of DC motors in an Arduino library called DCMotorBot. The library is available in github from where you can download it.

Instead of setting the pins individually, you can call the following directions to change the direction of the motors. Check out the examples sketches inside the /examples folder of the library.

  • Start
  • Stop
  • MoveUp
  • MoveDown
  • TurnLeft
  • TurnRight

Note: I am still working on adding support for changing the speed(pwm) as well.

What’s next

Next week we will see how we can put together all we have learned so far and build a complete bot. It’s going to be existing, so don’t miss it 😉

Till then, happy roboting 😉

81 thoughts on “Controlling speed of DC Motors using Arduino

  1. rosamunda

    Hi there!
    I´m following your instructions to the letter (instead of a battery I´m using a wall adapter), but the motors run very, very slowly (as if they didn´t have enough power). Why could that be?
    Thanks!

    Reply
    1. Sudar Post author

      Are you using analogWrite() or digitalWrite() to the enable the enable pin?

      Also what is the output voltage of the power supply you are using?

      Reply
      1. rosamundaRosamunda

        Thanks for your reply!
        This is my adapter that I connect to my Arduino Mega board: http://postimg.org/image/ug87tg2w1/
        bout analogWrite vs. digitalWrite, I´ve tried with your code:
        analogWrite(E1, 153);
        digitalWrite(E2, 255);
        And then, as it wasn´t working for me, I´ve tried both cases analogWrite, but still.

        I´ve also tried attaching 3 AA batteries to the board, and a 9v battery aswell, as your example does, and in this case the wheels moved, but barely.

        Again, thanks for your advice and insight!
        Rosamunda

        Reply
        1. Sudar Post author

          Okay let’s debug it one at a time. Try the following combination.

          – Use digitalWrite(pin, HIGH);
          – Use a 9V battery as input to motor

          Also what happens when you connect the motor directly to the batter? How fast is it rotating?

          Reply
  2. Davew

    As with the last tutorial, the has a SERIOUS wiring error, which may be the cause of Rosamnda’s problem.

    The positive and negative of the battery are both connected to the same row of the Breadboard, shorting it out!!

    I highly recommend using only the top row for Positive and bottom row for Negative, keeping the power ‘rails’ distinctly separate.

    Dave

    Reply
  3. Andrew

    Hi, great tutorial! Although I’m slightly confused why you sometimes use analogWrite() for E1/E2 and other times you use digitalWrite()?

    Also, can I update the E1/E2 values during operation like this to alternate fast and slow?

    analogWrite(E1, 153);
    delay(1000);
    analogWrite(E1, 255);
    delay(1000);
    analogWrite(E1, 153);

    Thank you!

    Reply
    1. chrsman63

      Hi
      if the Arduini is away from my pc, I would like to add two buttons (one to increase and the other to decrease) the values and so i can set the set point.
      Probably i have to connect the one pin of the button to the ground and the other to the V+ throw a resistor 10K. So when i press the button the input is pulled down to ground

      Any help to the code?

      Reply
  4. Leelesh

    Can a single arduino Atmega 328 board be used to control 3 different dc motors with different speeds at a time. If possible, how ? Please reply soon.
    If possible, which chips are required and how to connect it with breadboard…?

    Reply
    1. vrushabh Ganvir

      Sir, I m doing project of controlling speed of dc motor using arduino by recognizing sound signal. So please tell me which sensor are used to convert sound signal to arduino recognizable language…..and also tell that how power circuit is to be design…….

      Reply
  5. john

    I am.desperate for help. i built a robot with ardunio my dc motors will not move. im.going crazy. if you can help email.me and ill explain

    Reply
  6. fyp

    is it possible to halt the motors by adding command digitalWrite(I1,LOW)
    and digitalWrite(I2,LOW) instead of (E1,LOW)) & (E2,LOW)?

    Reply
  7. joel

    Love the tutorial but I’m having a problem controlling the speed. I have the wiring all the same and changed the code so i only have one motor. When i analog write between 0-255 I’m hardly hearing a change in speed and it’s not stopping when set to 0? Any thoughts?

    Thanks in advance.

    Here is my code
    #define MotorSpeed 10 // Enable Pin for motor 1
    #define I1 8 // Control pin 1 for motor 1
    #define I2 9 // Control pin 2 for motor 1

    void setup() {

    pinMode(MotorSpeed, OUTPUT);
    pinMode(I1, OUTPUT);
    pinMode(I2, OUTPUT);
    }

    void loop() {

    analogWrite(MotorSpeed, 250);
    digitalWrite(I1, HIGH);
    digitalWrite(I2, LOW);

    delay(2000);

    // change speed

    analogWrite(MotorSpeed, 150);

    delay(2000);

    analogWrite(MotorSpeed, 20);

    delay(2000);

    analogWrite(MotorSpeed, 0);

    delay(2000);
    }

    Reply
  8. Gero

    Thanks for the taking the time to make tutorials like this. Great Job.The previous one worked like a charm. With the code in this one I’m confused. You have only 1 analogWrite after void loop for half speed.
    After that it’s digitalWrite(E2, 255). Same after delay(200). I haven’t tried but I guess for the speeds there should be 4 analogWrite in the code.
    Looking forward to your other tutorials.

    Kind regards,
    Gero

    Reply
    1. Sudar Post author

      Yes, you are correct. The code is wrong. It should use analogWrite instead of digitalWrite.

      I have corrected it now.

      Reply
  9. zeevy

    Hi, i am trying to control the speed of the toy car motor.
    one like this

    but there is no change in speed of the motor always runs at constant speed.
    also motor starts only if the analog value is more than or equal to 130,
    analogWrite(E1, 130) starts the motor and runs at full speed ( no change in speed even for 255)
    any value below 130 motor is not rotating,

    Reply
  10. Ishani

    The tutorial was very helpful. Thank you.
    Do you have library which includes even speed controlling(PWM) command?!

    Regards.
    Ish

    Reply
  11. Amit

    Hi Sudar,
    my project is to generate random noise and apply this generated noise to dc motor such that the duty cycle of the motor is varied in order to vary the speed of the motor with this random noise. could I get any help for this issue ? I am very desperate to achieve this.
    Thanks

    Reply
  12. Haren

    Hello sir, I am using a motor driver module of L293D, the thing is when I connect motors to bridge and turn it on, the wheels rotate very slow even on digitalWrite(high) the speed is very very slow. How can I increase the speed?

    Reply
  13. Pingback: Lab 1 | Introduction to Robotics

  14. Pingback: #9 Controlling the tractor’s motor using L293D H-bridge | Arduino Dad

  15. Cassandra

    Hello!
    For my science fair project I’m creating a robot to cut crust off a sandwich with a turning table and a blade controlled by the Arduino UNO R3, two 12VDC motors w/encoders, a breadboard, male to male jumper wires, a 12V adapter, and an Arduino R3 Motor Shield.
    I’d appreciate some people I could bounce ideas off of since this is my very first robotics project.
    Please help soon as I only have till January 14th to have a complete robot that functions properly, plus research and a way to prove to the judges that I created it on my own.
    I have absolutely no idea on how to program or set up an Arduino, so if you wish to help, please don’t be frustrated by my “not knowing anything”.
    Thank you!

    Reply
  16. PRAKHAR

    IF I WANT TO CONTROL THE SPPED AND DIRECTION OF ARDUINO MANUALLY i.e WHENEVER I WANT I CAN INCREASE THE SPEED AND CHANGE THE DIRECTION. SPEED AND DIRECTION SHOULD NOT BE CHANGED AT REGULAR INTERVALS , LIKE IN THIS YOU HAVE DONE.WHAT SHOULD BE THE CODE FOR THIS WHAT EXTRA DO WE NEED? CAN WE USE POTENTIOMETER FOR THIS CAUSE?

    Reply
  17. M Arslan

    Hellow, nice tutorial
    I am making a robot for my FYP ………. and i want to control the speed of 3 motors at 3 legs of a pipe inspection robot 120 degree a part ……… i have heard that all motors do not run at same speed because of their some inner problem ……… so i will have to design a PID ……….. so i want to ask if this code is enough
    or need some changing?

    Reply
  18. Samer Najia

    I noticed this post as part of a plan to run a simple robot with a rotating platform on its back. Basically, you have 2 motors controlling direction (fwd, back, right and left) using skid steering, like a tank, and a simple pan tilt camera mechanism on its back (2 more motors). Based on what I am seeing, I would need a second L293D and make use of pins 2 through 7 wired up the same way (making use of the remaining 3 PWM pins) and coded the same way and coded much the same way as you have here. Is that correct?

    Reply
      1. Samer Najia

        I am proposing adding 2 more motors and using a second bridge chip. You still have 3 PWM pins on the Arduino, so conceivably I can do this by replicating your connections to the one bridge IC and adding a second L293D.

        Reply
          1. Samer Najia

            Not yet. I also would have to allocate certain letters to the app button or use another app to send commands to the other 2 motors. But, I will.

  19. Hallur

    Hi, thanks for your very good tutorial.
    I have gotten my motors to rotate as it says in the program, but both motors aren’t getting the same input voltage all the time, which makes the AGV NOT drive in a straight line. Any thoughts or solutions what I can do :)?
    thanks in advance 🙂

    Reply
  20. Wyatt

    Hi Sudar,
    I am working on an Arduino RC Car at my school, and have been this circuit. It worked with the DC motors, but we want to use higher voltage motors. We tried the code and circuit that you have. We are using a motor driver, but it recently died on me, and we ordered another. Also, we can run one of our motors at a time on a nine volt, but we don’t want to burn out the Arduino by using too high of a voltage battery. Is there any way to up the voltage of a battery used in the Arduino without destroying it? Any suggestions help.

    Reply
  21. Mohanraja

    Hi Sudar,
    I have computer science background, I don’t know much about electronics, so my questions might be naive.

    In your diagram, you only show Arudino, The board, IC, Motor, battery, but in your youtube video, I see some extra components, (looks like capacitor & resistor), I am not sure why you used that, could you explain?

    Reply
    1. Sudar Post author

      Hello Mohanraja,

      To get the basic circuit to work you don’t need the capacitor or resistors. Just use the components that I have shown in diagram.

      Reply
  22. Sarah

    Hi Sudar,
    Thanks for posting this, I’ve got it all working well. I’d like to introduce a switch so that when the motor shaft turns 360 degrees exactly, the switch is activated and the code starts again from the beginning. I want the motor to do exactly the same movement i.e. slow for 180 and fast for 180 in the exact same position over and over. I’ve added a switch and guessed at some code (below) but, as expected, it isn’t working! I wonder if you could pass an eye over it for me. I’m not sure how to tell the control pins 1 and 2 (I’m only using one motor) to stop altogether, or how to have switch reset the code. 🙁

    I’ll buy you many beers if you ever find yourself in Edinburgh. 🙂

    const int enablePin = 10;
    const int controlPin1 = 8; // Control pin 1 for motor 1
    const int controlPin2 = 9; // Control pin 2 for motor 1
    const int switchPin = 2;
    int switchState = 0;

    void setup() {

    pinMode(enablePin, OUTPUT);
    pinMode(controlPin1, OUTPUT);
    pinMode(controlPin2, OUTPUT);
    pinMode(switchPin, INPUT);
    }

    void loop() {

    analogWrite(enablePin, 50); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 100); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 150); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 200); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 255); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(566);

    analogWrite(enablePin, 200); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 150); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 100); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(30);

    analogWrite(enablePin, 50); // Run in half speed

    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, LOW);

    delay(566);

    switchState = digitalRead(switchPin);

    if (switchState == HIGH) {
    digitalWrite(controlPin1, HIGH);
    digitalWrite(controlPin2, HIGH);
    }
    else {
    digitalWrite(controlPin1, LOW);
    digitalWrite(controlPin2, LOW);
    }
    }

    Reply
  23. Pathfinder

    I have successfully made L293D driver and RC-CAR Controlled through Android but i want to ask one thing.What will happens if i connect L293D pin 1,16,9 direct to Arduino 5v pin.I found this in internet but cant figure out. I think it will not be PWM and cannot controll the speed of motor.

    How about using 2 L293D IC and drive 4 DC motors. Is it possible? Will it overheats?
    Plz suggest.

    Reply
      1. A Deepak Praveen

        sir..will this cose work..its urgent..its an automatic braking system using sensors..braking in the sense..the speed will be reduced to zero

        #define trigPin 13
        #define echoPin 14
        #define e1 10 // Enable Pin for motor 1
        #define t1 8 // Control pin 1 for motor 1
        #define t2 9 // Control pin 2 for motor 1
        #define led 3
        #define led2 5
        #define buzzer 4

        float duration,distance;
        #include

        void setup() {
        Serial.begin(9600);
        pinMode(trigPin,OUTPUT);
        pinMode(echoPin,INPUT);
        pinMode(e1, OUTPUT);
        pinMode(t1, OUTPUT);
        pinMode(t2, OUTPUT);

        }

        void loop() {
        digitalWrite(e1, HIGH);
        digitalWrite(t1, HIGH);
        digitalWrite(t2, LOW);

        digitalWrite(trigPin,LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin,HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin,LOW);

        duration=pulseIn(echoPin,HIGH);
        distance=(duration/2)*0.0343;
        Serial.print(“Distance= “);
        if(distance>=400||distance<=2)
        {
        Serial.println("out of range");
        }
        else if(distance<=100&&distance<=50)

        {
        digitalWrite(led,HIGH);
        delay(1000);
        analogWrite(e1,157);
        digitalWrite(t1,HIGH);
        digitalWrite(t2,LOW);
        delay(500);
        }
        else if(distance=25)
        {
        digitalWrite(buzzer,HIGH);
        delay(100);
        analogWrite(e1,56);
        digitalWrite(t1,HIGH);
        digitalWrite(t2,LOW);
        }
        else if(distance=10)
        {
        digitalWrite(led2,HIGH);
        delay(100);
        analogWrite(e1,0);

        }
        else if(distance=100)
        { digitalWrite(e1, HIGH);
        digitalWrite(t1, HIGH);
        digitalWrite(t2, LOW);

        }

        delay(500);
        }

        Reply
  24. Akhil V

    I made a circuit with L293D, motor and arduino but the speed of one motor is little bit faster than the other
    why it come like this?

    Reply
  25. Larry Berna

    I’m brand new to this world of micro controllers and sketches, but with enough digging, I’ve been able to find answers to most of my questions. One question I haven’t found info for, is my confusion over the PWM control wiring and code for certain motor control breakout boards. Some seem to require 3 input lines from the microcontroller for each DC motor, one line for enable/disable and the other two lines for set the direction (Clockwise/Anti-clockwise) of the motors. I have a DROK® Smart Car DC Dual Motor Driver PWM Module Circuit Board H-bridge MOSFET Driver, from Amazon I would like to use. It only has has 2 input lines per motor. They are PWM1 + DIR1 and PWM2 + DIR2 .
    Then they provide the following info.Control Signal:

    The motor is transferred: DIR = 1 PWM = PWM
    Motor Reverse: DIR = 0 PWM = PWM
    Parking brake: DIR = X PWM = 0
    Motor and power connections
    Then the power of positive POWER, GND for negative one. Two motors were connected MOTOR1, MOTOR2

    Thats all I can find. Can someone help me understand why some need 3, while others only require 2, and what if any changes are needed in a sketch between the two types.

    I need to start, brake, and or Stop, vary the speed, and pattern of two 24V DC motors soon, and I’m taking too long to figure it out!
    Sample code would be fantastic.

    Thanks

    Reply
  26. Okba

    Please, i have a problem with my “L293D” and “DC / Optical Encoder motor”.
    this IC generates a voltage about 3.9 v even without external supply and even in non turning state (enable grounded).
    i think, i don’t need any other component like diodes, because this circuit has his own integrated diodes.
    can u help me ?

    Reply
  27. Suresh

    I’m using LM298N and a 10 rpm dc motor for my egg tray turner working fine, but it requires 60 min interval between clock wise and anti clock wise turns,please help.
    void setup()
    {
    pinMode(7,OUTPUT);
    pinMode(8,OUTPUT);
    pinMode(9, OUTPUT);
    }
    void loop()
    {
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    digitalWrite(9,10);
    delay (4000);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
    delay(4000);
    }

    Reply
    1. Suresh

      Improving my understanding… the solution is…. added delay in between digitalWrite High and low!
      digitalWrite(8, HIGH);
      delay (17000);
      digitalWrite(7, LOW);
      digitalWrite(9,10);
      delay (4000);
      digitalWrite(8, LOW);
      delay (27000);
      digitalWrite(7, HIGH);
      delay(4000);
      thank you all..

      Reply
        1. Khan Mohammad Akash

          hello ppl, I really need some help regarding speed control of a motor using arduino uno. I’m currently doing a project on gesture control robot which uses an accelerometer, 2 arduino unos, rf pair and motor driver module. So far I’ve achieved what I desired. But my next challenge is to control the speed of the robocar using hand gestures via accelerometor. Is there anyone who can help me with this???

          Reply
          1. Okba

            if i understood your question: i used an optical encoder integrated with the motor to see its velocity, from that we can compare it with the desired velocity, and apply the correspondent regulation (PID), but actually i used MBED not ARDUINO.

  28. J Eman

    Thank you so much for this tutorial. I have just learned how to make the Robot go full speed.
    I was wondering if you can program it to go a specific distance -say 5 feet, then turn left etc.
    Could I possibly use a switch button to make it go and stop? If so how? Thanks again.

    Reply
  29. Mo

    Hey

    I have 2 12V DC Gearmotors. I’m trying to let them spin all the way until I hit a stop switch. I have two relays to reverse the movement.
    anyway you recommend any similar written program please, I’m very new to Arduino.

    Thank you

    Reply
  30. Rocky

    Thank you for Controlling DC motor Tutorial, helped me a lot. Still, I am facing some trouble’s using the code and the setup as per yours(ditto). I was able to achieve pwm from 65+ to 255(analogWrite(60)-analogWrite(255)) but unable to achieve pwm of DC motor less than value 65(analogWrite(60) or analogWrite(30). Even, analogWrite(0) doesn’t work, to achieve it i used “analogWrite(300)”. Thanks once again for your effort.

    Reply
  31. jayakarthick

    The bend winding machines are winds the circles in like way applications like transformer, inductors, motor and spreads. The structure of winding machine is articulating by multifaceted nature of circles, square of the material determined nature, versatilities of machine, intervention of head or robotization, creation level and other budgetary concerns.Choke winding

    Reply
  32. A Deepak Praveen

    sir,i need an urgent update regarding this question..its my final year project..will this code work?i have applied the above mentioned principle for automatic braking using sensors

    code-:
    #define trigPin 13
    #define echoPin 14
    #define e1 10 // Enable Pin for motor 1
    #define t1 8 // Control pin 1 for motor 1
    #define t2 9 // Control pin 2 for motor 1
    #define led 3
    #define led2 5
    #define buzzer 4

    float duration,distance;
    #include

    void setup() {
    Serial.begin(9600);
    pinMode(trigPin,OUTPUT);
    pinMode(echoPin,INPUT);
    pinMode(e1, OUTPUT);
    pinMode(t1, OUTPUT);
    pinMode(t2, OUTPUT);

    }

    void loop() {
    digitalWrite(e1, HIGH);
    digitalWrite(t1, HIGH);
    digitalWrite(t2, LOW);

    digitalWrite(trigPin,LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin,HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin,LOW);

    duration=pulseIn(echoPin,HIGH);
    distance=(duration/2)*0.0343;
    Serial.print(“Distance= “);
    if(distance>=400||distance<=2)
    {
    Serial.println("out of range");
    }
    else if(distance<=100&&distance<=50)

    {
    digitalWrite(led,HIGH);
    delay(1000);
    analogWrite(e1,157);
    digitalWrite(t1,HIGH);
    digitalWrite(t2,LOW);
    delay(500);
    }
    else if(distance=25)
    {
    digitalWrite(buzzer,HIGH);
    delay(100);
    analogWrite(e1,56);
    digitalWrite(t1,HIGH);
    digitalWrite(t2,LOW);
    }
    else if(distance=10)
    {
    digitalWrite(led2,HIGH);
    delay(100);
    analogWrite(e1,0);

    }
    else if(distance=100)
    { digitalWrite(e1, HIGH);
    digitalWrite(t1, HIGH);
    digitalWrite(t2, LOW);

    }

    delay(500);
    }

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *