Thursday, May 21, 2020

PIC16F887 controls the direction and speed of a brushed DC motor without using PWM module

A DC brushed motor commonly found some application like controlling a wheel speed of a robot, controlling the drilling speed of a numerical control machine etc.

PIC16F887 controls the direction and speed of a brushed DC motor without using PWM module
A brushed DC motor with gear box give a lower speed,
but higher torque.
The analog voltage fed into the motor directly varies the output speed of the rotating motor. The two pole of supply voltage determine the direction of rotating.

To interface with digital control device like a microcontroller, we need a proper driving circuit to protect the controller from being annoyed by the internal induction produce the the motor.

Typically, it is driven by a opto-coupler  or an L293 driver.

Without those two's, we can make our own H-Bridge driver by two complement transistors with some additional components.

In this example, I use three switches to control:
  1. motor to stop
  2. motor to rotate backward
  3. motor to rotate forward
  4. speed down
  5. and speed up
PIC16F887 controls the direction and speed of a brushed DC motor without using PWM module
Schematic diagram
RB0 to RB4 control the direction and speed.
A DC motor is driven by an BJT H-Bridge.
The control signals to the H-Bridge is fed from
RB6 and RB7.

In the program, those five switches generate individual interrupt signal without consuming the program main loop execution time.

The XC8 program listed below:

#include<xc.h>
// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config IESO = ON
#pragma config FCMEN = ON
#pragma config LVP = ON
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
#define _XTAL_FREQ 4000000
int duty=5;
/*Defualt is Stop*/
char controlReg=0;
/*Interrupt service routine*/
void interrupt _ISR(void){
    /*looking for portB interrupt
     on change by checking RBIF*/
    if(RBIF){
        /*Test individual pin*/
        /*Stop*/
        if(RB0==0)  controlReg=0;
        /*Backward*/
        if(RB1==0)  controlReg=1;
        /*Forward*/
        if(RB2==0)  controlReg=2;
        /*Decrease Speed*/
        if(RB3==0)  {
            if(duty>0)
                duty-=1;
        }
        /*Increase Speed*/
        if(RB4==0)  {
            if(duty<10)
                duty+=1;
        }
        RBIF=0;
    }
}
void main(){
    /*clear PortB*/
    PORTB=0x00;
    /*PortB0.4 inputs*/
    TRISB=0b00011111;
    /*disable all analog input of portB*/
    ANSELH=0;
    /*turn on global weak pull up*/
    nRBPU=0;
    /*Turn on all pull up resistor of portB0.4*/
    WPUB=0b00011111;
    /*enable portB interrupt on change
     for some pin pins*/
    IOCB=0b00011111;
    RBIE=1;
    /*enable global interrupt*/
    GIE=1;
    
    while(1){
        switch(controlReg){
            /*Stop the motor*/
            case 0:
                RB6=0;
                RB7=0;
                break;
            /*Forward*/
            case 1:
                RB6=0;
                RB7=1;
                for(int i=0;i<duty;i++)
                    __delay_ms(1);
                RB7=0;
                for(int i=0;i<11-duty;i++)
                    __delay_ms(1);
                break;
            /*Backward*/
            case 2:
                RB7=0;
                RB6=1;
                for(int i=0;i<duty;i++)
                    __delay_ms(1);
                RB6=0;
                for(int i=0;i<11-duty;i++)
                    __delay_ms(1);
                break;
            /*No Matched*/
            default:
                break;
        }
    }
}

A screen shot of the simulating program.

PIC16F887 controls the direction and speed of a brushed DC motor without using PWM module
A screen shot of the simulating program.
The DC motor rotates backward.
A virtual oscilloscope shows the timing
signal fed to the H-Bridge driver.


No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)