LPC844 SCTimer/PWM frequency variation leads to signal glitches

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC844 SCTimer/PWM frequency variation leads to signal glitches

Jump to solution
1,226 Views
andre_rex
Contributor II

Dear community,

we've implemented a small companion application for driving/managing a bunch of switching relays applying safety checks regarding weld contact and valid switch combination. This application is ported to an LPC844. If activated each relay coil is asserted with a 50% PWM signal at 17kHz (after asserting 100% for 200ms).

To improve EMC performance we're trying to add some kind of spread spectrum to this PWM signal to reduce the 17kHz harmonics' peaks in EM spectrum. As this is not supported by the HW I tried to achieve this by periodically modifying the PWM period with a small offset within the SCTimer peripheral but get results that I was not expecting and which I have no explanation for it.

 

How it is set up

Each relay's coil is connected to a dedicated output pin (via MOSFET stage). Initially all these pins are muxed to the GPIO peripheral driving them low. Additionally the SCTimer peripheral is initialized (OUT0, OUT1, OUT2) configuring a PWM frequency of 17kHz via SCTIMER_SetupPwm() call:

 

static Relay_sctPwmData_t Relay_asctPwmChannels[] = { ... }
static uint8_t u8PWMDutyCycle = 50U;
static uint32_t u32PwmFreq = 17000U;
// ...
for (uint32_t u32PwmCh=0; u32PwmCh < 3; u32PwmCh++)
{
  Relay_sctPwmData_t *psctPwmSignal = &Relay_asctPwmChannels[u32PwmCh];
  sctimer_pwm_signal_param_t sctimerPwmParams;

  // kSCTIMER_Out_0,kSCTIMER_Out_1 or kSCTIMER_Out_2
  sctimerPwmParams.output           = psctPwmSignal->eSCTimerOut; 
  sctimerPwmParams.level            = kSCTIMER_HighTrue;
  sctimerPwmParams.dutyCyclePercent = u8PWMDutyCycle;

  uint32_t u32Freqency = CLOCK_GetFreq(kSCT_Clk_From_SysPll);
  // Create PWM signal, the returned event number corresponds to the PWM
  // period event (pulse period would be event+1)
  status_t status = SCTIMER_SetupPwm(SCT0, &sctimerPwmParams,
                                     SCTIMER_EdgeAlignedPwm,
                                     u32PwmFreq, u32Freqency,
                                     &psctPwmSignal->u32EventNumberOutput);
  // Store the calculated timer period value for spread spectrum functionality
  psctPwmSignal->u32TimerPeriod = SCT0->MATCHREL[psctPwmSignal->u32EventNumberOutput];
  // ...
}

 

If activating a relay its GPIO is set high and after a timeout the pin is swapped to the according SCTimer output resulting in a 50% PWM signal.

 

Spread spectrum modification

To achieve the "spread spectrum" I periodically add a slightly increasing offset to the previously stored "u32TimerPeriod" value and store it in the SCTimer output's corresponding MATCHREL register (and at a maximum steadily decreasing the offset again). This happens at a 1ms interval and is applied as follows:

 

uint32_t u32TimerPeriodNew = psctPwmSignal->u32TimerPeriod + i32Offset
uint32_t u32TimerPulsePeriodNew;
// For 100% dutycyle, make pulse period greater than period so the event will never occur
if (u8PWMDutyCycle >= 100U)
  u32TimerPulsePeriodNew = u32TimerPeriodNew + 2U;
else
  u32TimerPulsePeriodNew = (uint32_t) (((uint64_t) u32TimerPeriodNew * u8PWMDutyCycle) / 100U);

// Update timer PWM period
SCT0->MATCHREL[psctPwmSignal->u32EventNumberOutput] = u32TimerPeriodNew;
// Update timer PWM pulse period (which is derived from PWM period with applied duty cycle)
SCT0->MATCHREL[psctPwmSignal->u32EventNumberOutput+1] = u32TimerPulsePeriodNew;

 

 

What is observed

This basically results in a wobbling PWM frequency BUT also shows arbitrary distributed signal dropouts of one or more periods. Following image shows the traces of two signals generated from SCT_OUT0 (blue) and SCT_OUT1 (yellow)

DSO.png

UM11029 chapter 21 states that an SCTimer event's MATCH register is reloaded with the value of its corresponding MATCHREL each new counter cycle. From this rare information I'm not able to create any hypothesis what could lead to that behavior. What I'm curious about is that this rather special use case matches pretty much the common LED "fading" application which I would expect to work flawlessly (with the difference that here I also modify the overall PWM period and not just the PWM pulse period value).

I'd rather appreciate of anyone is able to contribute any hints how to address this issue.

 

Kind regards

André

0 Kudos
Reply
1 Solution
1,158 Views
andre_rex
Contributor II

Hi Alice,

thanks for your response. Unfortunately stopping the timer just increases the "glitches" so it actually makes it even worse. Although I actually need to modify the period (spreading the PWM frequency peaks in EM spectrum to a wider bandwidth) I also tried to modify the duty cycle via SCTIMER_UpdatePwmDutycycle() instead. The effect is the same: There are notable glitches.

During further research and review of similar examples I stumbled upon the "NORELOAD" flag in SCTimer's CONFIG register. Enabling this flag prior to modifying the event's MATCHREL register ("SCT0->CONFIG |= SCT_CONFIG_NORELOAD_L_MASK;") and disabling it afterwards seems to make the glitches disappear.

An additional explanation as it not noticeable from my example: I need to modify three different PWM outputs (each utilizing two SCTimer events): So the "modification" actually is a for-loop iterating over those three outputs each performing the code shown in my example. Surrounding this loop with the NORELOAD-flag enable/disable fully solved my issue.


Regards

André

View solution in original post

0 Kudos
Reply
2 Replies
1,173 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello @andre_rex 

- Could you please try to stop the SCTIMER, then change the PWM frequency and check if it still has glitches?
 
- Yes, the LED "fading" application uses PWM duty - cycle changing. If it can meet your requirements, I recommend that you change the duty cycle instead of the period. There is a sctimer_pwm_with_dutycyle_change example under the SDK.

 
BR
Alice
 
0 Kudos
Reply
1,159 Views
andre_rex
Contributor II

Hi Alice,

thanks for your response. Unfortunately stopping the timer just increases the "glitches" so it actually makes it even worse. Although I actually need to modify the period (spreading the PWM frequency peaks in EM spectrum to a wider bandwidth) I also tried to modify the duty cycle via SCTIMER_UpdatePwmDutycycle() instead. The effect is the same: There are notable glitches.

During further research and review of similar examples I stumbled upon the "NORELOAD" flag in SCTimer's CONFIG register. Enabling this flag prior to modifying the event's MATCHREL register ("SCT0->CONFIG |= SCT_CONFIG_NORELOAD_L_MASK;") and disabling it afterwards seems to make the glitches disappear.

An additional explanation as it not noticeable from my example: I need to modify three different PWM outputs (each utilizing two SCTimer events): So the "modification" actually is a for-loop iterating over those three outputs each performing the code shown in my example. Surrounding this loop with the NORELOAD-flag enable/disable fully solved my issue.


Regards

André

0 Kudos
Reply