cancel
Showing results for 
Search instead for 
Did you mean: 

PWM complementary Output

Arek
Associate

Hi,
I try to implemend sinus algorithm for BLDC engine on  STM32G474RE chip.  

I want to use TIM1 (CH1 - CH3) and (CH1N - CH3N) to control a bldc controller. I have configured a complementary output with dead time according to datasheat (so I think) and I have a phase shift problem. Output waveform:

Screenshot from 2023-07-06 14-59-22.png

At first glance, everything looks good, but after zooming in:

Screenshot from 2023-07-06 14-59-31.png

 The 3rd(CH3) signals and 6th(CH3N) are shifted by ~2ms. Does anyone knows what could cause that?
my pwm setup:
```

#define MOTOR_INH_C_PIN (LL_GPIO_PIN_0)
#define MOTOR_INH_C_PORT (GPIOC)

#define MOTOR_INH_B_PIN (LL_GPIO_PIN_1)
#define MOTOR_INH_B_PORT (GPIOC)

#define MOTOR_INH_A_PIN (LL_GPIO_PIN_2)
#define MOTOR_INH_A_PORT (GPIOC)

 

 
void EnginePwm::Init()
{
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);

Enable();

SetPrescaler(32000, 1000);

MODIFY_REG(TIM1->CR1, TIM_CR1_CMS_Msk, (0x01b << TIM_CR1_CMS_Pos));
TIM1->CR2 |= TIM_CR2_OIS1;
TIM1->CR2 |= TIM_CR2_OIS1N;
TIM1->CR2 |= TIM_CR2_OIS2;
TIM1->CR2 |= TIM_CR2_OIS2N;
TIM1->CR2 |= TIM_CR2_OIS3;
TIM1->CR2 |= TIM_CR2_OIS3N;

TIM1->CCMR1 = 0;
TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
TIM1->CCMR1 |= TIM_CCMR1_OC1PE;
// TIM1->CCER |= TIM_CCER_CC1P_Msk;
TIM1->CCR1 = 0;

TIM1->CCMR1 |= TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1;
TIM1->CCMR1 |= TIM_CCMR1_OC2PE;
// TIM1->CCER |= TIM_CCER_CC2P_Msk;
TIM1->CCR2 = 0;

TIM1->CCMR2 = 0;
TIM1->CCMR2 |= TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1;
TIM1->CCMR2 |= TIM_CCMR2_OC3PE;
// TIM1->CCER |= TIM_CCER_CC3P_Msk;
TIM1->CCR3 = 0;

TIM1->CCR1 = 0;
TIM1->CCR2 = 0;
TIM1->CCR3 = 0;
MODIFY_REG(TIM1->BDTR, TIM_BDTR_DTG_Msk, (30 << TIM_BDTR_DTG_Pos));
TIM1->BDTR |= TIM_BDTR_OSSR_Msk;
TIM1->BDTR |= TIM_BDTR_OSSI_Msk;

TIM1->CCER |= TIM_CCER_CC1E_Msk; // disable pwm motor 1
TIM1->CCER |= TIM_CCER_CC1NE_Msk; // disable pwm motor 1
TIM1->CCER |= TIM_CCER_CC2E_Msk; // disable pwm motor 2
TIM1->CCER |= TIM_CCER_CC2NE_Msk;
TIM1->CCER |= TIM_CCER_CC3E_Msk; // disable pwm motor 3
TIM1->CCER |= TIM_CCER_CC3NE_Msk;

TIM1->BDTR |= TIM_BDTR_MOE;
TIM1->BDTR |= TIM_BDTR_AOE;
TIM1->EGR |= TIM_EGR_UG; // generate update
TIM1->CR1 |= TIM_CR1_CEN; // enable timer
}

void EnginePwm::Enable()
{
LL_GPIO_InitTypeDef gpioStruct;
LL_GPIO_StructInit(&gpioStruct);
gpioStruct.Pin = MOTOR_INH_A_PIN;
gpioStruct.Mode = LL_GPIO_MODE_ALTERNATE;
gpioStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpioStruct.Pull = LL_GPIO_PULL_NO;
gpioStruct.Alternate = LL_GPIO_AF_2;
gpioStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(MOTOR_INH_A_PORT, &gpioStruct);

LL_GPIO_StructInit(&gpioStruct);
gpioStruct.Pin = MOTOR_INH_B_PIN;
gpioStruct.Mode = LL_GPIO_MODE_ALTERNATE;
gpioStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpioStruct.Pull = LL_GPIO_PULL_NO;
gpioStruct.Alternate = LL_GPIO_AF_2;
gpioStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(MOTOR_INH_B_PORT, &gpioStruct);

LL_GPIO_StructInit(&gpioStruct);
gpioStruct.Pin = LL_GPIO_PIN_0;
gpioStruct.Mode = LL_GPIO_MODE_ALTERNATE;
gpioStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpioStruct.Pull = LL_GPIO_PULL_NO;
gpioStruct.Alternate = LL_GPIO_AF_6;
gpioStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOB, &gpioStruct);

LL_GPIO_StructInit(&gpioStruct);
gpioStruct.Pin = LL_GPIO_PIN_1;
gpioStruct.Mode = LL_GPIO_MODE_ALTERNATE;
gpioStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpioStruct.Pull = LL_GPIO_PULL_NO;
gpioStruct.Alternate = LL_GPIO_AF_6;
gpioStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOB, &gpioStruct);

LL_GPIO_StructInit(&gpioStruct);
gpioStruct.Pin = LL_GPIO_PIN_13;
gpioStruct.Mode = LL_GPIO_MODE_ALTERNATE;
gpioStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpioStruct.Pull = LL_GPIO_PULL_NO;
gpioStruct.Alternate = LL_GPIO_AF_6;
gpioStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOB, &gpioStruct);

LL_GPIO_StructInit(&gpioStruct);
gpioStruct.Pin = MOTOR_INH_C_PIN;
gpioStruct.Mode = LL_GPIO_MODE_ALTERNATE;
gpioStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
gpioStruct.Pull = LL_GPIO_PULL_NO;
gpioStruct.Alternate = LL_GPIO_AF_2;
gpioStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(MOTOR_INH_C_PORT, &gpioStruct);
}
 
 
and my control loop switch:
Ta = 0.4 * sinTable[59 - (teta)];
Tb = 0.4 * sinTable[(teta)];
T0 = (1000 - Ta - Tb) / 2;
T0 = 0;
if (oldTeta == teta)
{
continue;
}
oldTeta = teta;
uint8_t val = 0;
switch (lastSector)
{
case 1:
TIM1->CCR1 = (Ta + Tb) + (T0);
TIM1->CCR2 = T0;
TIM1->CCR3 = (Tb) + (T0);

break;
case 3:
TIM1->CCR1 = Ta + (T0);
TIM1->CCR2 = T0;
TIM1->CCR3 = (Ta + Tb) + (T0);

break;
case 2:
TIM1->CCR1 = T0;
TIM1->CCR2 = Tb + (T0);
TIM1->CCR3 = (Ta + Tb) + (T0);

break;
case 6:
TIM1->CCR1 = T0;
TIM1->CCR2 = (Ta + Tb) + (T0);
TIM1->CCR3 = Ta + (T0);

break;
case 4:
TIM1->CCR1 = Tb + (T0);
TIM1->CCR2 = (Ta + Tb) + (T0);
TIM1->CCR3 = T0;

break;
case 5:
TIM1->CCR1 = (Ta + Tb) + (T0);
TIM1->CCR2 = Ta + (T0);
TIM1->CCR3 = T0;

break;
default:
LogDebug(("Error %d", lastSector));
break;
}

Anyone had similar problem? 

Arek 

 

 

 

 

0 REPLIES 0