Cantafford
Member
Hello,
I'm trying to control a BLDC with a PIC18F2431. I simulated the application and I created an inverter using 2 L293D drivers. Like this:
The motor is supposed to start running after I select a direction from buttons on RB6, RB7 then by pressing the start button. It's speed is also dependend on the position of that potentiometer connected to ADC0. It works just fine like this.
However that would not be usefull if I had a BLDC with high current rating since the L293D can handle only around 7 amps.
So I wanted to make an inverter of MOSFETS instead. I have created this arrangments in proteus using 2N6660 mosfets. Like this:
However when I simulate this the motor acts very weird: the motor starts running with a very low speed as long as the START button is kept pressed. If the button is released the motor decelerates to 0. The program worked fine with the inverter created with 2 L293D's so i suppose the code is good and I made some error in making that arangment of mosfets. Please help me identify the issue so the application will simulate fine. Thank you.
Here is the code:
I'm trying to control a BLDC with a PIC18F2431. I simulated the application and I created an inverter using 2 L293D drivers. Like this:

The motor is supposed to start running after I select a direction from buttons on RB6, RB7 then by pressing the start button. It's speed is also dependend on the position of that potentiometer connected to ADC0. It works just fine like this.
However that would not be usefull if I had a BLDC with high current rating since the L293D can handle only around 7 amps.
So I wanted to make an inverter of MOSFETS instead. I have created this arrangments in proteus using 2N6660 mosfets. Like this:

