Hi,
I have a very very simple requirement but just couldn't seem to find the answer in a reasonable amount of time.
I am using MCUXpresso and the K64 baremetal C drivers supplied. This job is super simple, I just have two PWM's on FTM0.I just want 100Hz PWM with varied high time, super simple motor controller application. For some reason the gap between high pulses varies when i update the PWM using the driver like this instead of just changing the hi time it seems to "start agian" or something and the low time increases between pulses.
I read the reference manual and figered i should set it like this:
//SETUP
ftm_config_t ftmInfo;
ftm_chnl_pwm_signal_param_t ftmParam[2];
PORT_SetPinMux(RC1_M_PORT, RC1_M_PIN, RC1_M_ALT);
PORT_SetPinMux(RC2_M_PORT, RC2_M_PIN, RC2_M_ALT);
ftmParam[0].chnlNumber = (ftm_chnl_t)RC1CH_PWM;
ftmParam[0].level = kFTM_LowTrue;
ftmParam[0].dutyCyclePercent = 0U;
ftmParam[0].firstEdgeDelayPercent = 0U;
ftmParam[0].enableDeadtime = false;
ftmParam[1].chnlNumber = (ftm_chnl_t)RC2CH_PWM;
ftmParam[1].level = kFTM_LowTrue;
ftmParam[1].dutyCyclePercent = 0U;
ftmParam[1].firstEdgeDelayPercent = 0U;
ftmParam[1].enableDeadtime = false;
FTM_GetDefaultConfig(&ftmInfo);
ftmInfo.prescale = kFTM_Prescale_Divide_16;
ftmInfo.pwmSyncMode = (uint32_t)kFTM_SoftwareTrigger;
//I thought this flag hsould tell it to update the PWM when it clocks back over to min and i should get my perfect 2XKhz PWM with varied "high time"
ftmInfo.reloadPoints = kFTM_CntMin;
FTM_Init(FTM0, &ftmInfo);
if(FTM_SetupPwm(FTM0, ftmParam, 2U, kFTM_EdgeAlignedPwm, 100U, TPM_SOURCE_CLOCK) != kStatus_Success)
{
while(1); //Stop for debug
}
FTM_StartTimer(FTM0, kFTM_SystemClock);
FTM_SetDutyCycle(FTM0, (ftm_chnl_t)RC1CH_PWM, 0);
FTM_SetDutyCycle(FTM0, (ftm_chnl_t)RC2CH_PWM, 0);
....
for(;;)
{
//software to do things to the PWM values
FTM_SetDutyCycle(FTM0, (ftm_chnl_t)RC1CH_PWM, new_HighTimePulseValue);
FTM_SetDutyCycle(FTM0, (ftm_chnl_t)RC2CH_PWM, new_LowTimePUlseValue);
FTM_SetSoftwareTrigger(FTM0, true);
}
//I dont want to use a percentage, i want exact numbers for my PWM, so I just made this function which does the same as the drvier FTM_UpdatePwmDutycycle(); function
void FTM_SetDutyCycle(FTM_Type *base, ftm_chnl_t chnlNumber, uint16_t dutyCycle)
{
base->CONTROLS[chnlNumber].CnV = dutyCycle;
}
I just want exactly 100Hz PWM with my custom high time...
Solved! Go to Solution.
You guys need to update your example to either include this as an option, or, just turn it off
I have created this function call to fix the problem of PWM resetting its count.
I cannot really imagine many real examples where you would want your PWM to "start again" randomly or use this feature...
uint16_t FTM_DisableReset(FTM_Type *base)
{
base->SYNCONF &= (~FTM_SYNCONF_SWRSTCNT_MASK);
return base->SYNCONF;
}
Ok, so I have produced the problem using the supplied example driver from MCUXpresso!
To produce the fault and see it on scope simply slow the PWM down to 100hz (and prescaler /16 as required) and you can continually see it break PWM timing
Here is the code and some images showing that it sometimes destroys the PWM and outputs the wrong timing completely
void delay(void)
{
volatile uint32_t i = 0U;
for (i = 0U; i < 10000000U; ++i)
{
__asm("NOP"); /* delay */
}
}
int main(void)
{
/* Init board hardware. */
uint32_t error = 0;
BOARD_InitBootPins();
Global_IOConfig();
BOARD_InitBootClocks();
//TEST START
{
uint8_t prevupdatedDutycycle = 0;
bool brightnessUp = true; /* Indicate LEDs are brighter or dimmer */
ftm_config_t ftmInfo;
uint8_t updatedDutycycle = 0U;
ftm_chnl_pwm_signal_param_t ftmParam[2];
/* Configure ftm params with frequency 24kHZ */
ftmParam[0].chnlNumber = (ftm_chnl_t)RC1CH_PWM;
ftmParam[0].level = kFTM_LowTrue;
ftmParam[0].dutyCyclePercent = 0U;
ftmParam[0].firstEdgeDelayPercent = 0U;
ftmParam[0].enableDeadtime = false;
ftmParam[1].chnlNumber = (ftm_chnl_t)RC2CH_PWM;
ftmParam[1].level = kFTM_LowTrue;
ftmParam[1].dutyCyclePercent = 0U;
ftmParam[1].firstEdgeDelayPercent = 0U;
ftmParam[1].enableDeadtime = false;
PORT_SetPinMux(RC1_M_PORT, RC1_M_PIN, RC1_M_ALT);
PORT_SetPinMux(RC2_M_PORT, RC2_M_PIN, RC2_M_ALT);
/* Print a note to terminal */
PRINTF("\r\nFTM example to output PWM on 2 channels\r\n");
PRINTF("\r\nYou will see a change in LED brightness if an LED is connected to the FTM pin");
PRINTF("\r\nIf no LED is connected to the FTM pin, then probe the signal using an oscilloscope");
/*
* ftmInfo.prescale = kFTM_Prescale_Divide_1;
* ftmInfo.bdmMode = kFTM_BdmMode_0;
* ftmInfo.pwmSyncMode = kFTM_SoftwareTrigger;
* ftmInfo.reloadPoints = 0;
* ftmInfo.faultMode = kFTM_Fault_Disable;
* ftmInfo.faultFilterValue = 0;
* ftmInfo.deadTimePrescale = kFTM_Deadtime_Prescale_1;
* ftmInfo.deadTimeValue = 0;
* ftmInfo.extTriggers = 0;
* ftmInfo.chnlInitState = 0;
* ftmInfo.chnlPolarity = 0;
* ftmInfo.useGlobalTimeBase = false;
*/
FTM_GetDefaultConfig(&ftmInfo);
/* Initialize FTM module */
ftmInfo.prescale = kFTM_Prescale_Divide_16;
FTM_Init(FTM0, &ftmInfo);
// FTM_SetupPwm(FTM0, ftmParam, 2U, kFTM_EdgeAlignedPwm, 24000U, CLOCK_GetFreq(kCLOCK_BusClk));
//My Version
FTM_SetupPwm(FTM0, ftmParam, 2U, kFTM_EdgeAlignedPwm, 100U, TPM_SOURCE_CLOCK);
FTM_StartTimer(FTM0, kFTM_SystemClock);
while (1)
{
/* Delay to see the change of LEDs brightness */
delay();
if (brightnessUp)
{
/* Increase duty cycle until it reach limited value */
if (++updatedDutycycle == 100U)
{
brightnessUp = false;
}
}
else
{
/* Decrease duty cycle until it reach limited value */
if (--updatedDutycycle == 0U)
{
brightnessUp = true;
}
}
// if(prevupdatedDutycycle != updatedDutycycle)
{
prevupdatedDutycycle = updatedDutycycle;
/* Start PWM mode with updated duty cycle */
FTM_UpdatePwmDutycycle(FTM0, (ftm_chnl_t)RC1CH_PWM, kFTM_EdgeAlignedPwm, updatedDutycycle);
FTM_UpdatePwmDutycycle(FTM0, (ftm_chnl_t)RC2CH_PWM, kFTM_EdgeAlignedPwm, updatedDutycycle);
/* Software trigger to update registers */
FTM_SetSoftwareTrigger(FTM0, true);
}
}
}
}
You can see the attached view with examples of this. It happens "a lot". This PWM configuration is dangerous and certainly not obvious this is how the driver works.
How do I make it keep timing, i need that 100Hz to ALWAYS be 100Hz
You guys need to update your example to either include this as an option, or, just turn it off
I have created this function call to fix the problem of PWM resetting its count.
I cannot really imagine many real examples where you would want your PWM to "start again" randomly or use this feature...
uint16_t FTM_DisableReset(FTM_Type *base)
{
base->SYNCONF &= (~FTM_SYNCONF_SWRSTCNT_MASK);
return base->SYNCONF;
}