Professional Documents
Culture Documents
5 April 2011
jdhernandez_03@yahoo.com
jpmacabasco@gmail.com
Abstract The brushless DC motor is a motor type gaining
popularity because of its advantages over brushed ones. This
document presents a microcontroller-based driver design for a
BLDC motor.
I. INTRODUCTION
rushless Direct Current (BLDC) motors are one of the
motor types rapidly gaining popularity. BLDC motors
are used in industries such as appliances, automotive,
aerospace, consumer, medical, industrial automation
equipment and instrumentation.
As the name implies, BLDC motors do not use brushes
for commutation; instead, they are electronically commutated.
This is accomplished through a driver designed for the
particular operation of a BLDC motor.
The field effect transistors used for the driver are IRF9640
and IRF640; power MOSFETs complementary to each other
(P-channel and N-channel respectively). These MOSFETS are,
in turn, driven by power transistors (TIP30 and TIP31)
through a common-emitter amplifier cascaded with a power
amplifier.
2k
R4
Q3
TIP31
IRF9640
1K
470
10k
R3
R2
Q2
TIP31
Q10
TIP30
R5
d1n4004
D1
Q4
2k
R7
Q7
TIP31
IRF640
1K
Q1
TIP31
Q5
TIP30
R6
d1n4004
D2
Q8
Page 1 of 6
EE197 E-H
5 April 2011
ARB3
V(N1)*V(N2)
V10
N1
1K
OUT
ctr=1 frolloff=100k
U1
2k
R4
Q3
TIP31
IRF9640
1K
R1
N2
V7
470
10k
R3
R2
Q2
TIP31
Q10
TIP30
R5
d1n4004
D1
u
U
250k
250k
R2
R1
R1
250k
V_STAR
1K
V4
ctr=1 frolloff=100k
U2
2k
R7
Q7
TIP31
Q1
TIP31
Q5
TIP30
470
10k
R16
R8
R6
d1n4004
D2
Q8
R3
250k
R3
250k
v _u
R4
3.3k
IRF640
1K
R9
Q4
R5
250k
v _v
R2
10k
v _w
R4
10k
R6
10k
R2
3.3k
u_u
X1
v_u
250k
v_STAR
R1
Q1
Q2N3904
LF353
3.3
V4
7
V3
R4
3.3k
u_v
X2
v_v
250k
v_STAR
R3
Q2
Q2N3904
LF353
3.3
V6
7
V5
R6
3.3k
u_w
X3
v_w
250k
v_STAR
R5
Q3
Q2N3904
LF353
Page 2 of 6
EE197 E-H
5 April 2011
B. Software
The microcontroller used for this motor driver is the
Z8F6421 Flash Microcontroller (packaged in the IRC
slimboard). The language used for programming the
microcontroller is C.
Since the commutation sequence for the BLDC motor is
divided into six, a unique set of codes will correspond to each
stage.Timers are operated in PWM mode to produce the inputs
to the three-phase bridge. Fig. 11 shows the microcontroller
output waveforms for an open loop system (six-step
commutation). This program applies when the system is at its
starting condition. The output coming from the
microcontroller is fed directly to the motor, making it rotate at
low speed.
V. CONCLUSION
The design presented in this paper is able to drive the
BLDC motor with a rating of 48V; from low starting speed to
a certain high speed. The right commutation sequence is
followed by the driver; hence a smoother running of the
BLDC motor.
The driver also implements both open and closed loop
control; open loop is for starting sequences and then
transitions into the closed loop control for the motor. This is
done through correct voltage feedback sensing and use of
comparators. The driver also includes a current limiting
scheme to protect the design from damage due to high
currents caused by loading.
REFERENCES
[1]
[2]
[3]
[4]
Page 3 of 6
EE197 E-H
5 April 2011
APPENDIX
Source Code
#include <sio.h>
#include <stdio.h>
#include <ez8.h>
#define CHANNEL 0x00
#define MODE 0x00
#define VREF 0x00
#define ENABLE 0x80
#define RELOADPWM 144
void delay(void);
void Init_ADC(void);
int Poll_ADC(void);
void InitTimerDelay0(void);
void InitTimerDelay1(void);
void InitTimerDelay2(void);
void InitTimer0(void);
void InitTimer1(void);
void InitTimer2(void);
void stage_1(void);
void stage_2(void);
void stage_3(void);
void stage_4(void);
void stage_5(void);
void stage_6(void);
void sense_current(void);
int RELOAD=24001;
int PWM;
void delay ()
{
char a;
for(a = 0; a < (0x0F); a++);
}
void Init_ADC (void)
{
PBAF = 0x01;
ACTL = (CHANNEL | VREF | MODE);
}
int Poll_ADC (void)
{
ACTL |= ENABLE;
while(ACTL & ENABLE);
return (int)((ADHR<<2)|(ADLR>>6));
}
void InitTimerDelay0(void)
{
T1CTL1 = 0x28; // disable T3,one shot mode, prescaler 32
T1H = 0x00; T1L = 0x01;
// T3 start = 0x0001
T1RH = (RELOAD >> 8);
}
void InitTimer0(void)
{
PAAF |= 0x02;
//T0OUT --> PA1
T0CTL1 = 0x2B;
//PWM mode, prescaler = 32,
low first per period, disable T0
T0H = 0x00;
//T0 start = 0x0001
T0L = 0x01;
T0RH = (RELOADPWM>>8); //T0 reload value
T0RL = (RELOADPWM & 0xFF);
T0PWMH = (PWM>>8);
//T0 PWM value
T0PWML = (PWM & 0xFF);
IRQ0ENH &= ~0x02; //disable timer interrupt T0I
IRQ0ENL &= ~0x02;
IRQ0 &= ~0x02;
//clear timer0 interrupt flag
T0CTL1 |= 0x80;
//enable timer 0
}
void InitTimerDelay1(void)
{
T2CTL1 = 0x28; // disable T3,one shot mode, prescaler 32
T2H = 0x00; T2L = 0x01;
// T3 start = 0x0001
T2RH = (RELOAD >> 8);
T2RL = (RELOAD & 0xFF);
IRQ0ENH &= ~0x80;
// disable timer1 interrupt T3I
IRQ0ENL &= ~0x80;
IRQ0 &= ~0x80;
// clear timer3 interrupt flag
T2CTL1 |= 0x80;
// Enable timer3
}
void InitTimer1(void)
{
PCAF |= 0x02;
T1CTL1 = 0x2B;
T1H = 0x00;
T1L = 0x01;
T1RH = (RELOADPWM>>8); //T1 reload value
T1RL = (RELOADPWM & 0xFF);
T1PWMH = (PWM>>8);
//T1 PWM value
T1PWML = (PWM & 0xFF);
IRQ0ENH &= ~0x40; //disable timer interrupt T1I
IRQ0ENL &= ~0x40;
IRQ0 &= ~0x40;
//clear timer1 interrupt flag
T1CTL1 |= 0x80;
//enable timer 1
}
void InitTimerDelay2(void)
{
T0CTL1 = 0x28; // disable T3,one shot mode, prescaler 32
T0H = 0x00; T0L = 0x01;
// T3 start = 0x0001
T0RH = (RELOAD >> 8);
Page 4 of 6
EE197 E-H
5 April 2011
PCOUT |= 0x04;
InitTimerDelay0();
while(!(IRQ0&0x40))
{
sense_current();
}
IRQ0 &= ~0x40;
return;
}
void InitTimer2(void)
{
PCAF |= 0x80;
T2CTL1 = 0x2B;
T2H = 0x00;
T2L = 0x01;
T2RH = (RELOADPWM>>8); //T2 reload value
T2RL = (RELOADPWM & 0xFF);
T2PWMH = (PWM>>8); //T2 PWM value
T2PWML = (PWM & 0xFF);
IRQ0ENH &= ~0x80; //disable timer interrupt T2I
IRQ0ENL &= ~0x80;
IRQ0 &= ~0x80;
//clear timer2 interrupt flag
T2CTL1 |= 0x80; //enable timer 2
}
void stage_3(void)
{
PAAF &= ~0x02;
PADD &= ~0x02;
PAOUT &= ~0x02;
if(RELOAD<=4001)
{
while(1)
{
if(PAIN&0x10)break;
}
}
void stage_1(void)
{
//cancel alt func of PC7
//set PC7 as output
//set PC7 low
//set PA2 high
//set PC6 high
if(RELOAD>4001)InitTimerDelay1();
while(!(IRQ0&0x80))
{
sense_current();
}
IRQ0 &= ~0x80;
return;
InitTimer0();
if(RELOAD<=4001)
{
while(1)
{
if(PAIN&0x80)break;
}
}
}
void stage_4(void)
{
PAOUT &= ~0x04;
PCOUT |= 0x40;
if(RELOAD>4001)InitTimerDelay0();
while(!(IRQ0&0x40))
{
sense_current();
}
IRQ0 &= ~0x40;
return;
InitTimerDelay1();
while(!(IRQ0&0x80))
{
sense_current();
}
IRQ0 &= ~0x80;
return;
}
void stage_2(void)
{
PCOUT &= ~0xC2;
InitTimer1();
void stage_5(void)
{
Page 5 of 6
EE197 E-H
5 April 2011
InitTimer2();
if(RELOAD<=4001)
{
while(1)
{
if(PAIN&0x40)break;
}
}
if(RELOAD>4001)InitTimerDelay2();
while(!(IRQ0&0x20))
{
sense_current();
}
IRQ0 &= ~0x20;
return;
}
sense_current();
while(1)
{
stage_1();
sense_current();
stage_2();
sense_current();
stage_3();
sense_current();
stage_4();
sense_current();
stage_5();
sense_current();
stage_6();
sense_current();
if(RELOAD>3001)
RELOAD=RELOAD-1000;
}
void stage_6(void)
{
PAOUT |= 0x04;
PCOUT &= ~0x04;
InitTimerDelay2();
while(!(IRQ0&0x20))
{
sense_current();
}
IRQ0 &= ~0x20;
return;
}
void sense_current(void)
{
float volts;
Init_ADC();
volts=(float)(Poll_ADC())/512.0;
PWM=RELOADPWM*(0.7+(0.1*volts));
}
void main(void)
{
PWM=RELOADPWM*0.6;
PADD |= 0xD0;
//set PA4,PA6, and PA7 as input
PDDD |= 0x4C;
//set PD2,PD3, and PD6 as input
PADD &= ~0x06; //set PA1 and PA2 as output
/*
while(1)
{
stage_1();
sense_current();
stage_2();
sense_current();
stage_3();
sense_current();
stage_4();
sense_current();
stage_5();
sense_current();
stage_6();
sense_current();
}
*/
}
*/End of Code*/
Page 6 of 6