Reversing direction of BLDC motor

Status
Not open for further replies.

Cantafford

Member
Hello,

I'm working on a project controlling a bldc motor(just a simulation). I'm having problems when I try to reverse it's direction.

This is the schematic from proteus:



The forward phase sequence that I used to drive the motor CW is:

CB-AB-AC-BC-BA-CA and the motor runs fine in the forward direction. This is the code:

Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"

int HALL;
int HALLvalue[6] = { 0b00000101, 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100 };
int direction;
unsigned int dch;
unsigned int dcl;
// Capture Interrupt Service Routine


void interrupt CheckHallValue()
{



  IC1IF = 0; IC2QEIF = 0; IC3DRIF = 0;
  HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall directionor state
  if(HALL == HALLvalue[0]) { OVDCOND = 0b00100100; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF; }
  else if(HALL == HALLvalue[1]) { OVDCOND = 0b00000110; PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvalue[2]) { OVDCOND = 0b00010010; PDC2H = 0xFF; PDC2L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvalue[3]) { OVDCOND = 0b00011000; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF; } //
  else if(HALL == HALLvalue[4]) { OVDCOND = 0b00001001; PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvalue[5]) { OVDCOND = 0b00100001; PDC2H = 0xFF; PDC2L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
}

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 main()
{
 //OSCCON = 0b01001111; // frequency is 1Mhz
 ConfigureADC();
 SCS1 = 0; // use primary
 SCS0 = 0; // oscillator
 TRISA = 0b11111111; // PORTA is input(CAP's + POT)
 TRISB = 0b11000000;
 TRISC = 0b10000000;
 GIE = 1; // enable global interrupts
 GIEH = 1;
 PEIE = 1;

 // 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

 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


//T5SYNC = 0;
//T5CON = 0b01011001;
//TMR5CS = 0;
 T5CON = 0b00000101;
 //LATB = 0b00100100; // in order to start input capture must see a change



 OVDCOND = 0b00100100; // start sequence
 PDC2H = 0x0F; PDC2L = 0x0F; PDC1H = 0x0F; PDC1L = 0x0F;
 OVDCONS = 0;

 while(1)
 {
     ADON = 1; // keep getting ADC value
 }

}

Notice the starting sequence(that makes the motor run CW):
Code:
 OVDCOND = 0b00100100; // start sequence
 PDC2H = 0x0F; PDC2L = 0x0F; PDC1H = 0x0F; PDC1L = 0x0F; // Phase B to negative, phase C to positive, Phase A not connected
 OVDCONS = 0;

Now I want to reverse the direction of the motor so the phase sequences should be:
BC, BA, CA, CB, AB, AC

So I tried using this starting sequence(to make the motor run CCW):
Code:
 OVDCOND = 0b00011000; // start sequence
 PDC2H = 0x0F; PDC2L = 0x0F; PDC1H = 0x0F; PDC1L = 0x0F; // Phase B to positive, phase C to negative, Phase A not connected
 OVDCONS = 0;

However my motor does not start CCW it still starts CW.
What am I doing wrong? Thanks for reading.
 
Have you checked out the Picmicro MC LV Development board details, it includes code.
**broken link removed**
Max.
Hello. Yes I have. The examples there show pretty much everything other than how to reverse it's rotation(probably because it's too simple).
 
Instead of using the PWM manually ( OVDCONS and D ) see if you can use the automatic registers.. That way the reverse is only a bit change...
 
Instead of using the PWM manually ( OVDCONS and D ) see if you can use the automatic registers.. That way the reverse is only a bit change...
I'm sorry but what do you mean automatic registers? The TRISB port?

I need to use the PCPWM module in my project.
 
Sorry ... As the OVD registers are "override" I thought you were operating manually..

You will need a "run" buffer where the values loaded into the OVDCOND reg.. can be reversed

Apparently you can just "complement" the hall input!!
 
Right so my initial sequence was: CB - AB - AC - BC - BA - CA for int HALLvalue[6] = { 0b00000101, 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100 };
Now I have done my sequence as: BC - BA - CA - CB - AB - AC for the new buffer: int HALLvaluer[6] = { 0b00000010, 0b00000110, 0b00000100, 0b00000101, 0b00000001, 0b00000011 };

