DC Motor Speed Control using PWM with PIC Microcontroller

I already posted about Interfacing DC Motor with PIC Microcontroller. In our robotics applications we may have to control the speed of the DC Motor. In this tutorial we will see how to control the speed of a DC Motor using Pulse Width Modulation (PWM). By using PWM we can easily control the average power delivered to a load and by thus we can easily control the speed of the DC Motor.

You may think that a variable resistor in series with a DC Motor can control its speed. There are three reasons for “Resistor is not a good choice for controlling the speed of a DC Motor”.

  • The main problem is that the motor is a varying electrical load so a resistor can’t do this task. It needs more power during start up than in running state. It draws more current also when a mechanical load is applied to motor shaft.
  • The resistor drops excess energy as heat. Thus it is not good for a battery powered device.
  • We all know that motor requires more current, so resistors with higher power rating are required to drop excess energy.

PWM can be easily generated using the inbuilt CCP module of a PIC Microcontroller. CCP stands for Capture/Compare/PWM. CCP modules are available with a number of PIC Microcontrollers. Most of them have more than one CCP  module. MikroC Pro for PIC Microcontroller provides built in library routines for PWM which makes our task very simple. Please refer the following articles.

In this example project DC Motor is interfaced with PIC Microcontroller using L293D Motor Driver. Two Push Button switches are provided to control the speed of the motor. Here we are using 12V DC Motor and average DC value delivered to motor can be varied by varying the duty ratio of the PWM. The average DC Voltage of 0% duty cycle is 0V, 25% duty cycle is 3V, 50% duty cycle is 6V, 75% duty cycle is 9V and for 100% duty cycle 12V.

Circuit Diagram – DC Motor Speed Control

DC Motor Speed Control using PWM with PIC Microcontroller

DC Motor Speed Control using PWM with PIC Microcontroller

Note: VDD and VSS of the pic microcontroller is not shown in the circuit diagram. VDD should be connected to +5V and VSS to GND.

Two push button switches are connected to 1st and 2nd pins of PORTD which is used to control the duty ratio of the generated PWM. Pressing the UP switch increases the duty cycle, which increases the motor speed while pressing the DOWN switch decreases the duty cycle, which decreases the motor speed. Here we use CCP1 module of PIC 16F877A to generate PWM and it is given to the enable pin of L293D. The direction of rotation of motor can be control using the 1st and 2nd pins of PORTB.

MikroC Code

void main()
  short duty  = 0; //initial value for duty

  TRISD = 0xFF; //PORTD as input
  TRISC = 0x00; //PORTC as output
  TRISB = 0x00; //PORTB as output
  PORTB = 0x02; //Run motor in anticlock wise

  PWM1_Init(1000);  //Initialize PWM1
  PWM1_Start();  //start PWM1
  PWM1_Set_Duty(duty); //Set current duty for PWM1

  while (1)        // endless loop
     if (!RD0_bit && duty<250) //if button on RD0 pressed      
        duty = duty + 10;  //increment current_duty     
        PWM1_Set_Duty(duty);  //Change the duty cycle      
     if (!RD1_bit && duty >0) //button on RD1 pressed
       duty = duty - 10;  //decrement duty
    Delay_ms(10);      // slow down change pace a little

The parameter of PWM1_Set_Duty() is duty ratio which ranges from 0 to 255, ie 0 means 0% duty cycle and 255 means 100% duty cycle.

I think the program is self explanatory, so if you have doubts please comment below.

You can download the hex file, MikroC source code, Proteus files etc here…

DC Motor Speed Control with PIC Microcontroller

