cancel
Showing results for 
Search instead for 
Did you mean: 

HRTIM up down mode. PWM randomly switches polarity

LGard.1
Associate II

Hi folks,

I'm facing a strange issue with my PWM which changes polarity every once in a while and I think the issue is due to the way I'm generating a PWM while using up and down counter mode.

I have two identical configured but independent HRTIM counters, TA and TD. As I said both are in up-down counter mode. On Period and Zero TA furthermore triggers the ADC.

Here is the HRTIM config using LL lib:

	LL_HRTIM_ConfigADCTrig(HRTIM1, LL_HRTIM_ADCTRIG_1, LL_HRTIM_ADCTRIG_UPDATE_TIMER_A, LL_HRTIM_ADCTRIG_SRC13_TIMAPER|LL_HRTIM_ADCTRIG_SRC13_TIMARST);
	LL_HRTIM_SetADCPostScaler(HRTIM1, LL_HRTIM_ADCTRIG_1, 0x0);
	LL_HRTIM_TIM_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_PRESCALERRATIO_MUL32);
	LL_HRTIM_TIM_SetCounterMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_MODE_CONTINUOUS);
	LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_A, m_u16PwmPeriod);
	LL_HRTIM_TIM_SetRepetition(HRTIM1, LL_HRTIM_TIMER_A, 0x00);
	LL_HRTIM_TIM_SetUpdateGating(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_UPDATEGATING_INDEPENDENT);
	LL_HRTIM_TIM_SetCountingMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_COUNTING_MODE_UP_DOWN);
	LL_HRTIM_TIM_SetComp1Mode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_GTCMP1_EQUAL);
	LL_HRTIM_TIM_SetRollOverMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetFaultEventRollOverMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetBMRollOverMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetADCRollOverMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetOutputRollOverMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetDACTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_DACTRIG_NONE);
	LL_HRTIM_TIM_DisableHalfMode(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_SetInterleavedMode(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_INTERLEAVED_MODE_DISABLED);
	LL_HRTIM_TIM_DisableStartOnSync(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_DisableResetOnSync(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_DisableResyncUpdate(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_SetUpdateTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_UPDATETRIG_NONE|LL_HRTIM_UPDATETRIG_NONE);
	LL_HRTIM_TIM_SetResetTrig(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_RESETTRIG_NONE);
	LL_HRTIM_TIM_DisablePushPullMode(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_EnableDeadTime(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_SetBurstModeOption(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_BURSTMODE_MAINTAINCLOCK);
	LL_HRTIM_ForceUpdate(HRTIM1, LL_HRTIM_TIMER_A);
	LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_A, m_u16PwmPeriod/4);
	LL_HRTIM_DT_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_DT_PRESCALER_MUL8);
	LL_HRTIM_DT_SetRisingValue(HRTIM1, LL_HRTIM_TIMER_A, 54);
	LL_HRTIM_DT_SetRisingSign(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_DT_RISING_POSITIVE);
	LL_HRTIM_DT_SetFallingValue(HRTIM1, LL_HRTIM_TIMER_A, 81);
	LL_HRTIM_DT_SetFallingSign(HRTIM1, LL_HRTIM_TIMER_A, LL_HRTIM_DT_FALLING_POSITIVE);
	LL_HRTIM_OUT_SetPolarity(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_POSITIVE_POLARITY);
	LL_HRTIM_OUT_SetOutputSetSrc(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUTPUTSET_TIMCMP1);
	LL_HRTIM_OUT_SetOutputResetSrc(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUTPUTRESET_TIMCMP1);
	LL_HRTIM_OUT_SetIdleMode(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_NO_IDLE);
	LL_HRTIM_OUT_SetIdleLevel(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_IDLELEVEL_INACTIVE);
	LL_HRTIM_OUT_SetFaultState(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_FAULTSTATE_NO_ACTION);
	LL_HRTIM_OUT_SetChopperMode(HRTIM1, LL_HRTIM_OUTPUT_TA1, LL_HRTIM_OUT_CHOPPERMODE_DISABLED);
	
	/* Poll for DLL end of calibration */
	while(LL_HRTIM_IsActiveFlag_DLLRDY(HRTIM1) == RESET)
	{
		if (LL_SYSTICK_IsActiveCounterFlag())  /* Check Systick counter flag to decrement the time-out value */
		{
			if(Timeout-- == 0)
			{
				// TODO: Handle error
			}
		}
	}
	
	LL_HRTIM_TIM_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_PRESCALERRATIO_MUL32);
	LL_HRTIM_TIM_SetCounterMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_MODE_CONTINUOUS);
	LL_HRTIM_TIM_SetPeriod(HRTIM1, LL_HRTIM_TIMER_D, m_u16PwmPeriod);
	LL_HRTIM_TIM_SetRepetition(HRTIM1, LL_HRTIM_TIMER_D, 0x00);
	LL_HRTIM_TIM_SetUpdateGating(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_UPDATEGATING_INDEPENDENT);
	LL_HRTIM_TIM_SetCountingMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_COUNTING_MODE_UP_DOWN);
	LL_HRTIM_TIM_SetComp1Mode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_GTCMP1_GREATER);
	LL_HRTIM_TIM_SetRollOverMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetFaultEventRollOverMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetBMRollOverMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetADCRollOverMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetOutputRollOverMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_ROLLOVER_MODE_BOTH);
	LL_HRTIM_TIM_SetDACTrig(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_DACTRIG_NONE);
	LL_HRTIM_TIM_DisableHalfMode(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_SetInterleavedMode(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_INTERLEAVED_MODE_DISABLED);
	LL_HRTIM_TIM_DisableStartOnSync(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_DisableResetOnSync(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_DisableResyncUpdate(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_SetUpdateTrig(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_UPDATETRIG_NONE|LL_HRTIM_UPDATETRIG_NONE);
	LL_HRTIM_TIM_SetResetTrig(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_RESETTRIG_NONE);
	LL_HRTIM_TIM_DisablePushPullMode(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_EnableDeadTime(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_SetBurstModeOption(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_BURSTMODE_MAINTAINCLOCK);
	LL_HRTIM_ForceUpdate(HRTIM1, LL_HRTIM_TIMER_D);
	LL_HRTIM_TIM_SetCompare1(HRTIM1, LL_HRTIM_TIMER_D, m_u16PwmPeriod/4);
	LL_HRTIM_DT_SetPrescaler(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_DT_PRESCALER_MUL8);
	LL_HRTIM_DT_SetRisingValue(HRTIM1, LL_HRTIM_TIMER_D, 54);
	LL_HRTIM_DT_SetRisingSign(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_DT_RISING_POSITIVE);
	LL_HRTIM_DT_SetFallingValue(HRTIM1, LL_HRTIM_TIMER_D, 81);
	LL_HRTIM_DT_SetFallingSign(HRTIM1, LL_HRTIM_TIMER_D, LL_HRTIM_DT_FALLING_POSITIVE);
	LL_HRTIM_OUT_SetPolarity(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUT_POSITIVE_POLARITY);
	LL_HRTIM_OUT_SetOutputSetSrc(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUTPUTSET_TIMCMP1);
	LL_HRTIM_OUT_SetOutputResetSrc(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUTPUTRESET_TIMCMP1);
	LL_HRTIM_OUT_SetIdleMode(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUT_NO_IDLE);
	LL_HRTIM_OUT_SetIdleLevel(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUT_IDLELEVEL_INACTIVE);
	LL_HRTIM_OUT_SetFaultState(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUT_FAULTSTATE_NO_ACTION);
	LL_HRTIM_OUT_SetChopperMode(HRTIM1, LL_HRTIM_OUTPUT_TD1, LL_HRTIM_OUT_CHOPPERMODE_DISABLED);
 

I think the issue is that I'm setting and resetting the output on TIMCMP1 so if I change the compare value while the counter value is larger than the compare value, the output polarity flips which doesn't happen if I change the compare value while the counter value is smaller than the compare value. Does that make sense?

If I change the above so that the reset occurs on the counter reset. Everything works fine and the polarity never flips.

Assuming the above is correct: How can I implement a PWM that uses an up and down counter as shown in the HRTIM cookbook p.51 and still be able to arbitrarily change the compare value without having the issue of the output flipping polarity.

Thanks in advance!

Lenn

4 REPLIES 4
Bubbles
ST Employee

Hi @LGard.1​ ,

some compare values are not usable. The compare value must be above or equal to 3 periods of the fHRTIM clock.

BR,

J

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

LGard.1
Associate II

Hi @JHOUD​,

thanks for your suggestion. I'm aware of that but this isn't the problem. The problem above was that I used SetOutputSetSrc as well as SetOutputResetSrc. I though the one thing would bring the output up high and the other back down again but according to a presentation about HRTIM this isn't the case. Deleting the SetOutputResetSrc solved the issue.

Once again this issue and the documentation coming along with the LL and HAL lib makes me really dislike the LL libs. If you can't find an example that does exactly what you want it's a pain in the lower end to get it to work as the documentation is like:

int counter = 0; // counter

VinM
Associate

Hi @LGard.1​ ,

What you describe seems to be related to preload registers not enabled.

Try to replace

LL_HRTIM_TIM_DisablePreload(HRTIM1, LL_HRTIM_TIMER_A);

By

LL_HRTIM_TIM_EnablePreload(HRTIM1, LL_HRTIM_TIMER_A);

Regards

Thanks for the answer. As mentioned above I got it to work by deleting the SetOutputResetSrc. The project was cancelled due to other reasons and I wouldn't be able to try your suggestions. Thanks for taking the time though!