The motor still starts and runs in the CW direction as before...

This is the new code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"

int HALL;
int HALLvalue[6] = { 0b00000101, 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100 };
int HALLvaluer[6] = { 0b00000010, 0b00000110, 0b00000100, 0b00000101, 0b00000001, 0b00000011 };
int direction;
unsigned int dch;
unsigned int dcl;
// Capture Interrupt Service Routine


void interrupt CheckHallValue()
{



  IC1IF = 0; IC2QEIF = 0; IC3DRIF = 0;
  HALL = (PORTA >> 2) & 0x7; // read the capture pins to get hall directionor state
  if(HALL == HALLvaluer[0]) { OVDCOND = 0b00011000; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF; }
  else if(HALL == HALLvaluer[1]) { OVDCOND = 0b00001001; PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvaluer[2]) { OVDCOND = 0b00100001; PDC2H = 0xFF; PDC2L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvaluer[3]) { OVDCOND = 0b00100100; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF; } //
  else if(HALL == HALLvaluer[4]) { OVDCOND = 0b00000110; PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvaluer[5]) { OVDCOND = 0b00010010; PDC2H = 0xFF; PDC2L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
}

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 main()
{
 //OSCCON = 0b01001111; // frequency is 1Mhz
 ConfigureADC();
 SCS1 = 0; // use primary
 SCS0 = 0; // oscillator
 TRISA = 0b11111111; // PORTA is input(CAP's + POT)
 TRISB = 0b11000000;
 TRISC = 0b10000000;
 GIE = 1; // enable global interrupts
 GIEH = 1;
 PEIE = 1;

 // 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

 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


//T5SYNC = 0;
//T5CON = 0b01011001;
//TMR5CS = 0;
 T5CON = 0b00000101;
 //LATB = 0b00100100; // in order to start input capture must see a change



 OVDCOND = 0b00011000; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
 OVDCONS = 0;

 while(1)
 {
     ADON = 1; // keep getting ADC value
 }

}
 
Use the old code and stick this code

HALL = 6- ((PORTA >> 2) & 0x7);
 
You mean like this:

Code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"

int HALL;
int HALLvalue[6] = { 0b00000101, 0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100 };
int direction;
unsigned int dch;
unsigned int dcl;
// Capture Interrupt Service Routine


void interrupt CheckHallValue()
{



  IC1IF = 0; IC2QEIF = 0; IC3DRIF = 0;
  HALL = 6- ((PORTA >> 2) & 0x7);
  if(HALL == HALLvalue[0]) { OVDCOND = 0b00100100; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF; }
  else if(HALL == HALLvalue[1]) { OVDCOND = 0b00000110; PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvalue[2]) { OVDCOND = 0b00010010; PDC2H = 0xFF; PDC2L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvalue[3]) { OVDCOND = 0b00011000; PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF; } //
  else if(HALL == HALLvalue[4]) { OVDCOND = 0b00001001; PDC1H = 0xFF; PDC1L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
  else if(HALL == HALLvalue[5]) { OVDCOND = 0b00100001; PDC2H = 0xFF; PDC2L = 0xFF; PDC0H = 0xFF; PDC0L = 0xFF; } //
}

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 main()
{
 //OSCCON = 0b01001111; // frequency is 1Mhz
 ConfigureADC();
 SCS1 = 0; // use primary
 SCS0 = 0; // oscillator
 TRISA = 0b11111111; // PORTA is input(CAP's + POT)
 TRISB = 0b11000000;
 TRISC = 0b10000000;
 GIE = 1; // enable global interrupts
 GIEH = 1;
 PEIE = 1;

 // 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

 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


//T5SYNC = 0;
//T5CON = 0b01011001;
//TMR5CS = 0;
 T5CON = 0b00000101;
 //LATB = 0b00100100; // in order to start input capture must see a change



 OVDCOND = 0b00100100; // start sequence
 PDC2H = 0x0F; PDC2L = 0x0F; PDC1H = 0x0F; PDC1L = 0x0F;
 OVDCONS = 0;

 while(1)
 {
     ADON = 1; // keep getting ADC value
 }

}

Still the same problem
 
If I get a chance I look tonight... I get it to reverse easy by swapping two phases, but that's not the best solution..
 
You cannot swap two phases on a BLDC motor with hall commutation without swapping the respective Hall device.
It sounds as though you do not have the commutation correctly aligned with the respective poles.
Max.
 

Attachments

  • commutation.pdf
    136.6 KB · Views: 265
Best I got was the original statement..

HALL = 7 -(PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state

This moves forward 1 step then backwards..... I'm getting a strange feeling that there should be two more steps..
 
Best I got was the original statement..

HALL = 7 -(PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state

This moves forward 1 step then backwards..... I'm getting a strange feeling that there should be two more steps..
Can you please post the code that does this? Mine just goes CW for me won't go CCW at all. Maybe I can start from there and make it work.
 
Okay!!
C:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"

int HALL;
int HALLvalue[6] = { 0b00000101,0b00000001, 0b00000011, 0b00000010, 0b00000110, 0b00000100};
unsigned long duty;
unsigned int dch;
unsigned int dcl;
// Capture Interrupt Service Routine

void interrupt CheckHallValue()
{
  if(IC1IF==1)
  {
   duty = (int) ADRESH *256 + ADRESL;
  duty<<=4;
   dch = 64; // set the
     dcl = duty; // duty cycle with the pot
  IC1IF = 0;
  ADON = 0;
  }
  IC2QEIF = 0; IC3DRIF = 0;
  HALL = 7 -(PORTA >> 2) & 0x7; // read the capture pins to get hall sensor state
 
  if(HALL == HALLvalue[0]) {OVDCOND = 0b100100; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; OVDCONS = 0b00000000;}
  else if(HALL == HALLvalue[1]) { OVDCOND = 0b00000110; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; } //
  else if(HALL == HALLvalue[2]) { OVDCOND = 0b00010010; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; } //
  else if(HALL == HALLvalue[3]) { OVDCOND = 0b00011000; PDC2H = dch; PDC2L = dcl; PDC1H = dch; PDC1L = dcl; } //
  else if(HALL == HALLvalue[4]) { OVDCOND = 0b00001001; PDC1H = dch; PDC1L = dcl; PDC0H = dch; PDC0L = dcl; } //
  else if(HALL == HALLvalue[5]) { OVDCOND = 0b00100001; PDC2H = dch; PDC2L = dcl; PDC0H = dch; PDC0L = dcl; } //
}

void ConfigureADC()
{
  ADCON0 = 0b00100000; // continuous loop mode, single channel mode
  ADCON1 = 0;
  ADCON2 = 0b10001000; // right justified, 2TAD, conversion clock: Fosc/2
  ADCON3 = 0b00000100;  // input capture 1 starts the a/d sequence!!(check here the first two bits)
  GASEL1 = 0; // select AN0
  GASEL0 = 0;
  ANSEL0 = 0b00000001;
  ADON = 1; // start ADC
}

void main()
{
 //OSCCON = 0b01001111; // frequency is 1Mhz
 ConfigureADC();
 SCS1 = 0;
 SCS0 = 0;
 TRISA = 0b11111111; // PORTA is input(CAP's + POT)
 TRISB = 0b11000000;
 GIE = 1; // enable global interrupts
 GIEH = 1;
 PEIE = 1;

 // 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

 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


//T5SYNC = 0;
//T5CON = 0b01011001;
//TMR5CS = 0;
 T5CON = 0b00000101;
 //LATB = 0b00100100; // in order to start input capture must see a change

 OVDCOND = 0b00100100; // start(needs a change on input capture)
 PDC2H = 0xFF; PDC2L = 0xFF; PDC1H = 0xFF; PDC1L = 0xFF;
 OVDCONS = 0b00000000;

 while(1)
 {
  ADON = 1;
 }

}
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…