However when I simulate this the motor acts very weird: the motor starts running with a very low speed as long as the START button is kept pressed. If the button is released the motor decelerates to 0. The program worked fine with the inverter created with 2 L293D's so i suppose the code is good and I made some error in making that arangment of mosfets. Please help me identify the issue so the application will simulate fine. Thank you.
Here is the code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
#include <plib/delays.h>
#include <plib/xlcd.h>
#define FCY 6250000
int HALL;
int HALLvalue[6] = { 0b00000001, 0b00000101, 0b00000100, 0b00000110, 0b00000010, 0b00000011 };
int HALLvaluer[6] = { 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100, 0b00000101 };
unsigned int dch;
unsigned int dcl;
float timercount;
float speed, actualspeed;
unsigned char buf[20];
int dir;
float RPMconstant = 60 * 6250000 / 256;
int long timer5;
// Capture Interrupt Service Routine
void init_XLCD(void); //Initialize LCD display
void DelayFor18TCY( void ); //18 cycles delay
void DelayPORXLCD (void); // Delay of 15ms
void DelayXLCD (void); // Delay of 5ms
void CW();
void CCW();
void ConfigureADC();
void CalculateSpeed();
void SetSpeed();
void DisplaySpeed();
void ConfigureInterrupts();
void ConfigureInputCapture();
void ConfigurePCPWM();
void ConfigureTIMER5();
int SelectDir();
void Start();
void interrupt CheckHallValue()
{
if(IC1IF==1)
{
CalculateSpeed();
SetSpeed();
}
IC2QEIF = 0; IC3DRIF = 0;
if(dir==1) // right sequence
{
HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state
CW();
}
if(dir==2) // right sequence
{
HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state
CCW();
}
}
void main()
{
ConfigureADC();
SCS1 = 0; // use primary
SCS0 = 0; // oscillator
TRISA = 0b11111111; // PORTA is input(CAP's + POT)
TRISB = 0b11000000;
ConfigureInterrupts();
ConfigureInputCapture();
ConfigurePCPWM();
ConfigureTIMER5();
init_XLCD(); //Call the Initialize LCD display function
//OVDCOND = 0b00100100; // start(needs a change on input capture)
//PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
OVDCONS = 0;
while(1)
{
dir = SelectDir();
Start();
ADON = 1;
DisplaySpeed();
}
}
void init_XLCD(void) //Initialize LCD display
{
OpenXLCD(FOUR_BIT&LINES_5X7); //configure LCD in 4-bit Data Interface mode
//and 5x7 characters, multiple line display
while(BusyXLCD()); //Check if the LCD controller is not busy
//before writing some commands
WriteCmdXLCD(0x06); //Move cursor right, don't shift display
WriteCmdXLCD(0x0C); //Turn display on without cursor
}
void DelayFor18TCY( void ) //18 cycles delay
{
Delay10TCYx(20);
}
void DelayPORXLCD (void) //Delay of 15ms
{
Delay1KTCYx(30);
}
void DelayXLCD (void) //Delay of 5ms
{
Delay1KTCYx(10);
}
void CW()
{
if(HALL == HALLvalue[0]) { OVDCOND = 0x09; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
else if(HALL == HALLvalue[1]) { OVDCOND = 0x18; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvalue[2]) { OVDCOND = 0x12; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvalue[3]) { OVDCOND = 0x06; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
else if(HALL == HALLvalue[4]) { OVDCOND = 0x24; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvalue[5]) { OVDCOND = 0x21; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
}
void CCW()
{
if(HALL == HALLvaluer[0]) { OVDCOND = 0x06; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluer[1]) { OVDCOND = 0x12; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluer[2]) { OVDCOND = 0x18; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
else if(HALL == HALLvaluer[3]) { OVDCOND = 0x09; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluer[4]) { OVDCOND = 0x21; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluer[5]) { OVDCOND = 0x24; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
}
void SetSpeed()
{
while(GODONE); // wait untill conversion is over
dch = ADRESH >> 2; // set the
dcl = (ADRESL<<6) | ((ADRESL>>2) & 0x00) ; // duty cycle with the pot
IC1IF = 0;
ADON = 0;
}
void CalculateSpeed()
{
timercount = TMR5; // get
speed = ( 6250000 / (timercount*8*6) ) * 60 / 8.5; // the
TMR5 = 0;
if(dch==0 && dcl==0) {speed = 0; LATCbits.LATC7 = 0; }
}
void DisplaySpeed()
{
if(dir==0)
{
WriteCmdXLCD(0x01); // Clear screen
putrsXLCD("Select direction");
while(PORTBbits.RB6==1 && PORTBbits.RB7==1);
WriteCmdXLCD(0x01); // Clear screen
}
if(dir==1)
{
putrsXLCD("Dir: CW"); // Display digital on first line
SetDDRamAddr(0x40); // Shift cursor to beginning of second line
putrsXLCD("Speed: "); //Display on the screen
sprintf(buf, "%g", speed ); //Convert speed float value to string
putsXLCD(buf); //Display the speed on the screen
putrsXLCD(" "); // Space
putrsXLCD("RPM"); // DIsplay RPM
WriteCmdXLCD(0x02); //Home position on LCD
}
if(dir==2)
{
putrsXLCD("Dir: CCW"); // Display digital on first line
SetDDRamAddr(0x40); // Shift cursor to beginning of second line
putrsXLCD("Speed: "); //Display on the screen
sprintf(buf, "%g", speed ); //Convert speed float value to string
putsXLCD(buf); //Display the speed on the screen
putrsXLCD(" "); // Space
putrsXLCD("RPM"); // DIsplay RPM
WriteCmdXLCD(0x02); //Home position on LCD
}
}
void ConfigureADC()
{
ADCON0 = 0b00000000; // single shot mode, single channel mode
VCFG1 = 0; // VDD and VSS as ref
VCFG0 = 0;
ADCON2 = 0b00001000; // left justified, 2TAD, conversion clock: Fosc/2
ADCON3 = 0b11000100; // input capture 1 starts the a/d sequence!!(check here the first two bits)
GASEL1 = 0; // select AN0
GASEL0 = 0;
ANSEL0 = 0b00000001;
}
void ConfigureInterrupts()
{
GIE = 1; // enable global interrupts
GIEH = 1;
PEIE = 1;
}
void ConfigureInputCapture()
{
// Initialize the Input Capture Module
CAP1CON = 0b00000000; // disable input capture 1 module
CAP1CON = 0b00001000; // enable input capture 1 module; interrupt on every state change
CAP2CON = 0b00000000; // disable input capture 2 module
CAP2CON = 0b00001000; // enable input capture 2 module; interrupt on every state change
CAP3CON = 0b00000000; // disable input capture 3 module
CAP3CON = 0b00001000; // enable input capture 3 module; interrupt on every state change
// Enable Capture Interrupt and configure TMR5
IC1IE = 1; // enable IC1 interrupt
IC1IP = 1; // IC1 interrupt on high priority
IC1IF = 0; // clear IC1 interrupt status flag
IC2QEIE = 1; // enable IC2 interrupt
IC2QEIP = 1; // IC2 interrupt on high priority
IC2QEIF = 0; // clear IC2 interrupt status flag
IC3DRIE = 1; // enable IC3 interrupt
IC3DRIP = 1; // IC3 interrupt on high priority
IC3DRIF = 0; // clear IC3 interrupt status flag
}
void ConfigurePCPWM()
{
PTCON0 = 0b00000000; // 1:1 postscale, 1:1 prescale, PWM in free-running mode
PTCON1 = 0b10000000; // pwm time base is on, the time base counts up
PWMCON0 = 0b01001111; // pwm0-5 configured as pwm output in independent mode
SEVOPS3 = 0; // 1:1 postscale
SEVOPS2 = 0;
SEVOPS1 = 0;
SEVOPS0 = 0;
OSYNC = 1; //Output overrides via the OVDCON register are synchronized to the PWM time base(NOT SURE HERE)
PTPERH = 0x0F; // frequency is 1.5Khz
PTPERL = 0xFF; // 0xFF here
}
void ConfigureTIMER5()
{
T5CON = 0b00011001; // tmr 5 prescaler = 1:8
PR5H = 0xFF;
PR5L = 0xFF;
}
int SelectDir()
{
int answer;
if(PORTBbits.RB6==1 && PORTBbits.RB7==1) answer = 0; // left
if(PORTBbits.RB6==0 && PORTBbits.RB7==1) answer = 1; // right
if(PORTBbits.RB6==1 && PORTBbits.RB7==0) answer = 2; // left
return answer;
}
void Start()
{
if(dir==1)
if(PORTAbits.RA1==0) // start right
{
OVDCOND = 0x09;
PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
LATCbits.LATC7 = 1; // turn on LED
}
if(dir==2)
if(PORTAbits.RA1==0) // start left
{
OVDCOND = 0x06;
PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF;
LATCbits.LATC7 = 1; // turn on LED
}
}