无传感器 BLDC 电机控制 BEMF 部分

Posted

技术标签:

【中文标题】无传感器 BLDC 电机控制 BEMF 部分【英文标题】:Sensorless BLDC motor control BEMF section 【发布时间】:2020-01-04 09:32:36 【问题描述】:

我正在尝试制作无传感器 bldc 电机控制驱动器。我找到了一个 Arduino 代码,我想将其转换为 ARM Stm32。但我完全不明白 ISR 中断部分会发生什么。谁能尽快解释一下?为什么使用bldc_step&1,而当减少i

byte bldc_step = 0, motor_speed, pin_state;
 
void setup()

  DDRD  |= 0xE0;  // configure pins 5, 6 and 7 as outputs
  PORTD  = 0x00;
  DDRB  |= 0x0E;  // configure pins 9, 10 and 11 as outputs
  PORTB  = 0x31;

  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);

 
// pin change interrupt 2 (PCINT2) ISR
ISR (PCINT2_vect)

  if( (PIND & PCMSK2) != pin_state )
    return;
  // BEMF debounce
  for(byte i = 0; i < 20; i++)
  
    if(bldc_step & 1)
      if(PIND & PCMSK2)     i -= 1;
    
    else 
      if(!(PIND & PCMSK2))  i -= 1;
    
  
 
  bldc_move();
  bldc_step++;
  bldc_step %= 6;

 
// BLDC motor commutation function
void bldc_move()

  switch(bldc_step)
  
    case 0:
      AH_BL();
      BEMF_C_FALLING();
      break;
    case 1:
      AH_CL();
      BEMF_B_RISING();
      break;
    case 2:
      BH_CL();
      BEMF_A_FALLING();
      break;
    case 3:
      BH_AL();
      BEMF_C_RISING();
      break;
    case 4:
      CH_AL();
      BEMF_B_FALLING();
      break;
    case 5:
      CH_BL();
      BEMF_A_RISING();
  

  
  PCICR  = 4;  // enable pin change interrupt for pins PCINT23..16 (Arduino 0 to 7)
  
 
 
void BEMF_A_RISING()

  PCMSK2 = 0x04;    // enable Arduino pin 2 (PCINT18) interrupt, others are disabled
  pin_state = 0x04;

void BEMF_A_FALLING()

  PCMSK2 = 0x04;    // enable Arduino pin 2 (PCINT18) interrupt, others are disabled
  pin_state = 0;

void BEMF_B_RISING()

  PCMSK2 = 0x08;    // enable Arduino pin 3 (PCINT19) interrupt, others are disabled
  pin_state = 0x08;

void BEMF_B_FALLING()

  PCMSK2 = 0x08;    // enable Arduino pin 3 (PCINT19) interrupt, others are disabled
  pin_state = 0;

void BEMF_C_RISING()

  PCMSK2 = 0x10;    // enable Arduino pin 4 (PCINT20) interrupt, others are disabled
  pin_state = 0x10;

void BEMF_C_FALLING()

  PCMSK2 = 0x10;    // enable Arduino pin 4 (PCINT20) interrupt, others are disabled
  pin_state = 0;

 
void AH_BL()

  PORTD &= ~0xA0;
  PORTD |=  0x40;
  TCCR1A =  0;      // turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  TCCR2A =  0x81;   //

void AH_CL()

  PORTD &= ~0xC0;
  PORTD |=  0x20;
  TCCR1A =  0;      // turn pin 11 (OC2A) PWM ON (pin 9 & pin 10 OFF)
  TCCR2A =  0x81;   //

void BH_CL()

  PORTD &= ~0xC0;
  PORTD |=  0x20;
  TCCR2A =  0;       // turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  TCCR1A =  0x21;    //

void BH_AL()

  PORTD &= ~0x60;
  PORTD |=  0x80;
  TCCR2A =  0;      // turn pin 10 (OC1B) PWM ON (pin 9 & pin 11 OFF)
  TCCR1A =  0x21;   //

