DC Motor Speed Control With PIC16F628A

DC motor speed control with PIC16F628A microcontroller simulation.
DC Motor Speed Control Simulation

In this project, we will control the speed and direction of a DC motor using the PIC16F628A microcontroller. We will write the software in MPLAB IDE with the XC8 language that will sent PWM signal to L293D to control the motor. Finally, we will simulate it through the Proteus software.

You can get more information about the PWM signal from the link above. Now let’s examine the L293D motor driver.

L293D Motor Driver

L293D motor driver pinout diagram.
L293D Pinout

With this motor drive, we can supply 600mA (max. 1.2A) and the voltage between 4.5V-36V. We will give 12V voltage to the input, assuming that we will run 12V motors in this project. The control is as in the table below.

L293D Functions

0XXFree Running
Motor Stop
0XXFree Running
Motor Stop
100Fast Motor Stop100Fast Motor Stop
111Fast Motor Stop111Fast Motor Stop
110Turn Left110Turn Left
101Turn Right101Turn Right

As shown in the table, the control of the L293D motor driver is similar to that of the L298N.

If we want to drive 2 DC motors, one L293D is enough. However, if you will use 4 DC motors in your project, you will need 2 L293D.

Note: You must connect the GND of the L293D circuit and all other grounds to each other. Otherwise, the circuit will not work.

In this project, we describe 1 DC motor control because of microcontroller has 1 PWM module. We have set the required control frequency for the motor to 490Hz. This frequency is close to the ideal frequency for the DC motor. You can see the motor speed control code in the XC8 language and PWM calculation with explanations in the below.

Let’s do the calculations before going to code;

PWM calculation for PIC16F628A microcontroller.
PWM Calculation

As we cannot produce a 490 Hz PWM signal, we produced a 488 Hz signal. We used a 4 MHz internal oscillator to generate 488 Hz and 9-bit resolution PWM signal.

DC Motor Speed Control XC8 Code

 * File:   main.c
 * Author: Trionium
 * Created on 13.01.2020, 21:21

// PIC16F628A Configuration Bit Settings

#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 4000000

void main(void) {
    PR2 = 0x7F; // Set PWM frequency to 488Hz
    CCP1CONbits.CCP1M = 0b1100; // Set PWM Mode
    T2CONbits.T2CKPS = 0b11; // Set Timer2 prescale to 1:16
    T2CONbits.TMR2ON = 1; // TMR2 On
    TRISBbits.TRISB3 = 0; // RB3 Output
    TRISAbits.TRISA0 = 1; // RA0 Input
    TRISAbits.TRISA1 = 1; // RA1 Input
    CMCONbits.CM = 0b111; // Digital input
    int16_t speed = 0;
    // For direction input
    TRISAbits.TRISA2 = 1;
    // For direction control output
    TRISAbits.TRISA3 = 0;
    TRISAbits.TRISA4 = 0;
    while(1) {
        // Speed up
        if(PORTAbits.RA0) {
        // Speed down
        if(PORTAbits.RA1) {
        // Turn left
        if(PORTAbits.RA2) {
            PORTAbits.RA3 = 1;
            PORTAbits.RA4 = 0;
        // Turn right
        else {
            PORTAbits.RA3 = 0;
            PORTAbits.RA4 = 1;
        // PWM resolution is 9bit, therfore
        // Speed must be between 0 and 511
        if(speed > 511)
            speed = 511;
        else if(speed < 0)
            speed = 0;
        // Set Duty Cycle
        CCPR1L = speed >> 2;
        CCP1CONbits.CCP1X = (speed & 2) >> 1;
        CCP1CONbits.CCP1Y = speed & 1;

When the SPEED UP button is pressed, the speed of the motor will increase up to 100% and when the SPEED DOWN button is pressed, the speed of the motor will decrease by 0%. The direction of rotation of the motor can be controlled with the Direction Control switch.

Thus, we made a simple DC motor control circuit with a PIC microcontroller. We hope it has been useful, stay healthy.

Share This Tutorial
0 0 votes
Article Rating
Notify of
Inline Feedbacks
View all comments