cancel
Showing results for 
Search instead for 
Did you mean: 

6-Step Algorithm for Sensorless Motor application

Esakkimuthu
Associate II

I am using the STM32 NUCLEO-G474RE control board and the NUCLEO-IHM08M1 inverter board for a motor-control application. I want to run a 6-step (trapezoidal) commutation algorithm, so I need to generate PWM signals from the control board to the driver IC on the power board(NUCLEO-IHM08M1).

The driver IC (L6398) truth table specifies:

  • HIN = 0 and LIN = 0 → Low-side ON

  • HIN = 1 and LIN = 1 → High-side ON

But the STM32 timer provides complementary PWM outputs, where each channel only gives PWM + its inverted output, so it does not match the L6398 input logic. With complementary channels, the outputs are only HIGH or LOW for PWM—they cannot give “both HIGH” or “both LOW” on the same phase simultaneously as required by the driver.

Therefore, I need guidance on how to generate the correct 6-step commutation sequence for the IHM08M1 board using the NUCLEO-G474RE, given that the L6398 requires both HIN and LIN to be controlled independently.

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @Esakkimuthu,

 

MCSDK 6.4.1 controls complementary PWM generation on high-side and low-side signals for phase control with the specified board configuration.

To modify the management, you must directly change the code of the MCSDK.

After generating a project with the MCSDK workbench, the file mc_parameters.c contains several definitions for the PWM timer, particularly configurations for the CCER, CCMR1, and CCMR2 registers. These registers control the states of the PWM high-side and low-side signals.

Refer to the register description in chapter 29, Advanced-control timers (TIM1/TIM8/TIM20), of the documentation available at:

https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

For example, you can update the following structures according to your requirements.

.CCER_cfg = {
CCER_STEP14_CUSTOM,
CCER_STEP25_CUSTOM,
CCER_STEP36_CUSTOM,
CCER_STEP14_CUSTOM,
CCER_STEP25_CUSTOM,
CCER_STEP36_CUSTOM,
},

 

.CCMR1_Standard_cfg = {
CCMR1_STEP1_CUSTOM,
CCMR1_STEP2_CUSTOM,
CCMR1_STEP3_CUSTOM,
CCMR1_STEP4_CUSTOM,
CCMR1_STEP5_CUSTOM,
CCMR1_STEP6_CUSTOM,
},
.CCMR2_Standard_cfg = {
CCMR2_STEP1_CUSTOM,
CCMR2_STEP2_CUSTOM,
CCMR2_STEP3_CUSTOM,
CCMR2_STEP4_CUSTOM,
CCMR2_STEP5_CUSTOM,
CCMR2_STEP6_CUSTOM,
},

In your case something like that:

  • Phase A: HIN_A = PWM, LIN_A = 1

  • Phase B: HIN_B = 0, LIN_B = 0

  • Phase C: HIN_C = 0, LIN_C = 1

#define CCER_STEP14_CUSTOM  TIM_CCER_CC4E_Msk | TIM_CCER_CC3NE_Msk | TIM_CCER_CC3E_Msk | TIM_CCER_CC2NP | TIM_CCER_CC2NE_Msk | TIM_CCER_CC1NP | TIM_CCER_CC1E_Msk, /* A B */

#define  CCMR1_STEP1_CUSTOM  TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2PE_Msk | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE_Msk, /* */

#define CCMR2_STEP1_CUSTOM TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE_Msk | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE_Msk, /* */

....

 

Best regards.

Fabrice

View solution in original post

5 REPLIES 5
STuser2
Senior III

STuser2_0-1763104187817.png

STuser2_1-1763104216433.png

 

LIN is active low input, whether you have considered this?

 

Yes, I have considered that LIN is active-LOW.
The L6398 truth table requires the inputs to be equal to turn a MOSFET ON:

  • HIN = 1, LIN = 1 → High-side ON

  • HIN = 0, LIN = 0 → Low-side ON

  • HIN = 0, LIN = 1 → Phase FLOAT (both OFF)

So for low-side ON I must drive LIN = 0, and for high-side ON I must drive LIN = 1.

My practical control scheme:

  • Phase HIGH: HIN = PWM, LIN = 1

  • Phase LOW: HIN = 0 (PWM disabled), LIN = 0

  • Phase FLOAT: HIN = 0, LIN = 1

