Sensorless BLDC motor controller

This is my first post on this forum. I've read the general guidance, but please tell me if I missed anything. The company I'm at does not know how to help me, so I figured I'd try my chances here.

I am a student and currently doing my internship, so my experience is limited. I'm trying to make a motor controller for a 6 pole 3 phase brushless DC motor. I'm using an arduino mega 2560. The model that's being used for test-purposes is the DYS BE4715 330KV. It starts turning somewhat nicely at about 1.5A and 10V at NO load. However, after looking up the specs online I found out that it's supposed to turn at an rpm of 6000 at 14.8V and 0.9A at no load.

The problem I'm struggling with is the fact that the high side and low side FET get turned on at the same time. However, the motor still turns during the start process but stops right at the end of it. At which point it just makes sounds and is not turning. I suspect that this might be because I'm not getting any clear BEMF signals during the start process and none after. In my attached code it's clear that I don't turn them on at the same time. Neither the low nor the high input of the mosfet drivers are inverting. The components and values I used for my circuit are all visible on the attached schematic. I apologize if the quality is not to your liking.

My goal is to get the BLDC to turn using the output of 3 comparators, each connected to the virtual neutral and a phase. They're meant to measure/sense the Back EMF and send a signal to the arduino, which then sends the right signals to the Fet driver, etc.

I've already rebuilt the circuit about 4 to 5 times and checked for mistakes. The Fet drivers have already been replaced, but the result is still the same. All components have been checked for any faults as well.

Please find the schematic in the attachments.

This code has been through a lot of adjustments, so there's a good chance that there's an unused variable or anything of the like. I'll give it a good clean when my project starts showing signs of success.

If any information is missing, please tell me. If possible, I'll add it as a response to this post ASAP.

// Sensorless brushless DC (BLDC) motor control

/* 
 *  
 *  A HIGH = PIN 10        A LOW = PIN 7
 *  B HIGH = PIN 11        B LOW = PIN 8
 *  C HIGH = PIN 12        C LOW = PIN 9
 *  
*/
#define PWM_MAX_DUTY      255
#define PWM_MIN_DUTY      50
#define PWM_START_DUTY    100

byte bldc_step = 0, motor_speed, pin_state;
unsigned int i;
void setup() {
  DDRH  |= 0x70;          // Configure pins 7, 8, 9 as outputs
  PORTH  = 0x00;
  DDRB  |= 0x70;          // Configure pins 10, 11, 12 as outputs
  PORTB  = 0x00;
  // Timer1 module setting: set clock source to clkI/O / 1 (no prescaling)
  TCCR1A = 0;
  TCCR1B = 0x01;
  // Timer2 module setting: set clock source to clkI/O / 1 (no prescaling)
  TCCR2A = 0;
  TCCR2B = 0x01;
  
  pinMode(SPEED_UP,   INPUT_PULLUP);
  pinMode(SPEED_DOWN, INPUT_PULLUP);

  PCICR = EIMSK = 0;
}

ISR(PCINT0_vect){
  // BEMF debounce
//  for (byte i = 0; i < 20; i++){
//    compreading = PINB & PCMSK0;
//    if(!(compreading & pin_state)){
//      i -= 1;
//    }
//  }
  bldc_move();
  bldc_step++;
  bldc_step %= 6;
}

void bldc_move(){
    switch(bldc_step){
    case 0:
      AH_BL();
      BEMF_C_RISING();
      break;
    case 1:
      AH_CL();
      BEMF_B_FALLING();
      break;
    case 2:
      BH_CL();
      BEMF_A_RISING();
      break;
    case 3:
      BH_AL();
      BEMF_C_FALLING();
      break;
    case 4:
      CH_AL();
      BEMF_B_RISING();
      break;
    case 5:
      CH_BL();
      BEMF_A_FALLING();
      break;
  }
}
 
void loop() {
  motor_speed = PWM_START_DUTY;
  SET_PWM_DUTY(200);
  i = 10000;
  // Motor start
  while(i > 2000) {
    delayMicroseconds(i);
    bldc_move();
    bldc_step++;
    bldc_step %= 6;
    i = i - 20;
  }
  
  PCICR = 1;    // Enable comparator interrupts
  
  while(1) {
  }
}

void BEMF_A_RISING(){
  PCMSK0    = 0x08;       // Enable pin 50 (PCINT3) interrupt, disable others
  pin_state = 0x08;
}
void BEMF_A_FALLING(){
  PCMSK0    = 0x08;       // Enable pin 50 (PCINT3) interrupt, disable others
  pin_state = 0;
}
void BEMF_B_RISING(){
  PCMSK0    = 0x04;       // Enable pin 51 (PCINT2) interrupt, disable others
  pin_state = 0x04;
}
void BEMF_B_FALLING(){
  PCMSK0    = 0x04;       // Enable pin 51 (PCINT2) interrupt, disable others
  pin_state = 0;
}
void BEMF_C_RISING(){
  PCMSK0    = 0x02;       // Enable pin 52 (PCINT1) interrupt, disable others
  pin_state = 0x02;
}
void BEMF_C_FALLING(){
  PCMSK0    = 0x02;       // Enable pin 52 (PCINT1) interrupt, disable others
  pin_state = 0;
}
 
void AH_BL(){     // A high B low
  PORTB  =  0b00010000;
  PORTH &= ~0b01010000;
  PORTH |=  0b00100000;
  TCCR1A =  0;
  TCCR2A =  0b10000011;
  
}
void AH_CL(){     // A high C low
  PORTB  =  0b00010000;
  PORTH &= ~0b00110000;
  PORTH |=  0b01000000;
  TCCR1A =  0;
  TCCR2A =  0b10000011;
}
void BH_CL(){     // B high C low
  PORTB  =  0b00100000;
  PORTH &= ~0b00110000;
  PORTH |=  0b01000000;
  TCCR2A =  0;
  TCCR1A =  0b10000001;
}
void BH_AL(){     // B high A low
  PORTB  =  0b00100000;
  PORTH &= ~0b01100000;
  PORTH |=  0b00010000;
  TCCR2A =  0;
  TCCR1A =  0b10000001;
}
void CH_AL(){     // C high A low
  PORTB  =  0b01000000;
  PORTH &= ~0b01100000;
  PORTH |=  0b00010000;
  TCCR2A =  0;
  TCCR1A =  0b00100001;
}
void CH_BL(){     // C high B low
  PORTB  =  0b01000000;
  PORTH &= ~0b01010000;
  PORTH |=  0b00100000;
  TCCR2A =  0;
  TCCR1A =  0b00100001;
}
 
void SET_PWM_DUTY(byte duty){
  if(duty < PWM_MIN_DUTY)
    duty  = PWM_MIN_DUTY;
  if(duty > PWM_MAX_DUTY)
    duty  = PWM_MAX_DUTY;
  OCR2A  = duty;                   // Set pin 10  PWM duty cycle
  OCR1A  = duty;                   // Set pin 11  PWM duty cycle
  OCR1B  = duty;                   // Set pin 12  PWM duty cycle
}

1 Like

EDIT: Turns out only phase A has both fets on at the same time, while the others don't.