PWM not returning LOW when timer stopped

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

PWM not returning LOW when timer stopped

Jump to solution
1,143 Views
gary_metalle
Contributor III

I am using PWM2 on iMX.RT to control an RGB LED which is working ok except that when I turn the LED off using the following call, the outputs are randomly HIGH or LOW depending on the PWM value when it was turned off.

PWM_StopTimer(PWM2, kPWM_Control_Module_0 | kPWM_Control_Module_1);

I have had a look on the forum and the closest related question is this one.

I have a feeling it's something to do with the XBAR but I am not sure and am confused why the XBAR should be involved when using the PWM anyway. The PWM SDK example for the iMX.RT1052 is quite lengthy for something I would expect to be quite simple.

Here's the code I use to set up the three channels of the PWM. I have a separate timer that I use for blinking/flashing of the RGB LED and it is there that I call PWM_StartTimer or PWM_StopTimer accordingly.

I basically want to ensure that when the PWM is stopped all outputs are LOW.

    pwm_signal_param_t pwmSignal[3];
    pwm_config_t pwmConfig;
    pwm_fault_param_t faultConfig;
    uint32_t pwmSourceClockInHz;
    uint32_t pwmFrequencyInHz = LED_PWM_FREQUENCY_IN_HZ;

    // set the PWM Fault inputs to a low value
#if 1
    XBARA_Init(XBARA1);
    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault0);
    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault1);
    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault2);
    XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault3);
#endif

    PWM_GetDefaultConfig(&pwmConfig);

    pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;		// use full cycle reload
    pwmConfig.enableDebugMode = true;						// turn on debug mode
    pwmConfig.pairOperation = kPWM_Independent;				// we don't want complementary pair
    pwmConfig.prescale = kPWM_Prescale_Divide_8;			// divide input clock by 8

    /* initialise both of the sub modules that we are going to be using */
    if (PWM_Init(PWM2, kPWM_Module_0, &pwmConfig) == kStatus_Fail)
    {
        LOG_WARN("PWM initialization failed for submodule 0.");
    }

    if (PWM_Init(PWM2, kPWM_Module_1, &pwmConfig) == kStatus_Fail)
    {
        LOG_WARN("PWM initialization failed for submodule 1.");
    }

#if 0
    PWM2->SM[kPWM_Module_0].DISMAP[0] = 0;
    PWM2->SM[kPWM_Module_0].DISMAP[1] = 0;
    PWM2->SM[kPWM_Module_1].DISMAP[0] = 0;
    PWM2->SM[kPWM_Module_1].DISMAP[1] = 0;
#endif

    PWM_FaultDefaultConfig(&faultConfig);

#if 0
    faultConfig.faultLevel = true;
    faultConfig.enableCombinationalPath = false;
#endif

    /* Sets up the PWM fault protection */
    PWM_SetupFaults(PWM2, kPWM_Fault_0, &faultConfig);
    PWM_SetupFaults(PWM2, kPWM_Fault_1, &faultConfig);
    PWM_SetupFaults(PWM2, kPWM_Fault_2, &faultConfig);
    PWM_SetupFaults(PWM2, kPWM_Fault_3, &faultConfig);