I will not use the complementary CHxN outputs because they generate the opposite of HIN and would create invalid 1/0 → OFF states.

This approach is correct for 6-step BLDC where:

  • PWM is applied only on the high-side of the active phase, and

  • the low-side of the sink phase remains fully ON (LIN = 0) during the entire step.

Example:
To drive A+ / B- / C floating

  • Phase A: HIN_A = PWM, LIN_A = 1

  • Phase B: HIN_B = 0, LIN_B = 0

  • Phase C: HIN_C = 0, LIN_C = 1

I am not sure how you are generating the code etc, but see if the below CubeMx settings are useful

STuser2_0-1763113682927.png

It is giving an option to generate complementary or independent, verify if it is useful.

Hi @Esakkimuthu,

 

MCSDK 6.4.1 controls complementary PWM generation on high-side and low-side signals for phase control with the specified board configuration.

To modify the management, you must directly change the code of the MCSDK.

After generating a project with the MCSDK workbench, the file mc_parameters.c contains several definitions for the PWM timer, particularly configurations for the CCER, CCMR1, and CCMR2 registers. These registers control the states of the PWM high-side and low-side signals.

Refer to the register description in chapter 29, Advanced-control timers (TIM1/TIM8/TIM20), of the documentation available at:

https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

For example, you can update the following structures according to your requirements.

.CCER_cfg = {
CCER_STEP14_CUSTOM,
CCER_STEP25_CUSTOM,
CCER_STEP36_CUSTOM,
CCER_STEP14_CUSTOM,
CCER_STEP25_CUSTOM,
CCER_STEP36_CUSTOM,
},

 

.CCMR1_Standard_cfg = {
CCMR1_STEP1_CUSTOM,
CCMR1_STEP2_CUSTOM,
CCMR1_STEP3_CUSTOM,
CCMR1_STEP4_CUSTOM,
CCMR1_STEP5_CUSTOM,
CCMR1_STEP6_CUSTOM,
},
.CCMR2_Standard_cfg = {
CCMR2_STEP1_CUSTOM,
CCMR2_STEP2_CUSTOM,
CCMR2_STEP3_CUSTOM,
CCMR2_STEP4_CUSTOM,
CCMR2_STEP5_CUSTOM,
CCMR2_STEP6_CUSTOM,
},

In your case something like that:

  • Phase A: HIN_A = PWM, LIN_A = 1

  • Phase B: HIN_B = 0, LIN_B = 0

  • Phase C: HIN_C = 0, LIN_C = 1

#define CCER_STEP14_CUSTOM  TIM_CCER_CC4E_Msk | TIM_CCER_CC3NE_Msk | TIM_CCER_CC3E_Msk | TIM_CCER_CC2NP | TIM_CCER_CC2NE_Msk | TIM_CCER_CC1NP | TIM_CCER_CC1E_Msk, /* A B */

#define  CCMR1_STEP1_CUSTOM  TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2PE_Msk | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE_Msk, /* */

#define CCMR2_STEP1_CUSTOM TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE_Msk | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE_Msk, /* */

....

 

Best regards.

Fabrice

Thank you @Fabrice LOUBEYRE for the detailed clarification!

Your explanation about how MCSDK 6.4.1 manages complementary PWM generation through the CCER and CCMR register configurations in mc_parameters.c is extremely helpful. I now understand that modifying the high-side and low-side behavior for each phase requires customizing those predefined step structures directly in the MCSDK-generated code.

The example you provided—showing how to override CCER_STEPx, CCMR1_STEPx, and CCMR2_STEPx with custom bitmask configurations—makes it much clearer how to implement specific commutation patterns such as:

  • Phase A: HIN_A = PWM, LIN_A = 1

  • Phase B: HIN_B = 0, LIN_B = 0

  • Phase C: HIN_C = 0, LIN_C = 1

And the custom macro definitions you shared (e.g., CCER_STEP14_CUSTOM, CCMR1_STEP1_CUSTOM, CCMR2_STEP1_CUSTOM) give a good reference for how the TIM1/TIM8 configuration bits should be combined.

I also appreciate the reference to RM0440 – Chapter 29 (Advanced-control Timers); that will help me verify each bit and understand exactly how the output states are controlled.

Thanks again for the clear explanation!