无刷电机带上驱动器,掉电外力拖动有阻力

7 篇文章 0 订阅
6 篇文章 0 订阅

无刷电机带上驱动器,掉电外力拖动有阻力

这个问题一直以为很好理解或者应该是总所周知的,但是竟然很多人好奇问专门做电机控制的工程师,但是竟然很多人说不明白,今天我就好好聊一聊。

原因

  1. 反电动势效应
    当无刷电机在没有电源供电的情况下被外力拖动时,电机内部的转子仍然会转动。这时,电机的绕组切割磁力线,产生反电动势(Back EMF)。这个反电动势会在电机的绕组中产生电流,进而产生阻力。

  2. 短接制动
    当三相绕组短接后,反电动势在绕组中产生电流。由于三相绕组是短接的,这些电流在绕组中形成闭合回路,短接电流在绕组中产生的磁场与转子磁场相互作用,产生电磁制动力。这种制动力与电机的转速成正比,即电机转速越高,产生的制动力越大。

  3. 电流路径的形成
    · 定子绕组中的电流:反电动势在定子绕组中产生电压,这个电压驱动电流在定子绕组中流动。
    · 驱动器电路的连接:无刷电机的三相绕组通过连接线与驱动器的三相输出端(U、V、W)相连。即使驱动器掉电,电机绕组中的反电动势仍然会通过这些连接线传输到驱动器。
    · 在驱动器的功率开关元件(如MOSFET)上,通常存在体二极管。这些二极管在反向电压超过其导通电压时会导通,允许电流通过。

电流回路示例

96ddc97895efafd618e38eaafd9e6c8_1_.jpg

  1. 反电动势在B相产生正电压,A相产生负电压,从而形成由B相流入A相的电流。
  2. 电流通过A相的体二极管,进入驱动器的电源轨,又B相的体二极管流入地。
  3. 进入电源轨之后,我们将驱动器上的元器件近似比作一个电阻型负载。此时电流已形成,由于有负载电阻的原因电流并不大,这里可以思考下为什么会有这么大的阻力。

解决办法

  1. 原因:
    工作中大多驱动器的设计都会考虑到这些问题,会来看这个问题的同学多半是自己做的驱动器没有注意这个细节,专门跑到CSDN找原因的。请同学们们仔细看看自己的代码的PWM配置有没有将空闲引脚配置为低,如果为低仍有阻力,继续往后看,你的电流采样的偏置电压基准是否是在初始化时采集。

    回到上面的问题,电流明明很小为什么会产生明显的阻力?就是因为反电动势驱动驱动器上的元器件工作,上电就行初始化中会有将MOSFET导通的操作,形成短接制动的效果。

  2. 解决:

    (1)将初始化的PWM引脚改为高组态

	//STM32
	 sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  	 sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

	//HPM5300
	void disable_all_pwm_output(void)
   {
   /*force pwm*/
    pwm_config_force_cmd_timing(DRV_BLDCPWM, pwm_force_immediately);
    pwm_enable_pwm_sw_force_output(DRV_BLDCPWM, DRV_BLDC_UH_PWM_OUTPIN);
    pwm_enable_pwm_sw_force_output(DRV_BLDCPWM, DRV_BLDC_UL_PWM_OUTPIN);
    pwm_enable_pwm_sw_force_output(DRV_BLDCPWM, DRV_BLDC_VH_PWM_OUTPIN);
    pwm_enable_pwm_sw_force_output(DRV_BLDCPWM, DRV_BLDC_VL_PWM_OUTPIN);
    pwm_enable_pwm_sw_force_output(DRV_BLDCPWM, DRV_BLDC_WH_PWM_OUTPIN);
    pwm_enable_pwm_sw_force_output(DRV_BLDCPWM, DRV_BLDC_WL_PWM_OUTPIN);
    pwm_set_force_output(DRV_BLDCPWM,
                        PWM_FORCE_OUTPUT(DRV_BLDC_UH_PWM_OUTPIN, pwm_output_high_z)
                        | PWM_FORCE_OUTPUT(DRV_BLDC_UL_PWM_OUTPIN, pwm_output_high_z)
                        | PWM_FORCE_OUTPUT(DRV_BLDC_VH_PWM_OUTPIN, pwm_output_high_z)
                        | PWM_FORCE_OUTPUT(DRV_BLDC_VL_PWM_OUTPIN, pwm_output_high_z)
                        | PWM_FORCE_OUTPUT(DRV_BLDC_WH_PWM_OUTPIN, pwm_output_high_z)
                        | PWM_FORCE_OUTPUT(DRV_BLDC_WL_PWM_OUTPIN, pwm_output_high_z));
    pwm_enable_sw_force(DRV_BLDCPWM);

   }

	int main(void){

	disable_all_pwm_output();
    my_pwm_init(MY_PWM_FREQUENCY, 500);
	
	while(1){

	}
	}

