This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

关于 TZ 功能,触发PWM关闭的问题

请问一下,C2000 功能 TZ 触发区,是完全关闭 PWM输出,再次上电时才能使能输出?还是达到触发条件(低电平)关闭PWM输出,在恢复成高电平时则恢复PWM输出?增在使用这个功能做硬件保护,测试发现当低电平时,PWM关闭输出,恢复高电平时,PWM正常输出,这样是否会烧毁电机?

  • “请问一下,C2000 功能 TZ 触发区,是完全关闭 PWM输出,再次上电时才能使能输出?还是达到触发条件(低电平)关闭PWM输出,在恢复成高电平时则恢复PWM输出?增在使用这个功能做硬件保护,测试发现当低电平时,PWM关闭输出,恢复高电平时,PWM正常输出,这样是否会烧毁电机?”

    Eric:

    TZ 保护功能有两种模式,一种是Cycle by cycle, 一种是one shot模式。

    one shot 模式的时候,TZ信号一旦有低电平信号,则封锁PWM输出,即使TZ信号恢复为高电平,也需要软件上去清除TZ的标志位,才能恢复PWM输出。一般过流保护都用这个模式。

    Cycle by cycle模式是,TZ信号一旦有低电平,则封锁PWM输出。但是每个PWM周期都会检查TZ信号是否恢复为高电平,如果为高电平,则自动释放PWM输出。这种可以用在限流。

  • Hi,Eric,

    谢谢您的答案!我还有疑问的是,当我选择触发模式为 one shot时,表现依然与 Cycle by cycle 一致,这是为什么呢?我外部保护使用的是TZ3。
    for(cnt=0;cnt<3;cnt++)
    {
    PWM_enableTripZoneSrc(obj->pwmHandle[cnt],PWM_TripZoneSrc_CycleByCycle_TZ6_NOT);

    PWM_enableTripZoneSrc(obj->pwmHandle[cnt],PWM_TripZoneSrc_CycleByCycle_TZ5_NOT);

    PWM_enableTripZoneSrc(obj->pwmHandle[cnt],PWM_TripZoneSrc_OneShot_TZ3_NOT);

    // What do we want the OST/CBC events to do?
    // TZA events can force EPWMxA
    // TZB events can force EPWMxB

    PWM_setTripZoneState_TZA(obj->pwmHandle[cnt],PWM_TripZoneState_EPWM_Low);
    PWM_setTripZoneState_TZB(obj->pwmHandle[cnt],PWM_TripZoneState_EPWM_Low);
    }
  • "我还有疑问的是,当我选择触发模式为 one shot时,表现依然与 Cycle by cycle 一致,这是为什么呢?我外部保护使用的是TZ3。"

    Eric:

    如果你设置TZ3 为one shot, 然后TZ3有个低电平信号来之后,C2000 pwm就会拉低。

    你说的表现和cycle by cycle一样,那么我的判断是程序中有代码把TZFLG给清除掉了,然后导致PWM又恢复了,如enable PWM的函数。所以你要找找程序中哪里有调用TZFLG CLEAR之类的函数。

  • Hi, Eric,

    是的,我在主循环中,若控制状态和EST状态都在 online,是仍然使能 PWM的。

    我不知道这是不是根源,我的疑问是,若发生 TZ 触发事件,关闭了 PWM输出,是否会将控制状态等转变为空闲?或者说标志位 Flag_Run_Identify 和 Flag_enableSys是否会被清零?

    若没有被清零,在发生 TZ 触发拉低PWM 后,我如何检测当前状态?或者说如何一直关闭PWM?我没有使用 DRV 驱动,因此没有 SPI 读取故障信息。谢谢您!
  • 另外一个疑问是,若选择 TZ 异步触发,是否还会走 TZFLG 标志位置位?

  • "是的,我在主循环中,若控制状态和EST状态都在 online,是仍然使能 PWM的。

    我不知道这是不是根源,我的疑问是,若发生 TZ 触发事件,关闭了 PWM输出,是否会将控制状态等转变为空闲?或者说标志位 Flag_Run_Identify 和 Flag_enableSys是否会被清零?

    若没有被清零,在发生 TZ 触发拉低PWM 后,我如何检测当前状态?或者说如何一直关闭PWM?我没有使用 DRV 驱动,因此没有 SPI 读取故障信息"
    Eric:
    跟TZ异步同步没啥关系。
    主要是enable PWM 这个函数会清除TZ的标志位。
    run identify 和enable system一般都是手动清零。不会自动清零,除非在预测参数时出现系统故障。
  • HI, Eric, 

    关于标志问题,明白了,谢谢您!

    但是,我主循环也是按照例程执行的,HAL_enablePwm(halHandle);函数也只有在 online 状态执行,在运行阶段,ctrl_state 一直是 online 状态,因此按照
    下面程序逻辑,在状态没有改变以前是不会再执行   if(flag_ctrlStateChanged) 该条件内的内容,因此,在发生 TZ 事件后,应该也不会执行吧?还是说 TZ
    事件发生之后,改变了控制状态?

    while(gMotorVars.Flag_enableSys) { CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle; // increment counters gCounter_updateGlobals++; // enable/disable the use of motor parameters being loaded from user.h CTRL_setFlag_enableUserMotorParams(ctrlHandle,gMotorVars.Flag_enableUserParams); // enable/disable Rs recalibration during motor startup EST_setFlag_enableRsRecalc(obj->estHandle,gMotorVars.Flag_enableRsRecalc); // enable/disable automatic calculation of bias values CTRL_setFlag_enableOffset(ctrlHandle,gMotorVars.Flag_enableOffsetcalc); if(CTRL_isError(ctrlHandle)) { // set the enable controller flag to false CTRL_setFlag_enableCtrl(ctrlHandle,false); // set the enable system flag to false gMotorVars.Flag_enableSys = false; // disable the PWM HAL_disablePwm(halHandle); } else { // update the controller state bool flag_ctrlStateChanged = CTRL_updateState(ctrlHandle); // enable or disable the control CTRL_setFlag_enableCtrl(ctrlHandle, gMotorVars.Flag_Run_Identify); if(flag_ctrlStateChanged) { CTRL_State_e ctrlState = CTRL_getState(ctrlHandle); if(ctrlState == CTRL_State_OffLine) { // enable the PWM HAL_enablePwm(halHandle); } else if(ctrlState == CTRL_State_OnLine) { if(gMotorVars.Flag_enableOffsetcalc == true) { // update the ADC bias values HAL_updateAdcBias(halHandle); } else { // set the current bias HAL_setBias(halHandle,HAL_SensorType_Current,0,_IQ(I_A_offset)); HAL_setBias(halHandle,HAL_SensorType_Current,1,_IQ(I_B_offset)); HAL_setBias(halHandle,HAL_SensorType_Current,2,_IQ(I_C_offset)); // set the voltage bias HAL_setBias(halHandle,HAL_SensorType_Voltage,0,_IQ(V_A_offset)); HAL_setBias(halHandle,HAL_SensorType_Voltage,1,_IQ(V_B_offset)); HAL_setBias(halHandle,HAL_SensorType_Voltage,2,_IQ(V_C_offset)); } // Return the bias value for currents gMotorVars.I_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Current,0); gMotorVars.I_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Current,1); gMotorVars.I_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Current,2); // Return the bias value for voltages gMotorVars.V_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Voltage,0); gMotorVars.V_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Voltage,1); gMotorVars.V_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Voltage,2); // enable the PWM HAL_enablePwm(halHandle); } else if(ctrlState == CTRL_State_Idle) { // disable the PWM HAL_disablePwm(halHandle); gMotorVars.Flag_Run_Identify = false; } if((CTRL_getFlag_enableUserMotorParams(ctrlHandle) == true) && (ctrlState > CTRL_State_Idle) && (gMotorVars.CtrlVersion.minor == 6)) { // call this function to fix 1p6 USER_softwareUpdate1p6(ctrlHandle); } } } if(EST_isMotorIdentified(obj->estHandle)) { // set the current ramp EST_setMaxCurrentSlope_pu(obj->estHandle,gMaxCurrentSlope); gMotorVars.Flag_MotorIdentified = true; // set the speed reference CTRL_setSpd_ref_krpm(ctrlHandle,gMotorVars.SpeedRef_krpm); // set the speed acceleration CTRL_setMaxAccel_pu(ctrlHandle,_IQmpy(MAX_ACCEL_KRPMPS_SF,gMotorVars.MaxAccel_krpmps)); if(Flag_Latch_softwareUpdate) { Flag_Latch_softwareUpdate = false; USER_calcPIgains(ctrlHandle); // initialize the watch window kp and ki current values with pre-calculated values gMotorVars.Kp_Idq = CTRL_getKp(ctrlHandle,CTRL_Type_PID_Id); gMotorVars.Ki_Idq = CTRL_getKi(ctrlHandle,CTRL_Type_PID_Id); // initialize the watch window kp and ki values with pre-calculated values gMotorVars.Kp_spd = CTRL_getKp(ctrlHandle,CTRL_Type_PID_spd); gMotorVars.Ki_spd = CTRL_getKi(ctrlHandle,CTRL_Type_PID_spd); } } else { Flag_Latch_softwareUpdate = true; // the estimator sets the maximum current slope during identification gMaxCurrentSlope = EST_getMaxCurrentSlope_pu(obj->estHandle); } // when appropriate, update the global variables if(gCounter_updateGlobals >= NUM_MAIN_TICKS_FOR_GLOBAL_VARIABLE_UPDATE) { // reset the counter gCounter_updateGlobals = 0; updateGlobalVariables_motor(ctrlHandle); } // update Kp and Ki gains updateKpKiGains(ctrlHandle); // enable/disable the forced angle EST_setFlag_enableForceAngle(obj->estHandle,gMotorVars.Flag_enableForceAngle); } // end of while(gFlag_enableSys) loop