void CH_AL()

  PORTD &= ~0x60;
  PORTD |=  0x80;
  TCCR2A =  0;       // turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  TCCR1A =  0x81;    //

void CH_BL()

  PORTD &= ~0xA0;
  PORTD |=  0x40;
  TCCR2A =  0;       // turn pin 9 (OC1A) PWM ON (pin 10 & pin 11 OFF)
  TCCR1A =  0x81;    //

 
void SET_PWM_DUTY(byte duty)

  OCR1A  = duty;  // set pin 9  PWM duty cycle
  OCR1B  = duty;  // set pin 10 PWM duty cycle
  OCR2A  = duty;  // set pin 11 PWM duty cycle

【问题讨论】:

【参考方案1】:

电机的速度取决于施加的电压 D.V,其中 D 是占空比。

Fm = D.VP.KV.poles/120 = D.Vp/M
Tm = M/(D.Vp)

bemf 检测后的理想延迟为 30 度:

delay = Tm/12 = M/(12.D.Vp) = M'/(D.Vp)     : M'=M/12

M' – 过零检测后 30° 延迟的伏特*秒。 比较器 ISR 仅在导通时间内向上计数。 PWM 脉冲越宽,计数越快。 循环最大时间:

m = N.ticks.Cycles

周期是每条指令的滴答声。 循环仅在 ton 上升或下降 BEMF 期间计数(向上)到 N。计数的 PWM 脉冲将是:

Pc = m/ton  or  Pc = m/(D.Ts)

预计循环时间为:

dt = Pc.Ts = m.Ts/(D.Ts) = m/D

所需的延迟和循环的时间必须相等:delay = dt

M'/(Vp.D) = m/D or m = M'/Vp

此方法也称为“反电动势积分法”。 M' = D.Vp.Tm' 是从 ZCP 到下一个换向的积分 bemf 电压。你可以阅读更多 在这里简要介绍一下: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3231115/

调整 N 和 PWM 频率 (Fs=1/Ts) 可以在 bemf 检测后为您提供几乎完美的 30 度延迟。电机的极数和 Kv 应该是已知的。未经调整,此代码不适用于任何电机。 干杯

【讨论】:

【参考方案2】:

此代码用于消除反电磁力 (BEMF) 信号,等效代码在 https://github.com/esden/open-bldc-mk/blob/master/bldc.c 中

ISR(ANA_COMP_vect)
unsigned char i;

/* debounce the bemf signal */
for(i=0; i<BEMF_DEBOUNCE_COUNT; i++)
    if(bldc_phase & 1)
        if(BEMF_L) i -= BEMF_DEBOUNCE_DEC;
    else
        if(BEMF_H) i -= BEMF_DEBOUNCE_DEC;
    

对于去抖动以及为什么这样做,请参阅https://en.wikipedia.org/wiki/Switch#Contact_bounce

这里实现的确切算法是用垂直计数器去抖动开关,参见https://www.compuphase.com/electronics/debouncing.htm - 用垂直计数器去抖动开关

bldc_step &amp; 1 中,&amp; 运算符是按位与,即二进制中的45 &amp; 35 = 3300101101 &amp; 00100011 = 00100001 bldc_step 是一个字节,与1 进行按位与运算等效于测试bldc_step 的最后一位是否已设置。使用PIND &amp; PCMSK2 检查PIND 是高还是低

这段代码和去抖动循环的其余部分实现了https://www.compuphase.com/electronics/debouncing.htm中描述的垂直计数器

【讨论】:

以上是关于无传感器 BLDC 电机控制 BEMF 部分的主要内容,如果未能解决你的问题,请参考以下文章

有刷电机及无刷直流电机(BLDC)

有刷电机及无刷直流电机(BLDC)

STC15W408AS无感BLDC电机驱动程序

STC单片机驱动BLDC无刷直流电机(无HALL)官方示例

matlab simulink PMSM BLDC电机模糊pid转速控制

基于无速度传感器的永磁同步电机矢量控制研究