无刷直流电动机基本转动原理等内容请参考《基于霍尔传感器的无刷直流电机控制原理》、《基于反电动势过零检测法的无刷直流电机控制原理》与《以GD32F30x为例定时器相关功能详解》,BLDC基本原理及基础知识本篇不再赘述。
直流无刷电机由于定子绕组的反电动势与电机的转速成正比,所以电机在静止时反电动势为零或低速时反电动势很小,此时无法根据反电动势信号确定转子磁极的位置。因此,反电动势法需要采用特殊启动技术,从静止开始加速,直至转速足够大。通过反电势能检测到过零时,再切换至直流无刷电机运行状态。这个过程称为“三段式”启动,主要包括转子预定位、加速和运行状态切换三个阶段。这样既可以使电机转向可控,又可以保证电机达到一定转速后再进行切换,保证了启动的可靠性。
下面对“三段式”启动技术进行详细的分析。
1、电机转子预定位
若要保证直流无刷电机能够正常启动,首先要确定转子在静止时的位置。
在小型轻载条件下,对于具有梯形反电势波形的直流无刷电机来说,一般采用磁制动转子定位方式。系统启动时,任意给定一组触发脉冲,在气隙中形成一个幅值恒定、方向不变的磁通。只要保证其幅值足够大,那么这一磁通就能在一定时间内将电机转子强行定位在这个方向上。
在应用中,可以在任意一组绕组上通电一定时间,其中预定位的PWM占空比和预定位时间的长短设定值可由具体电机特性和负载决定,在实际应用中调试而得。通常为了保险起见,会定位两次相邻的位置,防止转子刚好处于临界位置。
在预定位成功后,转子在启动前可达到预定的位置,为电机启动做好准备。
void motor_lacation_cfg_1()
{
//W+ U-
/* channel0 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCXN_ENABLE);
/* channel1 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCXN_DISABLE);
/* channel2 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCX_ENABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCXN_DISABLE);
}
void motor_lacation_cfg_2()
{
//U+ V-
/* channel0 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCX_ENABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCXN_DISABLE);
// /* channel1 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCXN_ENABLE);
/* channel2 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCXN_DISABLE);
}
void motor_lacation_cfg_3()
{
//W+ V-
/* channel0 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCXN_DISABLE);
/* channel1 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCXN_ENABLE);
/* channel2 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCX_ENABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCXN_DISABLE);
}
void motor_lacation_cfg_4()
{
//V+ W-
/* channel0 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCXN_DISABLE);
/* channel1 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCX_ENABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCXN_DISABLE);
/* channel2 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCXN_ENABLE);
}
void motor_lacation_cfg_5()
{
//V+ U-
/* channel0 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCXN_ENABLE);
/* channel1 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCX_ENABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCXN_DISABLE);
/* channel2 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCXN_DISABLE);
}
void motor_lacation_cfg_6()
{
// U+ W-
/* channel0 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCX_ENABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_0, TIMER_CCXN_DISABLE);
/* channel1 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_1, TIMER_CCXN_DISABLE);
/* channel2 configuration */
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCX_DISABLE);
timer_channel_complementary_output_state_config(TIMER0, TIMER_CH_2, TIMER_CCXN_ENABLE);
}
void motor_step_stop()
{
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0, 0);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1, 0);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2, 0);
}
void motor_locate()
{
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0, 1500);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1, 1500);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2, 1500);
if(CCW==0){
motor_lacation_cfg_4();
timer_enable(TIMER0);
delay_1ms(60);
motor_lacation_cfg_6();
timer_enable(TIMER0);
delay_1ms(60);
}
else{//逆时针
motor_lacation_cfg_3();
timer_enable(TIMER0);
delay_1ms(60);
motor_lacation_cfg_2();
timer_enable(TIMER0);
delay_1ms(60);
}
motor_step_stop();
timer_disable(TIMER0);
}
2、电机的外同步加速
确定了电机转子的初始位置后,由于此时定子绕组中的反电动势仍为零,所以须人为改变电机的外施电压和换相信号,使电机由静止逐步加速运动。这一过程称为外同步加速。对于不同的外施电压调整方法和换相信号调整方法,外同步加速可划分为三类:
①换相信号频率不变,逐步增大外施电压使电机加速,称为恒频升压法。
②保持外施电压不变,逐渐增高换相信号的频率,使电机逐步加速,称为恒压升频法。
③在逐步增大外施电压的同时,增高换相的频率,称为升频升压法。
各个方法都有其优点和缺点。如升频升压法是人为地给电机施加一个由低频到高频不断加速的他控同步切换信号,而且电压也在不断地增加。通过调整电机换相频率,即可调整电机启动的速度。调整方法比较简单。但是这个过程较难实现。切换信号的频率的选择要根据电机的极对数和其他参数来确定。太低,电机无法加速;太高,电机转速达不到,会有噪声甚至无法启动,算法比较困难。
无论哪种方法,该过程都是在未检测到反电动势信号时进行。因此对于控制系统来说此段电机控制是盲区。参数在调试好的时候,可以快速切换至正常运行状态;而参数不理想时,电流可能不稳甚至电机会抖动。因此,在应用中,应根据电机及负载特性设定合理的升速曲线,并在尽可能短的时间内完成切换。
void openloop_step_change(uint32_t pwm_duty,uint32_t counter)
{
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0, pwm_duty);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1, pwm_duty);
timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2, pwm_duty);
if(CCW==0){//顺时针
motor_lacation_cfg_2();
delay_1us(counter);
motor_lacation_cfg_3();
delay_1us(counter);
motor_lacation_cfg_1();
delay_1us(counter);
motor_lacation_cfg_5();
delay_1us(counter);
motor_lacation_cfg_4();
delay_1us(counter);
motor_lacation_cfg_6();
delay_1us(counter);}
else{//逆时针
motor_lacation_cfg_6();
delay_1us(counter);
motor_lacation_cfg_4();
delay_1us(counter);
motor_lacation_cfg_5();
delay_1us(counter);
motor_lacation_cfg_1();
delay_1us(counter);
motor_lacation_cfg_3();
delay_1us(counter);
motor_lacation_cfg_2();
delay_1us(counter);}
}
void motor_openloop()
{
int i=0;
timer_enable(TIMER0);
for(i=0;i<192;i++)
{
openloop_step_change(1600,60000-300*i);
}
for(i=0;i<800;i++)
{
openloop_step_change(1600,2700);
}
}
3、电机运行状态的转换
当电机通过外同步加速到一定的转速,反电势信号可以准确检测时,即可由外同步向自同步切换。可以通过试验观察反电势信号能够被准确检测的转速。在进行切换有两种方法:一种是测速模块可以测出电机的转速,当达到这一转速时即可进行切换;另一种,通过试验检测出达到预定切换转速的时间,通过软件定时器设置切换时间。
这一步是关键也是比较难实现的一步。有时软件或者硬件设计的不合理都可能导致启动失败。通常是采用估算的方式来选择切换速度。文章来源:https://www.toymoban.com/news/detail-403248.html
void motor_sensorless_start()
{
timer_channel_control_shadow_config(TIMER0,ENABLE); //开始从外同步切入自同步模式,即使用过零点检测法检测位置
timer_enable(TIMER2);
while(speed_count>1300){} //自同步模式切入后会有短暂的升速阶段,通过判断速度等待并确认自同步成功切入
CloseLoop_Start=1; //闭环标志位置位,后续进行闭环控制
}
int main(void)
{
systick_config();
bldc_gpio_config(); // all gpio
PID_init( &Speed_Ctrl, PID_Speed, I_ref_Max, 0.0f);
PID_init( &I_Ctrl, PID_I, PWM_Duty_Max, 0.0f);
NVIC_CFG();
dma_config();
adc_config();
TimerIn_config();
TimerOut_config();
motor_locate(); //定位
motor_openloop(); //外同步
motor_sensorless_start(); //自同步-闭环
while (1){
}
}
通过上面的分析可知,无位置传感器直流无刷电机控制系统的难点就是加速及切换阶段。当电机顺利启动后,就可以对电机进行调速操作。其中,无位置传感器直流无刷电机和有位置传感器直流无刷电机调速原理一致。但,由于无感三段式启动过程,转子位置检测无效。因此,对电机进行的速度PID闭环控制,须在电机启动顺利完成后进行。文章来源地址https://www.toymoban.com/news/detail-403248.html
到了这里,关于【零基础玩转BLDC系列】无刷直流电机无位置传感器三段式启动法详细介绍及代码分享的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!