Watch the video tutorial

DC motors are used in many industrial, commercial, and domestic applications. We have DC motors in toys, irrigation pumps, robotics, Drills and in many applications. In The interfacing DC Motor with PIC Microcontroller article, we learnt how to interface a DC motor with PIC Microcontroller using H-bridge circuit constructed from four MOSFET transistors or using a motor controller chip like the L293/L293D.

In real life applications turning a motor ON in clockwise or anticlockwise directions or turning it OFF is not always all that is required. The speed of rotation has to be controlled as well. In this article, we are going to learn how to control the speed of a DC motor using the Pulse Width Modulation of a PIC Microcontroller.

Before you continue with this tutorial, you must read first:

As we have learnt from the interface a DC motor with PIC Microcontroller tutorial, a DC Motor cannot be driven directly from a Microcontroller’s pin. Normally DC Motors require high current and high voltage than a Microcontroller can handle as Microcontrollers usually operates at +5 or +3.3V supply and it I/O pin can provide only up to 25mA current which on most cases is not enough for a motor. Typical small DC Motors require 12V supply and about 300mA current which way beyond what a Microcontroller can handle, we are going to use the L293D motor controller chip which can provide bidirectional drive currents of up to 600-mA at voltages from 4.5 V to 36 V.

By changing the voltage across the DC motor, we could change its speed. We can’t use a variable resistor (potentiometer) to change the voltage across our motor has this has several disadvantages.

  • A motor is not an resistive load, it is an inductive load, 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. So a simple resistor won’t work.
  • The resistor drops excess energy as heat. Thus this will be a huge loss.
  • As the motor requires more current, so resistors with higher power rating are required to drop excess energy.

The best technique is to use the PWM of the PIC microcontroller. The Pulse width modulation (PWM) is a technique of controlling the amount of power delivered to an electronic load by switching ON and OFF a digital signal. This is the simplest technique that can be used to produce analog voltages from a digital one. The fraction of the period for which the signal is ON to the total period is known as the duty cycle. By changing the duty cycle of the signal, the amount of energy transferred to device can be varied.

 Figure 1: L293D Motor Driving Chip Circuit

In this example a DC Motor is interfaced with PIC Microcontroller using L293D Motor Driver as shown on figure 1 above. A potentiometer is connected to Analog channel 0 (AN0) of the PIC. By varying the potentiometer, the PWM duty cycle will be varied as well. By connecting the EN pin to a PWM pin of a PIC Microcontroller, the speed of the motor can be controlled in this way.


We will use The MPLAB® Code Configurator (MCC) plugin to configure our Output pins, PWM and ADC modules. Figure 2 below shows the ADC configuration.

 Figure 2: ADC configuration

Timer 2 uses the oscillator selected in the System section to adjust the Timer 2 period. PWM period of 1.953KHz is selected to give us a CCPR value of 1023 with a duty cycle of 100%. This will enable us to vary the duty cycle from 0% to 100% as the analog reading values are from 0 to 1023, with 1023 representing 5V.

 Figure 3: PWM configuration

#include "mcc_generated_files/mcc.h"

                         Main application
//This function creates seconds delay. The argument specifies the delay time in seconds
void Delay_Seconds(unsigned char z)
    unsigned char x,y;

uint16_t convertedValue = 0;

void main(void) {
    // Initialize the device

    PWM2_LoadDutyValue(511); // Start at 50% speed
    //Turn motor clockwise
    while (1) {
     convertedValue = 0;
      convertedValue = ADC_GetConversionResult();  
       if (convertedValue >= 101) //limit the minimum speed to 10%      
         PWM2_LoadDutyValue(convertedValue); //change duty cycle   
     __delay_ms(10)   ; // create a short delay

You can download the full project files (MPLAB XC8 source code and Proteus Schematic design) below here.  All the files are zipped, you will need to unzip them (Download a free version of the Winzip utility to unzip files).  

Download Mplab Project: DC_Motor_Speed_Control_xc8

Download Proteus Schematic: DC_Motor_Speed_Proteus_Project