TMS320F280037C: Universal motor control reverse direction disable

Guru 56398 points

Part Number: TMS320F280037C

Hello,

UMCSDK: v5.03 - v5.04 

When we disable the motor in the reverse direction seemingly torque changes positive causing current to pop in the motor windings.  That is not occuring in the forward direction when setting            motorVars_M1.flagEnableRunAndIdentify = false;

Notably, first disabling 3 half bridges outputs in reverse direction to stop motor produce same sudden pop. Why can we properly decelerate the motor in forward direction to a full stop but not in the reverse direction? Even as decel trajectory current is divided 4 times either direction. 

Copilot AI can't even figure out why we can make the motor decelerate in forward, change the sign for reverse the motor runs at what ever the pot is set with added speed guard band (±4Hz) or the motor speed oscillates wildly by the ADC samples. Also turning the pot alone should never start a motor running.

           if(obj->speedRef_Hz > 0.0f)
            {
                obj->direction = 1.0f;
            }
            else
            {
                obj->direction = -1.0f;
            }

                if(bFwd_Dir && obj->direction == 1.0f)
                {
                    //SCIprintf(">> DecelSpeed \n");
                    /* reduce acceleration, slowly decelerate to a stop */
                    obj->speedRef_Hz -= 0.05f; //= obj->speedRef_Hz
                }
                if(!bFwd_Dir && obj->direction == -1.0f)
                {
                    /* reduce acceleration, slowly decelerate to a stop */
                    //obj->speedRef_Hz += -0.05f;   // move toward zero
                    //obj->speedRef_Hz = fabsf(obj->speedRef_Hz);// enforce negative sign

                    /* Set motor offline not running */
                    motorVars_M1.flagEnableRunAndIdentify = false;

               }

  • Hi,

    Can you please capture the phase currents, DC bus voltage, and PWM signals with a scope during the reverse stop? 

    Thanks,

    Jiaxin

  • Can you please capture the phase currents, DC bus voltage, and PWM signals with a scope during the reverse stop? 

    Hi Jiaxin,

    This is a software issue where the sign change on speedRef_Hz is not working the same in reverse, of course the current is going to spike. The bus voltage of course jumps back to +183v after the phase current collapses. We really don't need reverse all the time and the rotor does run CCW but it refuses to slowly reduce the trajectory speedRef_Hz in the forever loop as forward CW direction. The last speedRef_Hz is being saved prior to declaration.  

    Please test these code snips on TI motor test bench.

    The phase current should not suddenly spike in reverse direction when setting motorVars_M1.flagEnableRunAndIdentify = false;

    Project floats math set to relaxed.

    The acceleration trajectory current is divided by 4 during deceleration. That is why we can restart inside deceleration back to the last throttle speed without asserting flying restart. Automotive cruise control works a bit like this when resume button is activated.     

    /* Reduce half the min/max deceleration current */
    if(bMainDecel)
    {
        PI_setMinMax(obj->piHandle_spd, -obj->maxCurrent_A / 4, obj->maxCurrent_A / 4);
    }
    else
    {
        PI_setMinMax(obj->piHandle_spd, -obj->maxCurrent_A , obj->maxCurrent_A );
    }

  • Hello,

    The asymmetry is in the posted code. In forward, speedRef_Hz is ramped down (-= 0.05f), so the motor decelerates under closed-loop control. In reverse, the ramp is commented out and the code sets flagEnableRunAndIdentify = false at full speed.

    This disables the PWM outputs immediately, so the phase current commutates through the body diodes and the stored energy returns to the DC bus. That is the current spike and bus jump you are seeing. Disabling the half bridges directly is the same event, which is why it produces the same result.

    Note the commented line += -0.05f moves the reference further negative, commanding acceleration in reverse. The mirror of the forward logic is += 0.05f toward zero, then clear the flag near zero speed.

    You can confirm this by disabling in forward at full speed: the same transient will occur.

    Best regards,

    Kudra

  • Hello Kudra,

    Thank you for looking at this issue.

    The asymmetry is in the posted code. In forward, speedRef_Hz is ramped down (-= 0.05f)

    We also tested code inverse as you suggested though the same issue occurs.(+= 0.05f) as if the direction detection guard code slips into forward direction sign change in C code. That is why we added sign test logic. So the CPU IP should never end up in forward deceleration loop when in reverse and visa-versa.  

    You can confirm this by disabling in forward at full speed: the same transient will occur.

    Well setting the PWM drives high impedance (GPIO disabling half bridge outputs) in forward direction does not cause any current spike and before setting motorVars_M1.flagEnableRunAndIdentify = false. That just confused FAST estimator logic, then we have to clear faults several times before the next run. Though you are correct in the forward deceleration loop first motorVars_M1.flagEnableRunAndIdentify = false, lastly GPIO disables half bridge outputs.

    So, in forward CW direction that adds a panic mode. When something is going seriously wrong test bench can double tap stop for panic in either direction. A single tap enters deceleration or coasting regenerative braking can be enabled in the same loop then tapping start again recovers the last set pot speed. Speed pot updates in 500µs polling loop, that also sets the reverse sign in the speedRef_Hz and LastspeedRef_Hz floats.

    This snip was causing disable current spike. Of course without the direction flags and the else if inverse clause it was entering the top if clause.

    if(motorVars_M1.speed_Hz <= 5.0f && bFwd_Dir) 

       DEVICE_DELAY_US(10); //10us
       /* Set motor offline not running */
       motorVars_M1.flagEnableRunAndIdentify = false;
       //
       DEVICE_DELAY_US(10); //10us
      /* Disable the gate drives */
      GPIO_writePin(37, 0);

    }

    else if(motorVars_M1.speed_Hz >= 5.0f && !bFwd_Dir)
    {
      // same code }

     

  • Hello, 

    I see the mechanism identified in your last paragraph. speed_Hz is signed, so in reverse it is negative and the condition speed_Hz <= 5.0f is true at all reverse speeds. The disable branch therefore fired at full speed in reverse, which is the current spike; the drive was being shut off while running, exactly as described earlier. In forward, the same condition only becomes true below 5 Hz, which is why forward never showed it.

    One caution on the corrected code: else if(speed_Hz >= 5.0f && !bFwd_Dir) will never be true if speed_Hz is negative in reverse, so the reverse stop may now never trigger. The condition should be speed_Hz >= -5.0f, or more simply fabsf(motorVars_M1.speed_Hz) <= 5.0f used for both directions, with bFwd_Dir only selecting the ramp sign.

    Best regards, 

    Kudra.

  • Hi Kudra,

    else if(speed_Hz >= 5.0f && !bFwd_Dir) will never be true if speed_Hz is negative in reverse,

    Yet else if was asserting for both ±5.0f signs when bench tested but adding the fabsf() was key or else would decel down to 78Hz hang there. Somehow fabsf() enforces the sign from changing in the -= clause and was not necessary for += clause and likely more relative for FPU inverse integer math.

    more simply fabsf(motorVars_M1.speed_Hz) <= 5.0f used for both directions, with bFwd_Dir only selecting the ramp sign.

    Oddly the else if <= 5.0f clause caused immediate phase crash though did not have fabsf() directive. Adding fabsf() then motor decels down to 0Hz.

    more simply fabsf(motorVars_M1.speed_Hz) <= 5.0f used for both directions, with bFwd_Dir only selecting the ramp sign.

    I'm unclear what you mean about bFWD_Dir only selecting the ramp sign? The two bool flags are to assure the GUI push button 0/1 state is asserted across three C modules. It also does not allow bool flag change if the speed_Hz != 0.0f.