• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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.
 

Cantafford

Member
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.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
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!!
 

Cantafford

Member
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
 }

}
 

Cantafford

Member
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 :(
 

MaxHeadRoom78

Well-Known Member
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

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
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..
 

Cantafford

Member
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.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
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.

EE World Online Articles

Loading
Top