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.

BLDC motor PWM generation with ePWM

Other Parts Discussed in Thread: TMS320F28027, DRV8301, CONTROLSUITE

Hello,


I am currently learning the basics of BLDC motor control. I have successfully generated 6 step commutation signals with ePWM module. Now I would like to modulate high side FETs with higher frequency PWM signal. On the image below you can see my signals for high side FETs and a PWM signal I would like to modulate them with.

Hardware I use: TMS320F28027 and DRV8301 on custom board.

I would kindly ask if anyone can give me any information on how to accomplish this.

Or point me to the relevant literature if this is something one wouldn't do to drive a BLDC motor. As I understand duty cycle of the higher frequency PWM on high side FETs effectively sets the amount of energy supplied to the motor and commutation frequency aligns accordingly to the rotating speed.

Here is what i got so far:

    CLK_enablePwmClock(myClk, PWM_Number_1);

    PWM_setPeriod(myPwm1, PWM_Period);						//Set period -> TBCLK counts
    PWM_setCmpA(myPwm1, PWM_Period / 6);					//Set Comp_A val
    PWM_setCmpB(myPwm1, (5 * PWM_Period) / 6);					//Set Comp_B val
    PWM_setPhase(myPwm1, 0);							//Set Phase register to zero
    PWM_setCount(myPwm1, 0);							//Clear TBCLK count
    PWM_setCounterMode(myPwm1, PWM_CounterMode_UpDown);				//Symmetrical mode
    PWM_disableCounterLoad(myPwm1);						//As master module
    PWM_setSyncMode(myPwm1, PWM_SyncMode_CounterEqualZero);			//Sync slave module @ counter = to zero
    PWM_setShadowMode_CmpA(myPwm1, PWM_ShadowMode_Shadow);			//Shadow CmpA
    PWM_setShadowMode_CmpB(myPwm1, PWM_ShadowMode_Shadow);			//Shadow CmpB
    PWM_setLoadMode_CmpA(myPwm1, PWM_LoadMode_Zero);				//Load CmpA @ zero
    PWM_setLoadMode_CmpB(myPwm1, PWM_LoadMode_Zero);				//Load CmpB @ zero


    PWM_setHighSpeedClkDiv(myPwm1, PWM_HspClkDiv_by_1);     		// Clock ratio to SYSCLKOUT
    PWM_setClkDiv(myPwm1, PWM_ClkDiv_by_1);

    // Set actions
    PWM_setActionQual_CntUp_CmpA_PwmA(myPwm1, PWM_ActionQual_Set);
    PWM_setActionQual_CntUp_CmpB_PwmA(myPwm1, PWM_ActionQual_Clear);

    PWM_setActionQual_CntDown_CmpB_PwmB(myPwm1, PWM_ActionQual_Set);
    PWM_setActionQual_CntDown_CmpA_PwmB(myPwm1, PWM_ActionQual_Clear);


 //Init PWM2
    CLK_enablePwmClock(myClk, PWM_Number_2);

    PWM_setPeriod(myPwm2, PWM_Period);						//Set period -> TBCLK counts
    PWM_setCmpA(myPwm2, PWM_Period / 6);					//Set Comp_A val
    PWM_setCmpB(myPwm2, (5 * PWM_Period) / 6);					//Set Comp_B val
    PWM_setPhase(myPwm2, PWM_Period / 3);					//Set Phase register to zero
    PWM_setCount(myPwm2, 0);							//Clear TBCLK count
    PWM_setCounterMode(myPwm2, PWM_CounterMode_UpDown);				//Symmetrical mode
    PWM_enableCounterLoad(myPwm2);						//As slave module
    PWM_setSyncMode(myPwm2, PWM_SyncMode_EPWMxSYNC);				//sync flow-through
    PWM_setShadowMode_CmpA(myPwm2, PWM_ShadowMode_Shadow);			//Shadow CmpA
    PWM_setShadowMode_CmpB(myPwm2, PWM_ShadowMode_Shadow);			//Shadow CmpB
    PWM_setLoadMode_CmpA(myPwm2, PWM_LoadMode_Zero);				//Load CmpA @ zero
    PWM_setLoadMode_CmpB(myPwm2, PWM_LoadMode_Zero);				//Load CmpB @ zero

    PWM_setHighSpeedClkDiv(myPwm2, PWM_HspClkDiv_by_1);     		        // Clock ratio to SYSCLKOUT
    PWM_setClkDiv(myPwm2, PWM_ClkDiv_by_1);

    // Set actions
    PWM_setActionQual_CntUp_CmpA_PwmB(myPwm2, PWM_ActionQual_Set);
    PWM_setActionQual_CntUp_CmpB_PwmB(myPwm2, PWM_ActionQual_Clear);

    PWM_setActionQual_CntDown_CmpB_PwmA(myPwm2, PWM_ActionQual_Set);
    PWM_setActionQual_CntDown_CmpA_PwmA(myPwm2, PWM_ActionQual_Clear);

