Tuesday, July 19, 2016

CD-ROM BLDC motor controller using PIC18F4550 and L293D


BLDC Motor controller using PIC18F4550 and L293D
BLDC motor ESC using PIC18F4550 and L293D 
In the following topic URL we've seen how to control BLDC motor speed and direction of rotation using PIC18F4550 microcontroller and 3-phase bridge circuit:
CD-ROM Spindle motor (BLDC) control with PIC18F4550 microcontroller
This topic shows how to make the same controller using L293D motor driver instead of the 3-phase bridge circuit.
The 3 phase bridge is more complicated and expansive and while the L293D motor driver chip is a small, cheap and saves time.
In this project we need two L293D chips because the BLDC motor is a three phase motor, and at any time two windings energized while the third one floating.
The L293D has 4 inputs and 4 outputs with 2 enable pins, each enable pin controls 2 outputs as shown below:
L293D Motor driver chip pinout BLDC motor
Complete circuit schematic is shown below:
Interfacing sensored BLDC motor with PIC18F4550 microcontroller and L293D circuit CCS PIC C
In the circuit there are 3 buttons connected to RB0, RB1 and RB2. The buttons connected to RB1 and RB2 are used to start the BLDC motor and the other button is a stop button.
The BLDC motor speed is controlled using a potentiometer connected to AN0 channel.
There are 3 AND gates (HEF4081BP) in the circuit, these gates are used to get a 3 PWM signals from the original one which comes from RC2 pin using CCP1 module.
HEF4081BP has 4 independent 2-input AND gates, three of them are used. This IC needs a supply voltage of +5V between pins 7 (GND) and 14 (VCC).
PIC18F4550 microcontroller internal oscillator is used (8MHz).
BLDC Motor control using PIC18F4550 and L293D CCS PIC C code:

// Sensored BLDC motor controller using PIC18F4550 and L293D CCS C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

#include <18F4550.h>
#device ADC = 10
#fuses NOMCLR INTRC_IO
#use delay(clock = 8000000)
#use fast_io(B)
#use fast_io(D)

int8 hall, Direction = 0;
int8 MoveTable1[8] = {0, 50, 11, 56, 44, 14, 35, 0};
int8 MoveTable2[8] = {0, 35, 14, 44, 56, 11, 50, 0};
#INT_RB                                       // RB port interrupt on change
void rb_isr(void){
  hall = (input_b() >> 4) & 7;
  if(Direction == 1)
    output_d(MoveTable1[hall]);
  else
    output_d(MoveTable2[hall]);
  clear_interrupt(INT_RB);
}
void main(){
  setup_oscillator(OSC_8MHZ);                 // Set internal oscillator to 8MHz
  setup_adc_ports(AN0);                       // Configure RA0 (AN0) pin as analog
  output_b(0);                                // PORTB initial state
  set_tris_b(0xF7);                           // TRISB configurartion
  port_b_pullups(TRUE);                       // Enable PORTB internal pull-ups
  output_d(0);                                // PORTD initial state
  set_tris_d(0);                              // Configure PORTD pins as outputs
  setup_adc(ADC_CLOCK_DIV_8);                 // Set ADC conversion time to 64Tosc
  set_adc_channel(0);                         // Select channel 0 input
  setup_timer_2(T2_DIV_BY_1, 199, 1);         // Timer2 configuration for PWM
  setup_ccp1(CCP_OFF);
  enable_interrupts(GLOBAL);                  // Enable global interrupts
  while(TRUE){
    if(!input(PIN_B1)){                       // If RB1 button pressed
      if(Direction == 0){
        Direction = 1;
        setup_ccp1(CCP_PWM);                  // Configure CCP1 as a PWM
        clear_interrupt(INT_RB);              // Clear RB IOC flag bit
        enable_interrupts(INT_RB);            // Enable PORTB IOC
        hall = (input_b() >> 4) & 7;
        output_d(MoveTable1[hall]);
      }
    }
    if(!input(PIN_B2)){                       // If RB1 button pressed
      if(Direction == 0){
        Direction = 2;
        setup_ccp1(CCP_PWM);                  // Configure CCP1 as a PWM
        clear_interrupt(INT_RB);              // Clear RB IOC flag bit
        enable_interrupts(INT_RB);            // Enable PORTB IOC
        hall = (input_b() >> 4) & 7;
        output_d(MoveTable2[hall]);
      }
    }
    while(Direction != 0){
     set_pwm1_duty(read_adc());
     if(!input(PIN_B0)){
       disable_interrupts(INT_RB);             // Disable PORTB IOC
       output_d(0);
       setup_ccp1(CCP_OFF);                    // CCP1 OFF
       Direction = 0;
     }
   }
  }
}

BLDC Motor controller using PIC18F4550 and L293D video:
The following video shows project hardware circuit.


References:
Microchip: Sensored BLDC Motor Control Using dsPIC30F2010 (AN957).
Microchip: Brushless DC Motor Control Made Easy (AN857).
L293D Datasheet.