根据自己具体的MCU型号做对应处理

(2) 如果是将偏置电压采样放在了mian函数的初始中,较为简单的方法是在采样函数前加一个延时,因为拖动大多并不持续。另外的方法就是在校准中进行偏置电压采样存入flash,常用的方法是在下桥臂关断是再进行一次采样,这时的采样即为偏置电压采样,用作电流采样时的offset进行电流计算,这样的好处就是防止环境或工况变化导致的零漂。


void Motor::current_meas_cb(uint32_t timestamp, std::optional<Iph_ABC_t> current) {
    // TODO: this is platform specific
    //const float current_meas_period = static_cast<float>(2 * TIM_1_8_PERIOD_CLOCKS * (TIM_1_8_RCR + 1)) / TIM_1_8_CLOCK_HZ;
    TaskTimerContext tmr{axis_->task_times_.current_sense};

    n_evt_current_measurement_++;

    bool dc_calib_valid = (dc_calib_running_since_ >= config_.dc_calib_tau * 7.5f)
                       && (abs(DC_calib_.phA) < max_dc_calib_)
                       && (abs(DC_calib_.phB) < max_dc_calib_)
                       && (abs(DC_calib_.phC) < max_dc_calib_);

    if (armed_state_ == 1 || armed_state_ == 2) {
        current_meas_ = {0.0f, 0.0f, 0.0f};
        armed_state_ += 1;
    } else if (current.has_value() && dc_calib_valid) {
        current_meas_ = {
            current->phA - DC_calib_.phA,
            current->phB - DC_calib_.phB,
            current->phC - DC_calib_.phC
        };
    } else {
        current_meas_ = std::nullopt;
    }

    // Run system-level checks (e.g. overvoltage/undervoltage condition)
    // The motor might be disarmed in this function. In this case the
    // handler will continue to run until the end but it won't have an
    // effect on the PWM.
    odrv.do_fast_checks();

    if (current_meas_.has_value()) {
        // Check for violation of current limit
        // If Ia + Ib + Ic == 0 holds then we have:
        // Inorm^2 = Id^2 + Iq^2 = Ialpha^2 + Ibeta^2 = 2/3 * (Ia^2 + Ib^2 + Ic^2)
        float Itrip = effective_current_lim_ + config_.current_lim_margin;
        float Inorm_sq = 2.0f / 3.0f * (SQ(current_meas_->phA)
                                      + SQ(current_meas_->phB)
                                      + SQ(current_meas_->phC));

        // Hack: we disable the current check during motor calibration because
        // it tends to briefly overshoot when the motor moves to align flux with I_alpha
        if (Inorm_sq > SQ(Itrip)) {
            disarm_with_error(ERROR_CURRENT_LIMIT_VIOLATION);
        }
    } else if (is_armed_) {
        // Since we can't check current limits, be safe for now and disarm.
        // Theoretically we could continue to operate if there is no active
        // current limit.
        disarm_with_error(ERROR_UNKNOWN_CURRENT_MEASUREMENT);
    }

    if (control_law_) {
        Error err = control_law_->on_measurement(vbus_voltage,
                            current_meas_.has_value() ?
                                std::make_optional(std::array<float, 3>{current_meas_->phA, current_meas_->phB, current_meas_->phC})
                                : std::nullopt,
                            timestamp);
        if (err != ERROR_NONE) {
            disarm_with_error(err);
        }
    }
}

void Motor::dc_calib_cb(uint32_t timestamp, std::optional<Iph_

ABC_t> current) {
    const float dc_calib_period = static_cast<float>(2 * TIM_1_8_PERIOD_CLOCKS * (TIM_1_8_RCR + 1)) / TIM_1_8_CLOCK_HZ;
    TaskTimerContext tmr{axis_->task_times_.dc_calib};

    if (current.has_value()) {
        const float calib_filter_k = std::min(dc_calib_period / config_.dc_calib_tau, 1.0f);
        DC_calib_.phA += (current->phA - DC_calib_.phA) * calib_filter_k;
        DC_calib_.phB += (current->phB - DC_calib_.phB) * calib_filter_k;
        DC_calib_.phC += (current->phC - DC_calib_.phC) * calib_filter_k;
        dc_calib_running_since_ += dc_calib_period;
    } else {
        DC_calib_.phA = 0.0f;
        DC_calib_.phB = 0.0f;
        DC_calib_.phC = 0.0f;
        dc_calib_running_since_ = 0.0f;
    }
}


  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值