Cantafford
Member
Hello,
I'm trying to run a BLDC motor clockwise in proteus simulator. I wrote a code in MPLAB for PIC18F2431. My motor is running fine in the clockwise direction but I just can't get it to spin in the counter clockwise direction. I wrote this code:
These are the routines that are important:
In the above CW and CCW routines I send different sequences to the phases of the BLDC motor. Yet the motor spins in the exact same direction...I used a virtual oscilloscope on it's 3 phases and I see same sequence of voltages for both CW and CCW code routines...but how is that possible the motor to see exactly same sequence on it's phases if I'm sending different commands? Please help me identify this issue if possible(yes I know I have a different thread on this but I have made some modifications in the code and I need this kinda urgent so any help would be appreciated. Thank you!)
This is how the schematic looks like: I made an inverter with 2 L293D drivers.
I'm trying to run a BLDC motor clockwise in proteus simulator. I wrote a code in MPLAB for PIC18F2431. My motor is running fine in the clockwise direction but I just can't get it to spin in the counter clockwise direction. I wrote this 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 HALLvaluereverse[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;
TRISCbits.RC7 = 0;
LATCbits.LATC7 = 0; // led initially off
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 == HALLvaluereverse[0]) { OVDCOND = 0x06; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluereverse[1]) { OVDCOND = 0x12; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluereverse[2]) { OVDCOND = 0x18; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; }
else if(HALL == HALLvaluereverse[3]) { OVDCOND = 0x09; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluereverse[4]) { OVDCOND = 0x21; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; }
else if(HALL == HALLvaluereverse[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
}
}
These are the routines that are important:
Code:
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; }
In the above CW and CCW routines I send different sequences to the phases of the BLDC motor. Yet the motor spins in the exact same direction...I used a virtual oscilloscope on it's 3 phases and I see same sequence of voltages for both CW and CCW code routines...but how is that possible the motor to see exactly same sequence on it's phases if I'm sending different commands? Please help me identify this issue if possible(yes I know I have a different thread on this but I have made some modifications in the code and I need this kinda urgent so any help would be appreciated. Thank you!)
This is how the schematic looks like: I made an inverter with 2 L293D drivers.