//Init PWM3
	CLK_enablePwmClock(myClk, PWM_Number_3);

	PWM_setPeriod(myPwm3, PWM_Period);					//Set period -> TBCLK counts
	PWM_setCmpA(myPwm3, PWM_Period / 6);					//Set Comp_A val
	PWM_setCmpB(myPwm3, (5 * PWM_Period) / 6);				//Set Comp_B val
	PWM_setPhase(myPwm3, (2 * PWM_Period) / 3);				//Set Phase register to zero
	PWM_setCount(myPwm3, 0);						//Clear TBCLK count
	PWM_setCounterMode(myPwm3, PWM_CounterMode_UpDown);			//Symmetrical mode
	PWM_enableCounterLoad(myPwm3);						//As slave module
	PWM_setSyncMode(myPwm3, PWM_SyncMode_EPWMxSYNC);			//sync flow-through
	PWM_setShadowMode_CmpA(myPwm3, PWM_ShadowMode_Shadow);			//Shadow CmpA
	PWM_setShadowMode_CmpB(myPwm3, PWM_ShadowMode_Shadow);			//Shadow CmpB
	PWM_setLoadMode_CmpA(myPwm3, PWM_LoadMode_Zero);			//Load CmpA @ zero
	PWM_setLoadMode_CmpB(myPwm3, PWM_LoadMode_Zero);			//Load CmpB @ zero

	PWM_setHighSpeedClkDiv(myPwm3, PWM_HspClkDiv_by_1);     		// Clock ratio to SYSCLKOUT
	PWM_setClkDiv(myPwm3, PWM_ClkDiv_by_1);

	// Set actions
	PWM_setActionQual_CntUp_CmpA_PwmA(myPwm3, PWM_ActionQual_Set);
	PWM_setActionQual_CntUp_CmpB_PwmA(myPwm3, PWM_ActionQual_Clear);

	PWM_setActionQual_CntDown_CmpB_PwmB(myPwm3, PWM_ActionQual_Set);
	PWM_setActionQual_CntDown_CmpA_PwmB(myPwm3, PWM_ActionQual_Clear);

//Init PWM4
    CLK_enablePwmClock(myClk, PWM_Number_4);

    PWM_setPeriod(myPwm4, PWM4_Period);						//Set period -> TBCLK counts
    PWM_setCmpA(myPwm4, PWM4_Period / 2);					//Set Comp_A val
    PWM_setPhase(myPwm4, 0);							//Set Phase register to zero
    PWM_setCount(myPwm4, 0);							//Clear TBCLK count
    PWM_setCounterMode(myPwm4, PWM_CounterMode_Up);		   		//Symmetrical mode
    PWM_disableCounterLoad(myPwm4);						//Master mode
    PWM_setShadowMode_CmpA(myPwm4, PWM_ShadowMode_Shadow);			//Shadow CmpA
    PWM_setShadowMode_CmpB(myPwm4, PWM_ShadowMode_Shadow);			//Shadow CmpB
    PWM_setLoadMode_CmpA(myPwm4, PWM_LoadMode_Zero);				//Load CmpA @ zero


    PWM_setHighSpeedClkDiv(myPwm4, PWM_HspClkDiv_by_1);     		        // Clock ratio to SYSCLKOUT
    PWM_setClkDiv(myPwm4, PWM_ClkDiv_by_1);

    // Set actions
    PWM_setActionQual_CntUp_CmpA_PwmA(myPwm4, PWM_ActionQual_Clear);
    PWM_setActionQual_Period_PwmA(myPwm4, PWM_ActionQual_Set);

  • I would always suggest you start with a working software solution and modify to fit your needs
    There is a sensorless 6-step version for DRV8301 + F28035 in controlSUITE
    C:\ti\controlSUITE\development_kits\DRV830x-HC-C2-KIT_v105\InstaSPIN_BLDC

    this uses a 20 KHz PWM by default.
  • Thank you for quick reply!
    I was hoping for an conceptual explanation of how to do it. As it seems very complex I'll spend some time interpreting that code.
    I am working on my bachelor thesis and the only goal is to run the motor in sensorless mode and to understand the basics of electronic commutation and sensorless speed control.