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:

Interface a DC motor with PIC Microcontroller

Pulse Width Modulation (PWM) with PIC Microcontroller

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.

MikroC Code

In this example, a potentiometer connected to Analog channel 0 will be used to change the speed of rotation of the motor as shown on figure 1 above.

The motor will rotate in clockwise direction in this example.

 * Project name:  DC Motor Speed Control
 * Copyright:
     (c) www.studentcompanion.net, 2017.
 * Test configuration:
     MCU:             PIC18F45K22
     Oscillator:      HS-PLL, 8.00000 MHz

//variables declaration

 unsigned int adc_rd;
 long current_duty;

void main() {
 ANSELC = 0;         // Configure PORTC as digital I/O
 ANSELB = 0;        // Configure PORTB as digital I/O

  TRISA0_bit = 1;    //Configure AN0 (RA0) as input
  TRISC = 0;         //PORTC pins are outputs
  TRISB = 0;         //PORTB pins are outputs
  PWM1_Init(1000);      // Initialize PWM1 module at 1KHz
  PWM1_Start();        // start PWM1
  ADC_Init();         // Initialize ADC

  LATB =  0x01;      //Turn the motor Clockwise

  while (1) {         // endless loop

  adc_rd = ADC_Read(0);     //Read Analog value from Analog channel 0
  //convert voltage level to duty cycle 0-->255
  current_duty = (long) adc_rd * 255;
  current_duty =  current_duty/1023;
  PWM1_Set_Duty(current_duty);  //change duty cycle

  Delay_ms(5);                  // slow down change pace a little

You can download the full project files (mikroC Pro for PIC 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 mikroC Project: DC Motor Speed Control_MikroC project

Download Proteus Schematic: DC Motor Speed Control_Proteus Project