DC Motor speed and direction control with PIC MCU | MPLAB Projects

This project shows how to control a DC motor speed and direction of rotation using PIC16F887 microcontroller and L293D motor driver chip.
The L293D quadruple half-H drivers chip allows us to drive 2 motors in both directions. With one PWM signal from the PIC16F887 and two control signals we can easily control the speed as well as the direction of rotation of one DC motor. (PWM: Pulse Width Modulation).

The compiler used in this project is Microchip MPLAB XC8 (MPLAB X IDE with MPLAB XC8 compiler).

Components Required:

  • PIC16F887 microcontroller  —->  datasheet
  • L293D driver                     —->  datasheet
  • 12V DC motor
  • 10k ohm potentiometer
  • Push button
  • 5V source
  • 12V source
  • Breadboard
  • Jumper wires

DC Motor speed and direction control with PIC16F887 MCU and L293D circuit:
Project circuit schematic diagram is shown below.

DC motor control circuit with PIC16F887 and L293D

(All grounded terminals are connected together)

The circuit is supplied with two sources, one with voltage of 5V which supplies the PIC16F887 microcontroller and the L293D driver IC (VCC1), and the second source with voltage of 12V which supplies the L293D chip (VCC2) and therefore the DC motor. The DC motor nominal voltage is 12V.

The speed of the DC motor (both directions) is controlled with the 10k potentiometer which is connected to AN0 pin of the PIC16F887 (#2) and the direction of rotation is controlled with the push button which is connected to RB1 pin (#34). If the button is pressed the motor will change its direction of rotation directly.

The L293D driver has 2 VCCs: VCC1 is +5V and VCC2 is +12V (same as motor nominal voltage). IN1 and IN2 pins are the control pins where:

IN1 IN2 Function
L H Direction 1
H L Direction 2
L L Fast motor stop
H H Fast motor stop

The PIC16F887 generates a PWM signal on pin RC2 (#17) using CCP1 module (CCP: Capture/Compare/PWM), this pin is connected to EN1,2 pin of the L293D chip. IN1 and IN2 pins are connected to RD0 and RD1 respectively (they can be reversed).

In this project the PIC16F887 microcontroller uses its internal oscillator @ 8 MHz, MCLR pin is configured as an input pin.

DC Motor speed and direction control with PIC16F887 MCU and L293D code:
The C code below is for MPLAB XC8 compiler, it was tested with version 2.00 installed on MPLAB X IDE version 5.05.

PIC16F887 Timer2 module is configured to generate a PWM signal with frequency of 1.953 KHz and resolution of 10 bits (prescaler = 4 and preload value = 255).
PWM frequency and resolution can be calculated using the functions below (Fosc = 8 MHz):
PWM_freqency = Fosc / { [ (PR2) + 1 ] * 4 * ( TMR2 Prescaler Value ) } = 1.953 KHz
Resolution = log[ 4(PR2 + 1) ] / log(2) = 10 bits

Code functions:
uint16_t read_adc(): this function reads (and returns) data from ADC module registers ADRESH and ADRESL, the 2 registers contain digital value corresponds to analog voltage.

void set_pwm_duty(uint16_t pwm_duty): simply this function sets the PWM duty cycle.

__bit debounce (): this function is for button debounce.

The microcontroller used in this example is PIC16F887, configuration words are:


  • In-Circuit Debugger disabled
  • Low voltage programming disabled
  • Fail-Safe Clock Monitor enabled
  • Internal/External Switchover mode enabled
  • Brown-out Reset (BOR) disabled
  • Data memory code protection disabled
  • Program memory code protection disabled
  • RE3/MCLR pin function is digital input, MCLR internally tied to VDD
  • Power-up Timer (PWRT) disabled
  • Watchdog Timer (WDT) disabled
  • INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN
  • Flash Program Memory Self Write disabled
  • Brown-out Reset set to 4.0V

Full MPLAB XC8 code:

The following video shows a simple Proteus simulation of the project:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.