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.

TMS320F28379D: Regeneration source available for Motor Driver

Part Number: TMS320F28379D


Tool/software:

Hello Experts ,

Do you have any reference projects where regeneration is taken care of by wasting the excess enery via a braking resistor?

If not,  I am currently designing my own regeneration protection logic to control the DC bus voltage, could some experts please verify the logics.?

Thanks,

AK

  • No such reference design that could be a very easy method. You can find many introduction about this topic on some of the engineering website.

    With dynamic braking, the electrical energy generated during stopping is released as heat through a voltage regulated transistor and resistor. There are actually two versions of a dynamic braking circuit: a “chopper” and a “dynamic brake.” The dynamic brake circuit includes the switching device (an insulated-gate bipolar transistor, or IGBT), the control circuit, and the resistor.

    A chopper, on the other hand, only includes the regulatory circuit and switching device, with the resistors being separate components. This allows the resistors to be appropriately sized and mounted remotely, which can be important, since the resistors generate a significant amount of heat. The combination of switching device and control circuit is generally referred to as the “chopper module,” while the resistor is referred to as a “dynamic brake resistor.” Dynamic brakes are typically rated for duty cycles in the 20 percent range, and choppers are often used in heavier-duty applications.

     

     

  • Okay, thanks for the info, is there any plan to add that in future?

  • Generally, the user could be easy to add this function by themself according to their hardware.

  • Hi AK,

    A good method often requires a combination of software constraints and hardware as Yanming mentions chopper & dynamic brake. Dynamic brake can also drive NFET switch with PWM modulation by simple calls to dynamic function with preset switch on/off times. We found it very effective to configure an extra PWM output with interrupt to drive low side half bridge at the same PWM frequency as motor drive. The interrupt was asserted at the same intervals of the software dynamic switch on/off constraints within the PWM periods. This method avoids excessive blead off energy often requiring expensive resistors or heat strips. So less is more and efficient use of hardware and software to quickly arrest regeneration energy or even allow some current to flow back into batteries during coasting or engine braking and bus voltage monitored by an ADC channel.

    Regards,

    //*****************************************************************************
    //
    //! \page brake_intro Introduction
    //!
    //! Dynamic braking is the application of a power resistor across the DC bus in
    //! order to control the increase in the DC bus voltage.  The power resistor
    //! reduces the DC bus voltage by converting current into heat.
    //!
    //! The dynamic braking routine is called every millisecond to monitor the DC
    //! bus voltage and handle the dynamic brake.  When the DC bus voltage gets too
    //! high, the dynamic brake is applied to the DC bus.  When the DC bus voltage
    //! drops enough, the dynamic brake is removed.
    //!
    //! In order to control heat buildup in the power resistor, the amount of time
    //! the brake is applied is tracked.  If the brake is applied for too long, it
    //! will be forced off for a period of time (regardless of the DC bus voltage)
    //! to prevent it from overheating.  The amount of time on and off is tracked
    //! as an indirect measure of the heat buildup in the power resistor; the heat
    //! increases when on and decreases when off.
    //!
    //! The code for handling dynamic braking is contained in <tt>brake.c</tt>,
    //! with <tt>brake.h</tt> containing the definitions for the functions exported
    //! to the remainder of the application.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //! \defgroup brake_api Definitions
    //! @{
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    //! The dynamic brake is turned off.  The bus voltage going above the trigger
    //! level will cause a transition to the #STATE_BRAKE_ON state.
    //
    //*****************************************************************************
    #define STATE_BRAKE_OFF         0
    
    //*****************************************************************************
    //
    //! The dynamic brake is turned on.  The bus voltage going below the trigger
    //! level will cause a transition to the #STATE_BRAKE_OFF state, and the brake
    //! being on for too long will cause a transition to #STATE_BRAKE_COOL.
    //
    //*****************************************************************************
    #define STATE_BRAKE_ON          1
    
    //*****************************************************************************
    //
    //! The dynamic brake is forced off to allow the power resistor to cool.  After
    //! the minimum cooling period has expired, an automatic transition to
    //! #STATE_BRAKE_OFF will occur if the bus voltage is below the trigger level
    //! and to #STATE_BRAKE_ON if the bus voltage is above the trigger level.
    //
    //*****************************************************************************
    #define STATE_BRAKE_COOL        2
    
    //*****************************************************************************
    //
    //! The current state of the dynamic brake.  Will be one of #STATE_BRAKE_OFF,
    //! #STATE_BRAKE_ON, or #STATE_BRAKE_COOL.
    //
    //*****************************************************************************
    static uint32_t g_ulBrakeState;
    
    //*****************************************************************************
    //
    //! The number of interrupt microseconds the dynamic brake has been on. For each
    //! brake update period, this is incremented if the brake is on and decremented
    //! if it is off.  This effectively represents the heat buildup in the power
    //! resistor; when on heat will increase and when off it will decrease.
    //
    //*****************************************************************************
    static uint32_t g_ulBrakeCount;
    
    //*****************************************************************************
    //
    //! Updates the dynamic brake.
    //!
    //! This function will update the state of the dynamic brake.  It must be
    //! called at the PWM frequency to provide a time base for determining when to
    //! turn off the brake to avoid overheating.
    //!
    //! \return None.
    //
    //*****************************************************************************
    __interrupt void
    BrakeIntHandler(void)
    {
    
    	static uint32_t ul32BrakeHalfMilliCount;
    
    	/* Clear the interupt twice if the first one is missed */
    	HWREG((PWM0_BASE + PWM_GEN_2) + PWM_O_X_ISC) = (PWM_INT_CNT_AU | PWM_INT_CNT_AD); //PWM_INT_CNT_LOAD
        HWREG((PWM0_BASE + PWM_GEN_2) + PWM_O_X_ISC) = (PWM_INT_CNT_AU | PWM_INT_CNT_AD); //PWM_INT_CNT_LOAD
    
    	//
    	// Update the state of the dynamic brake.
    	// Called at PWM frequency time base for determining
    	// when to turn on and off brake to avoid overheating.
    	//
    	if((!MainIsRunning()) ||
    			(HWREGBITH(&(g_sParameters.usFlags), FLAG_BRAKE_BIT) != FLAG_BRAKE_ON))
    
    	{   //((g_ucMotorStatus == MOTOR_STATUS_DECEL) &&
    
    		/* The brake does not turn on when brake Flag disabled */
    		MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, 0x0);
    
    		return;
    	}
    
    	/* Increment the count by 500 (0.0025ms)
    	 * each interrupt 25us*2=50us period */
    	  ul32BrakeHalfMilliCount += 500;
    
    	//
    	// See if the bus voltage exceeds the voltage required to turn on the
    	// dynamic brake.
    	//
    	if(g_ulBusVoltage > g_sParameters.ulBrakeOnV)
    	{
    		//
    		// The bus voltage is too high, check if brake flag
    		// is currently set on in the primary state machine
    		//
    		if((g_ulBrakeState == STATE_BRAKE_OFF) &&
    		   (HWREGBITH(&(g_sParameters.usFlags), FLAG_BRAKE_BIT) == FLAG_BRAKE_ON))
    		{
    			//
    			// Turn on the dynamic brake.
    			//
    			MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, PIN_BRAKE_PIN);//0x4
    
    			//
    			// Change the brake state to on.
    			//
    			g_ulBrakeState = STATE_BRAKE_ON;
    
    		}
    	}
    
    	//
    	// Otherwise, see if the dynamic brake is on and the bus voltage is less
    	// than the voltage required to turn it off.
    	//
    	else if((g_ulBusVoltage < g_sParameters.ulBrakeOffV) &&
    			(g_ulBrakeState == STATE_BRAKE_ON))//STATE_BRAKE_ON
    	{
    		//
    		// Turn off the dynamic brake.
    		//
    		MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, 0x0); //0x0~(PIN_BRAKE_PIN)
    
    		//
    		// Change the brake state to off.
    		//
    		g_ulBrakeState = STATE_BRAKE_OFF;
    
    		/* Brake is off so clear count */
    		//g_ulBrakeCount = 0;
    
    	}
    
    	//
    	// See if the dynamic brake is on.
    	//
    	if(g_ulBrakeState == STATE_BRAKE_ON)
    	{
    		//
    		// Increment the number of brake ticks that the dynamic brake has been
    		// on.
    		//
    		g_ulBrakeCount ++; //++
    
    		//
    		// See if the dynamic brake has been on for too long.
    		// The brake cool time (seconds) and the state machine must
    		// compensate brake counts for much faster PWM interrupt periods
    		// 1:1 brake count ratio of total BrakeMax 2.5sec or 500us
    		// PWM periods interrupt duty cycle via GEN2 CMPA up CMPB down.
    		//
    		if(g_ulBrakeCount * 10 >= g_sParameters.ulBrakeMax / 5000)//5000
    		{
    		    //
    		    // See how many milliseconds expired.
    		    //
    		    if(ul32BrakeHalfMilliCount >= g_sParameters.ulBrakeMax)
    		    {
    				//
    				// Turn off the dynamic brake.
    				//
    				MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, 0x0);//0x0 ~(PIN_BRAKE_PIN)
    
    				//
    				// Change the brake state to cool to allow the braking resistor to
    				// cool off (to avoid overheating).
    				//
    				g_ulBrakeState = STATE_BRAKE_COOL;
    
    		        // Decrement the 1/2 counter by the brake count, which
    		        // corresponds to one milliseconds.
    		       ul32BrakeHalfMilliCount -= g_ulBrakeCount * 40;//g_sParameters.ulBrakeMax
    
    			/* Cool down so clear brake ON count */
    			//g_ulBrakeCount = 0;
    		    }
    		 }
    	}
    
    	//
    	// Otherwise, see if dynamic brake tick count is now cooling.
    	//
    	else if(g_ulBrakeState == STATE_BRAKE_COOL) //g_ulBrakeCount !=0
    	{
    		//
    		// Decrement the number of brake ticks that the dynamic brake has been
    		// off.
    		//
    		g_ulBrakeCount ++; //--
    
    		//
    		// See if the dynamic brake is in the cooling state and has cooled off
    		// for long enough. The brake cool time (seconds) and the state
    		// machine must compensate brake counts for much faster PWM interrupt periods.
    		//
    		if((g_ulBrakeState == STATE_BRAKE_COOL) &&
    		   (g_ulBrakeCount * 10 >= g_sParameters.ulBrakeCool / 5000))//5000
    		{
    		    //
    		    // See how many milliseconds are counted to cool brakes
    		    //
    		    if(ul32BrakeHalfMilliCount >= g_sParameters.ulBrakeCool)
    		    {
    				//
    				// The dynamic brake has cooled off enough, so see if the bus
    				// voltage exceeds the voltage required to turn it on.
    				//
    				if(g_ulBusVoltage >= g_sParameters.ulBrakeOnV)
    				{
    					//
    					// Turn on the dynamic brake.
    					//
    					MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, PIN_BRAKE_PIN);//0x4
    
    					// Change the brake state to on.
    					g_ulBrakeState = STATE_BRAKE_ON; //on
    
    					/* Exit and clear brake count */
    				  //g_ulBrakeCount = 0;
    
    				}
    		        // Decrement the 1/2 counter by the brake count, which
    		        // corresponds to one milliseconds.
    		       ul32BrakeHalfMilliCount -= g_ulBrakeCount * 40; //g_sParameters.ulBrakeMax
    			}
    
    			//
    			// Otherwise, the voltage is low enough that the brake should
    			// remain off.
    			//
    			else
    			{
    				// Turn off the dynamic brake.
    				MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, 0x0);
    
    				// Change the brake state to off.
    				g_ulBrakeState = STATE_BRAKE_OFF;
    
    				/* Exit and clear brake count */
    				g_ulBrakeCount = 0;
    
    			}
    		}
    	}
    }
    //*****************************************************************************
    //
    //! Initializes the dynamic braking control routines.
    //!
    //! This function initializes the ADC module and the control routines,
    //! preparing them to monitor currents and voltages on the motor drive.
    //!
    //! \return None.
    //
    //*****************************************************************************
    void
    BrakeInit(void)
    {
        //
        // Configure brake for (UCC27517DVBR, FL3100T Low side FET driver) keep pin "0" state (Brake disabled).
        // BP1-X9,Pin20(PP2)MCU-103
    
        MAP_GPIOPinWrite(PIN_BRAKE_PORT, PIN_BRAKE_PIN, 0x0);
    
        //
        // The initial brake state is off.
        //
        g_ulBrakeState = STATE_BRAKE_OFF;
    
        //
        // The initial brake count is zero.
        //
        g_ulBrakeCount = 0;
    }
    
    //*****************************************************************************
    //
    // Close the Doxygen group.
    //! @}
    //
    //*****************************************************************************

  • Thanks GI. 

    AK, you may refer to the code GI mentioned above.

  • Thanks Yanming Happy Holidays,

    Above C code was used on TI-Arm Cortex MCU, should not be difficult a rewrite for C2000 hardware. The GUI brake page input overlay time constraints had two other features used with GUI composer or HMI device. The deceleration voltage sets ramp threshold to avoid rapid dives in velocity (PI) during braking or coasting. Set brake off typically near nominal bus voltage or bit under as battery drains the peak supply voltage also falls to lower SOC. The MCU temperature constraint could turn off the motor if MCU gets to hot or turn on a small cooling fan placed above or near MCU.

  • Thanks  &  for the source code, I have a few questions from your source code, please correct me wherever i am wrong or if i am assuming somthing unknown.
    1. I don't see any modululation(i.e 0 to 100 percent duty cycle modulation) of the brake mosfet , i mean the brake mosfet is either fully on or fully off(binary).
    Would'nt that have a lot of ripple on the DC bus? OR (worst case) , you briefly start cunsuming some current from the battery/input , while the brake mosfet is fully switched on?

    2. You mention in your code, somewhere that the dc bus is checked every milli-second..
    For a system which is very dynamic, i mean the regenerative torque that would be applied would almost be like a sudden step to the system, this time would be too slow, if the dc bus rise time exceeds 1 ms, then the bus voltage would be uncontrollable..

    3. I am asuming that this control scheme is for a system with a relatively low Motor speed and the load dynamics of the system are well known, for a motor operating at a relatively high RPM , for a small regenerative torque(of even if there is a sudden decelaration demanded), the rise time of the DC bus would be quite big?, Would the control scheme compensate for this sudden change?

    4. The control scheme that you had shared, Could it be done in MCU hardware? i.e. no software involvement at all by using a CMPSS module to compare the DC bus voltage, coupled with a EPWM CBC(cycle by cycle) trip zone, to turn the GPIO on/off(using the ePWM modules test actions and Digital compare module)..would'nt this be safer and faster?, Has anybody tried this approach?

    Lastly, i have tried to make my own "reactive feedforward" controller that takes into account the dc bus voltage, speed,
    voltage dynamics by verifying the energey built up and the bus voltage rise/fall times.


    The function ReactiveFeedforwardBrakeController() first assigns a rough brake effort , and the function brakeEffortValidation()
    validates the calculated effort by calculating the minimum energy and looking at the dc bus voltage transients individually.
    Could you have a look and share your thoughts:

    //! \brief      Verifies and adjusts brake chopper effort based on energy and voltage dynamics.
    //!
    //! **Example**
    //! ~~~~~~~~~~.c
    //! totalEffort = brakeEffortValidation(totalEffort, &brakeChopperVars, &motorVars[0]);
    //! ~~~~~~~~~~
    //!
    //! **Details**
    //! This function ensures the brake chopper effort is sufficient to manage both
    //! regenerative energy and voltage dynamics on the DC bus.
    //!
    //! **Functionality**
    //!
    //! 1. **Energy Calculations**:
    //!    - **Regenerative Energy (Eregen)**: Calculates the energy added to the DC
    //!      bus per second based on motor torque and speed:
    //!      Eregen = (Torque * Speed) / 9.549.
    //!    - **Brake Energy (Ebrake)**: Calculates the energy dissipated by the brake
    //!      chopper per second:
    //!      Ebrake = totalEffort * (Vdc^2 / R), where R is the brake resistance (6.6 ohm).
    //!
    //! 2. **Effort Adjustment (Energy Comparison)**:
    //!    - If Eregen > Ebrake:
    //!        a. Calculates the minimum brake effort required to counter-balance the
    //!           energy imbalance: minEffort = (Eregen * R) / (Vdc^2).
    //!        b. Adds a 20% safety margin for pro-active braking to reduce DC bus voltage.
    //!
    //! 3. **Voltage Dynamics**:
    //!    - Computes voltage rise (deltaV_rise) due to regenerative energy:
    //!      deltaV_rise = (Eregen * timestep) / (Cdc * Vdc)
    //!    - Computes voltage fall (deltaV_fall) due to brake energy:
    //!      deltaV_fall = (Ebrake * timestep) / (Cdc * Vdc)
    //!    - If voltage rise exceeds voltage fall (deltaV_rise > deltaV_fall), calculates:
    //!        a. Voltage imbalance: deltaV_imbalance = deltaV_rise - deltaV_fall
    //!        b. Power imbalance: Pimbalance = (Cdc * Vdc * deltaV_imbalance) / timestep
    //!    - Derives additional braking effort to correct the imbalance:
    //!      deltaEffort = (Pimbalance * brakeRes) / (Vdc^2)
    //!
    //! 4. **Output**:
    //!    - Returns the adjusted total brake chopper effort to handle energy and
    //!      voltage dynamics effectively.
    //!
    //! **Parameters**
    //! \param[in]  totalEffort  Initial brake chopper effort (in pu).
    //! \param[in]  pBrCp        Pointer to the brake chopper variable structure.
    //! \param[in]  pMotor       Pointer to the motor variable structure.
    //! \return     Adjusted brake chopper effort (in pu).
    float32_t brakeEffortValidation(float32_t totalEffort, BrCp_Vars_t *pBrCp, const MOTOR_Vars_t *pMotor)
    {
        /* System constants */
        const float32_t brakeRes = 6.6f;                  // Brake resistor value in ohms
        const float32_t Cdc = 540.0e-6f;                  // DC bus capacitance in farads (default 540uF)
        const float32_t timestep = 150.0e-6f;             // Controller time step in seconds (150 us)
    
        /* Regenerative energy per second */
        //float32_t Eregen = (pMotor->TorqueNmRef * fabs(pMotor->speed.SpeedRpm)) / 9.549;
        float32_t Eregen = __divf32((pMotor->TorqueNmRef * fabs(pMotor->speed.SpeedRpm)),9.549);
    
        /* Brake energy per second */
        //float32_t Ebrake = totalEffort * ((pBrCp->dcBusBrCp * pBrCp->dcBusBrCp) / brakeRes);
        float32_t Ebrake = totalEffort * __divf32((pBrCp->dcBusBrCp * pBrCp->dcBusBrCp), brakeRes);
    
        /* Compare energies */
        if (Eregen > Ebrake)
        {
            /* Calculate the minimum required effort to counter the energy imbalance */
            //float32_t minEffort = (Eregen * brakeRes) / (pBrCp->dcBusBrCp * pBrCp->dcBusBrCp);
            float32_t minEffort = __divf32((Eregen * brakeRes), (pBrCp->dcBusBrCp * pBrCp->dcBusBrCp));
    
            /* Add a safety margin for pro-active braking */
            minEffort *= 1.2f;  // 20% safety margin to reduce DC bus voltage
    
            totalEffort = minEffort;
        }
    
        /* Compute voltage rise (Delta Vrise) due to regenerative energy */
        //float32_t deltaV_rise = (Eregen * timestep) / (Cdc * pBrCp->dcBusBrCp);
        float32_t deltaV_rise = __divf32((Eregen * timestep), (Cdc * pBrCp->dcBusBrCp));
    
        /* Compute voltage fall (Delta Vfall) due to brake energy */
        //float32_t deltaV_fall = (Ebrake * timestep) / (Cdc * pBrCp->dcBusBrCp);
        float32_t deltaV_fall = __divf32((Ebrake * timestep), (Cdc * pBrCp->dcBusBrCp));
    
        /* Compare voltage changes */
        if (deltaV_rise > deltaV_fall)
        {
            /* Calculate the voltage imbalance */
            float32_t deltaV_imbalance = deltaV_rise - deltaV_fall;
    
            /* Calculate the power imbalance (P = C * V * dV/dt) */
            //float32_t Pimbalance = (Cdc * pBrCp->dcBusBrCp * deltaV_imbalance) / timestep;
            float32_t Pimbalance = __divf32((Cdc * pBrCp->dcBusBrCp * deltaV_imbalance), timestep);
    
            /* Calculate the additional effort to offset the power imbalance */
            //float32_t deltaEffort = (Pimbalance * brakeRes) / (pBrCp->dcBusBrCp * pBrCp->dcBusBrCp);
            float32_t deltaEffort = __divf32((Pimbalance * brakeRes), (pBrCp->dcBusBrCp * pBrCp->dcBusBrCp));
    
            /* Update total effort */
            totalEffort += deltaEffort;
        }
    
        /* Return the final brake effort */
        return totalEffort;
    }
    
    //! \brief      Reactive Feedforward Brake Controller for Brake Chopper Duty Cycle.
    //!
    //! **Example**
    //! ~~~~~~~~~~.c
    //! ReactiveFeedforwardBrakeController(&brakeChopperVars, &motorVars[0]);
    //! ~~~~~~~~~~
    //!
    //! **Details**
    //! This function calculates and updates the brake chopper's duty cycle by summing
    //! reactive efforts from DC bus voltage, quadrature current (Iq), and motor speed.
    //! The effort is validated and adjusted to balance energy using brakeEffortValidation.
    //!
    //! **Functionality**
    //!
    //! 1. **DC Bus Voltage Effort**:
    //!    - If the DC bus voltage exceeds the nominal level (310V), the effort is
    //!      calculated as a percentage of the range between nominal (310V) and
    //!      maximum (330V) voltage:
    //!      dcbusEffort = ((Vdc - nominalDCbus) / (maxDCbus - nominalDCbus)) * 60%
    //!    - Effort is clamped between 0% and 60%.
    //!
    //! 2. **Quadrature Current (Iq) Effort**:
    //!    - The effort is proportional to the feedback quadrature current (IqFbk)
    //!      relative to its maximum value (1.0 pu):
    //!      iqEffort = (IqFbk / iqMax) * 35%
    //!    - Effort is clamped between 0% and 35%.
    //!
    //! 3. **Speed Effort**:
    //!    - The effort is calculated based on motor speed feedback relative to
    //!      the maximum speed (12000 RPM):
    //!      speedEffort = (SpeedFbk / speedMax) * 5%
    //!    - Effort is clamped between 0% and 5%.
    //!
    //! 4. **Total Effort Calculation**:
    //!    - If there is a DC bus voltage rise, the total effort is computed as:
    //!      totalEffort = (dcbusEffort + iqEffort + speedEffort) / 100
    //!    - The effort is validated and adjusted using `brakeEffortValidation()`.
    //!    - The validated total effort is clamped to a maximum of 90%.
    //!
    //! 5. **Brake Chopper Duty Cycle Update**:
    //!    - The total effort is assigned to the brake chopper's duty cycle `a_duty`.
    //!    - The PWM module is updated using `updateBrCpDutyCycle()`.
    //!
    //! **Parameters**
    //! \param[in]  pBrCp   A pointer to the brake chopper variable structure.
    //! \param[in]  pMotor  A pointer to the motor variable structure.
    //! \return     None (updates `a_duty` in the brake chopper structure).
    void ReactiveFeedforwardBrakeController(BrCp_Vars_t *pBrCp, const MOTOR_Vars_t *pMotor)
    {
        /* Percentage of effort */
        const float32_t dcBusPercentage = 60.0f;
        const float32_t iqPercentage = 35.0f;
        const float32_t speedPercentage = 5.0f;
    
        /* Scaling parameters */
        const float32_t nominalDCbus = 310.0f;   //volts
        const float32_t maxDCbus = 330.0f;       //volts
        const float32_t iqMax = 1.0f;            //pu
        const float32_t speedMax = 12000.0f;     //RPM
    
        float32_t speedFbk = fabs(pMotor->speed.SpeedRpm);
        float32_t iqFbk = fabs(pMotor->ptrFCL->pi_iq.fbk);
    	pBrCp->dcBusBrCp = pMotor->Vdcbus;		//Assign the dc bus voltage to the brake struct variable
    
        //Calculate the DC bus effort
        float32_t dcbusEffort = 0.0f;
        if(pBrCp->dcBusBrCp > nominalDCbus)
        {
            //dcbusEffort = ((pBrCp->dcBusBrCp - nominalDCbus) / (maxDCbus - nominalDCbus)) * dcBusPercentage;
            dcbusEffort = __divf32((pBrCp->dcBusBrCp - nominalDCbus), (maxDCbus - nominalDCbus)) * dcBusPercentage;
            dcbusEffort = fmaxf((fminf(dcbusEffort,dcBusPercentage)),0.0);    //range check
        }
        else
        {
            dcbusEffort = 0.0f;
        }
    
        //Calculate the quadrature current effort
        float32_t iqEffort = 0.0f;
        if(fabs(iqFbk * 100) > 0.0f)
        {
            //iqEffort = (iqFbk / iqMax) * iqPercentage;
            iqEffort = __divf32(iqFbk, iqMax) * iqPercentage;
            iqEffort = fmaxf((fminf(iqEffort,iqPercentage)),0.0);    //range check
        }
        else
        {
            iqEffort = 0.0f;
        }
    
        //Calculate the Speed effort
        float32_t speedEffort = 0.0f;
        if(speedFbk > 0)
        {
            //speedEffort = (speedFbk / speedMax) * speedPercentage;
            speedEffort = __divf32(speedFbk, speedMax) * speedPercentage;
            speedEffort = fmaxf((fminf(speedEffort,speedPercentage)),0.0);    //range check
        }
        else
        {
            speedEffort = 0.0f;
        }
    
        //Sum up all the efforts only if there is a raise in the DC bus
        float32_t totalEffort = 0.0f;
        if(dcbusEffort != 0.0f)
        {
            totalEffort = dcbusEffort + iqEffort + speedEffort;
            totalEffort = __divf32(totalEffort, 100);                       //Convert to pu
    
            //Validate the effort 
            totalEffort = brakeEffortValidation(totalEffort, pBrCp, pMotor);
    
            totalEffort = fmaxf((fminf(totalEffort,0.90)),0.0);    //range check to 0 to 90%
        }
        else
        {
            totalEffort = 0.0f;
        }
    
        //Assign the effort to the brake chopper duty cycle
        pBrCp->a_duty = totalEffort;
    
        //update the duty cycle to the pwm module
        updateBrCpDutyCycle(pMotor, pBrCp);
    }

  • 1. I don't see any modululation(i.e 0 to 100 percent duty cycle modulation) of the brake mosfet , i mean the brake mosfet is either fully on or fully off(binary).

    The interrupt timing is derived via PWM module not 1ms, more like 50us intervals at 20KHz

    2. You mention in your code, somewhere that the dc bus is checked every milli-second.

    The original code was configured to call the brake function during 1ms duty cycle updates.  That simply did not work as well as PWM interrupt function during comparator A up/down intervals derived from the PWM period.

    4. The control scheme that you had shared, Could it be done in MCU hardware? i.e. no software involvement at all by using a CMPSS module to compare the DC bus voltage, coupled with a EPWM CBC(cycle by cycle) trip zone, to turn the GPIO on/off(using the ePWM modules test actions and Digital compare module)..would'nt this be safer and faster?, Has anybody tried this approach

    The point of the module is to control the thermal dynamics of the brake resistor by asserting cool down cycles via PWM periods. So the resistor rated wattage is not easily overloaded since the PWM interrupt gives precise and proportionate brake on to brake off cool intervals. You have to experiment with the brake on/off times relative to the PWM period of your project. The HW advantage is the power control circuit does not have to be so robust and lower power NFET and low side bridge driver or pulsed LED driver can be used to provide proper gate voltage up to +15VDC.

  • You don't need a high switching MOSFET for braking, you just need to turn on or turn off the MOSFET according to the bus voltage.

  • Hi Yanming,

    Curious, does TI recommend switching bridge drives on as an alternative brake method, where motor coils dissipate brake energy? One concern being excessive brake energy might burn cooper wire coating (polyamide), even overheat stator NdFeB rotor magnets past a recovery point. The blead off resistor seems less likely to destroy a perfectly good motor and far less costly to simply replace power resistor if it might burn to a point of needing replacement.

  • Most of customer will select the braking mode and design the braking circuit according to their system. TI doesn't have a specific recommendation.

  • However, the DRV series driver chips typically have a SPI address for brake and coast commands used to assert NFET control over those functions. Seemingly that would be the easiest way to assert braking without adding any additional hardware. If the SPI brake command were enabled by bool flag state in a brake function added to (main.c) loop. Would it also drive NFETS via PWM during trajectory deceleration or just keep NFET gates fully enabled?

    There is electrical difference between coasting and braking in the way the half bridges are driven and what the ADC inputs to Clarke and Park transforms, fast estimator keeps producing rotor angles during rapid braking. One would assume we also have to change the target trajectory for braking to a zero speed. So the fast estimator does not keep trying to assert the original target trajectory speed during braking - right? 

  • FAST is just an estimator to estimate the rotor angle and speed. Generally, the braking operation is not related to the estimator if you are using the hard braking mode.