You may also like...

  • jeffin91

    HI…ur posts are very useful and informative…i was wondering if you could provide me with the details of doing this same task with a pic18f452.

  • http://www.electrosome.com/ Ligo George

    You can use the above program for pic 18f452 with some modifications. As shown above TRIS registers are used to set the direction of a pin while to write a data to a output pin LAT register is used. But for reading a port PORT register is used as above………. You can use the above functions in mikroc for 18f452

  • jeffin91

    thank u so much..is there a fuzzy logic concept in the above code or can we incorporate the fuzzy logic concept into the above code.?

  • http://www.electrosome.com/ Ligo George

    Yes, it may be said like that as the motor is not fully ON or OFF …. …. You can incorporate fuzzy logic concept in to above code, for eg: speed control of FAN according to the room temperature…

  • Nishantk

    Hi..I had a doubt that rather than using switch to control duty cycle is it possible for us to write a code and accordingly generate pwm?

  • http://www.electrosome.com/ Ligo George

    Yes, of course…………. You can generate appropriate pwm for your applications.. This is just a tutorial for getting started with PWM

  • mylz muzik

    can i use this setup to drive brushless outrunner motors ?
    i have tries using ESC with very little luck
    thank you !

  • http://www.electrosome.com/ Ligo George

    Brushless DC Motors uses a 3 phase AC motor that has connected to a Electronic Speed Controller (ESC) circuit…. so there is no use of DC PWM controller in this case……..

  • mylz muzik

    am trying 2 run it with pwm from pic16f887 but it keeps implying that somrthing is wrong with my signal ,.. so am thinking of substituting the ESC with a motor driver IC .. good idea or not ?

  • http://www.electrosome.com/ Ligo George

    Use a 3 phase brushless motor instead of dc brushless motor…. and control its speed using 3 pwm…………

  • pervez karim

    can you please help me to right the above program in assembly language plzzz

  • http://www.electrosome.com/ Ligo George

    Sorry, I haven’t yet used pic assembly language ..

  • Dante

    i have a problem here. I’m using PIC 18F4550. Is it requires a totally different code?

  • http://www.electrosome.com/ Ligo George

    Nop, since we are using MikroC compiler, there are only some modifications… To set direction of io pins use TRIS register, to read data from io pins use PORT register but for write data to io pins use LAT register…
    In the above program change PORT register to LAT, it will work..

  • metwally shoier

    I am using a pic18f452 with a crystal 4Mhz …. Do i have to change the constant 1000 ???

  • http://www.electrosome.com/ Ligo George

    Nop, change the Clock Frequency in the project settings..

  • Fathin Amira

    Can i use crystal 20mhz and 18pf capacitor? And what should i change in the coding?

  • http://www.electrosome.com/ Ligo George

    You need to change only the crystal frequency in the project settings…

  • http://www.facebook.com/muhammadarslan.khurshidbhatti Muhammad Arslan Khurshid Bhatt

    I want to generate continuous pwm on the basis of voltage. Can it possible that one pin generate pwm continuously while my program observing voltage continuously with out disturbing PWM. IN this program you add 10 in duty cycle how much duty it increase.Thanks

  • http://www.electrosome.com/ Ligo George

    Yes you can generate continuous pwm by changing dutycycle…
    The parameter of PWM1_Set_Duty() is duty ratio which ranges from 0 to 255, ie 0 means 0% duty cycle and 255 means 100% duty cycle.

  • Tolga

    Hey great documents, thanks. Sir, I need to do a pic16f84a project that controls dc motor gonna use mosfet, i need to speed it up and slow it down with a pwm technique can you help me with circuit and assm code if you have some time?

  • http://www.electrosome.com/ Ligo George

    Sorry, I haven’t yet used pic assembly language…

  • bunny

    can we i use this program for pic 18f4520 to control the speed of 12v dc motor??

  • layan

    what about 3ph induction motor i wanna connect potentiometer with pic to controlled motor speed i need pic code of this case any one help me

  • http://www.electrosome.com/ Ligo George

    For the speed control of 3 phase induction motor you need 3 pwm channel.. but the above pic has only two.. but you can generate a Software generated pwm using interrupts of CCP module……
    You need to vary the frequency of the pwm to control the speed of three phase induction motor..

  • http://www.electrosome.com/ Ligo George

    Yes.. of course… .. Note that for 18f series.. output register is LAT… not PORT… PORT is used for reading data……You need to change the output registers of above program as LAT… no other changes in program..

  • Srishti Srivastava

    what’s the purpose of using the crystal?

  • http://www.electrosome.com/ Ligo George

    If you need to connect only one 7 segment, simply connect its 7 inputs to any of the output pins of the microcontroller. If you need to connect more than one 7 segments… try this article. It might help you..

  • Srishti Srivastava

    okay, thanks! And what about the coding part ? If i want to display the speed in rpm

  • http://www.electrosome.com/ Ligo George

    To display speed in rpm you need more than one seven segment.. You can use above link and Hex() covert a number to its 7 segment code…
    The speed of the dc motor can be find using an IR transmitter and Receiver, by counting the no. of times IR beam is cutting in a minute…….

  • Srishti Srivastava

    Thank you so much!

  • Xolani M Charlie

    does a atmega16 microcontroller have a CCP?

  • http://www.electrosome.com/ Ligo George

    Why don’t you refer its datasheet??
    There are 4 PWM channels in Atmega16… there is no CCP…

  • Kinetic Energy

    My input is form the dtmf decoder, can i use this code to control my DC motors?

  • http://www.electrosome.com/ Ligo George

    Sure,,, give the output of DTMF decoder to input of PIC and write the required code to control the motor..

  • rajatbhise



  • http://www.electrosome.com/ Ligo George

    It can be used in robotics applications…….

  • kite

    PWM to control stepper motor is it possible

  • http://www.electrosome.com/ Ligo George

    To adjust the speed of stepper motor, you should control the delay between stepping..

  • derr

    two questions

    1) Can this setup receive an analog signal to the microcontroller? does it have ADC? Basically what type of micro controller is used to monitor an analog signal in real time and compute the motor speed based on a function of the incoming analog signal? (or would a DSP be more suited for this)

    2)is it always necessary to have a motor driver between the microcontroller and the motor? Or are do there exist microcontrollers that can directly control the motor speed?

  • http://www.electrosome.com/ Ligo George

    The above microcontroller have ADC…. I think the above microcontroller is enough for you… since I think you are dealing with slowly varying analog signals…………..
    A driver is required.. to drive the motor..

  • rahul

    is the above method suitable to control the speed of a 36v 360 watt dc motor?

  • http://www.electrosome.com/ Ligo George

    You can use the PWM Method,… but can’t use L293D…. ..
    You should use appropriate drivers…

  • RINS

    the above circuit not working, i tried many times, pls help me….

  • http://www.electrosome.com/ Ligo George

    Hello, it will work..
    Did you tried it in hardware..??
    If it is not working in hardware.. try connecting the EN1 pin to VDD and check whether the motor is working……..
    if it works.. then reconnect it to ccp pin… then try reducing the pwm frequency…

  • jan

    How to use this with a PIC32, what ports to use ?

  • http://www.electrosome.com/ Ligo George

    Please refer the datasheet of your microcontroller..

  • Mout Hunter

    I have one project about line follower. Can you give me some information about it???

  • http://www.electrosome.com/ Ligo George

    You can use PWM to control the speed of motors… depending upon the curves..

  • Mout Hunter

    But i don’t know how to write code with Mikro Basic to apply to my line follower.

  • http://www.electrosome.com/ Ligo George

    Use google .. There are a lot of tutorials over internet..

  • fifi

    is it possible to run a 3V DC motor directly from the microcontroller? or do i need a motor driver for it to turn?

  • Safaa Monther

    hello iwant to control dc motor and feed back to micro controller by using vco ineed the program in micro c

  • rinku

    hi i am doing project on people counting system and home automation so as number of people increase temperature increase it is necessary and if yes so i can control the speed by pwm ? i am mot using temperature sensor. thanks

  • sachin poly

    sir ,
    i want to make a temperature controlled fan using pic168f77a i connected a temperature sensor in to pic’s adc input port A0.. and tried with your above program with slight modification.. but it shows error . it shows we want to initialise the identifier TRISD,C,B.. and lot of other errors..
    can you please help me..?

  • Gaurees

    Hi Mate, I want to use this for a robotic arm, I am planing to use 2 DC motors for 2 joints (Each motor for each joints). I decided to use L293 motor driver full bridge IC. My question is should I use two L293 IC for 2 motors? both joints moves up and down wards. not side movement.
    I am designing my own PCB board on Altium designer. so plzz give me clear full circuit the with PIC16f877A and L193 for 2 motors. Thank you and have a nice day

  • Nguyễn Đình Việt

    This wish is reversible reversible how dear?, You can edit the code to help me please? Thank you

  • myra

    how to do if i want to control the speed by using 5 switches
    means that i have 5 speed. (just like fan)

  • Cristian

    xc8.exe –pass1 –errformat=”Error at file %%f line %%l column %%c: (%%n) %%s” –warnformat=”Warning at file %%f line %%l column %%c: (%%n) %%s” –msgformat=”Message at file %%f line %%l column %%c: (%%n) %%s” -G –chip=16F877A -O”main.p1″ “../main.c”

    Microchip MPLAB XC8 C Compiler (Free Mode) V1.31

    Copyright (C) 2014 Microchip Technology Inc.

    License type: Node Configuration

    Warning at file line column : (1273) Omniscient Code Generation not available in Free mode

    Warning at file ../main.c line 15 column 1: (361) function declared implicit int

    Warning at file ../main.c line 16 column 1: (361) function declared implicit int

    (908) exit status = 1

    make: *** [main.p1] Error 1

    Warning at file ../main.c line 17 column 1: (361) function declared implicit int

    Error at file ../main.c line 21 column 18: (195) expression syntax

    Error at file ../main.c line 23 column 13: (194) “)” expected

    Error at file ../main.c line 27 column 18: (195) expression syntax

    Error at file ../main.c line 29 column 13: (194) “)” expected

    Error at file ../main.c line 33 column 10: (194) “)” expected

    Error at file ../main.c line 34 column 1: (285) no identifier in declaration

    Warning at file ../main.c line 34 column 1: (374) missing basic type; int assumed

    Error at file ../main.c line 34 column 1: (314) “;” expected

    Error at file ../main.c line 35 column 1: (285) no identifier in declaration

    Warning at file ../main.c line 35 column 1: (374) missing basic type; int assumed

    Error at file ../main.c line 35 column 1: (314) “;” expected

    Error code 2

  • Cristian

    were is my mistake???

  • http://www.electrosome.com/ Ligo George

    The above code is written for MikroC PRO Compiler..

  • azam khan

    hii , can i use a 12v/ 2 amp dc motor here

  • http://www.electrosome.com/ Ligo George

    No, L293D is able to handle only 600mA continuous current and 1.2A Peak current.
    You can use power transistors.