#if 1
    /* Set PWM fault disable mapping for channels and submodules we're using */
    PWM_SetupFaultDisableMap(PWM2, kPWM_Module_0, kPWM_PwmA, kPWM_faultchannel_0,
                             kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
    PWM_SetupFaultDisableMap(PWM2, kPWM_Module_0, kPWM_PwmB, kPWM_faultchannel_0,
                             kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
    PWM_SetupFaultDisableMap(PWM2, kPWM_Module_1, kPWM_PwmA, kPWM_faultchannel_0,
                             kPWM_FaultDisable_0 | kPWM_FaultDisable_1 | kPWM_FaultDisable_2 | kPWM_FaultDisable_3);
#endif

    pwmSourceClockInHz = PWM_SRC_CLK_FREQ;

    // configuration for RED component
    pwmSignal[0].level            = kPWM_HighTrue;
    pwmSignal[0].deadtimeValue    = 0;
    pwmSignal[0].faultState       = kPWM_PwmFaultState0;
    pwmSignal[0].pwmChannel = kPWM_PwmA;
    pwmSignal[0].dutyCyclePercent = 0;

    // configuration for GREEN component
    pwmSignal[1].level            = kPWM_HighTrue;
    pwmSignal[1].deadtimeValue    = 0;
    pwmSignal[1].faultState       = kPWM_PwmFaultState0;
    pwmSignal[1].pwmChannel = kPWM_PwmB;
    pwmSignal[1].dutyCyclePercent = 0;

    if (PWM_SetupPwm(PWM2, kPWM_Module_0, pwmSignal, 2, kPWM_CenterAligned, pwmFrequencyInHz, pwmSourceClockInHz) == kStatus_Fail)
    {
        LOG_WARN("PWM setup failed.");
    }

    // configuration for BLUE component
    pwmSignal[2].level            = kPWM_HighTrue;
    pwmSignal[2].deadtimeValue    = 0;
    pwmSignal[2].faultState       = kPWM_PwmFaultState0;
    pwmSignal[2].pwmChannel = kPWM_PwmA;
    pwmSignal[2].dutyCyclePercent = 0;

    if (PWM_SetupPwm(PWM2, kPWM_Module_1, &pwmSignal[2], 1, kPWM_CenterAligned, pwmFrequencyInHz, pwmSourceClockInHz) == kStatus_Fail)
    {
        LOG_WARN("PWM setup failed.");
    }

    /* Set the load okay bit for both submodules to load registers from their buffer */
    PWM_SetPwmLdok(PWM2, kPWM_Control_Module_0 | kPWM_Control_Module_1, true);

    /* Start the PWM generation from Submodules 0 and 1 */
    PWM_StartTimer(PWM2, kPWM_Control_Module_0 | kPWM_Control_Module_1);
Labels (1)
Tags (1)
0 Kudos
Reply
1 Solution
1,114 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I suggest you clear the corresponding bits in PWM OUTEN register, which will disable the PWM signal output, but the PWM module continues to work.

xiangjun_rong_0-1665304693934.png

 

You can use the code to write the register.

PWM2->OUTEN=0x00;

If you connect a external pull-down resistor or set the PWM signal pin as pull-down mode, the pin will be low logic.

Hope it can help you

BR

XiangJun Rong

 

 

View solution in original post

0 Kudos
Reply
4 Replies
1,093 Views
gary_metalle
Contributor III

I think one of the problems I had was that the PWM pin was configured by default for KEEPER when it needed to be PULL. This meant the 100k pull-down wasn't being used. It does pay to be careful when configuring pins because it's not safe to assume that the configuration will be correct if you set a pin to use a peripheral such as PWM, you still have to make sure the other settings are correct. So for I2C etc you will want to make sure you have open drain etc.

0 Kudos
Reply
1,096 Views
gary_metalle
Contributor III

Thanks for taking the time to reply.

Yes that does work. I am surprised the fsl_pwm PWM driver doesn't have a function to set/clear the OUTEN bits if this is something that is obviously important.

I am also confused as to why I needed to add an external pull-down resistor because all the PWM pins have a 100K pull-down enabled in the pin configuration. I am assuming that this pull-down is still used when the pin is configured for PWM and not a general purpose GPIO?

0 Kudos
Reply
1,086 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I suppose that you can set SW_PAD_CTL_PAD_xxx register to enable on-chip pull-down resistor to get low logic of the PWM pin when the PWM outputting function is disabled. But it is a common design to connect pull-down resistor for each PWM pins.

Hope it can help you

BR

XiangJun Rong

0 Kudos
Reply
1,115 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I suggest you clear the corresponding bits in PWM OUTEN register, which will disable the PWM signal output, but the PWM module continues to work.

xiangjun_rong_0-1665304693934.png

 

You can use the code to write the register.

PWM2->OUTEN=0x00;

If you connect a external pull-down resistor or set the PWM signal pin as pull-down mode, the pin will be low logic.

Hope it can help you

BR

XiangJun Rong

 

 

0 Kudos
Reply