Quantcast
Channel: Processors forum - Recent Threads
Viewing all articles
Browse latest Browse all 17527

What is the correct way to change the PWM duty cycle?

$
0
0

Looking for suggestions on changing the PWM consistently and glitchlessly.

I need to implement a dimmable LCD backlight on our design.  Using a simple configuration of the eHRPWM I'm able to initialize and run the PWM to control the backlight.  However, I'm not able to change the PWM's duty cycle in a consistent manner.

On start up the PWM is configured to generate a waveform with a 50% duty cycle.  The action qualifier is configured to toggle the PWM signal when the period counter (PRD) equals counter compare A (CMPA) or counter compare B (CMPB).  To change the duty cycle I make only change; write a new value to the counter compare A register.  Here's a simple diagram that shows how I expect this to work.

 

____________1                                   

                            |                                   

                            |_______________2 and 3 

1 - CMPA -- when period counter = CMPA toggle (expect signal to go high)

2 - CMPB -- when period counter = CMPB toggle (expect signal to go low)

3 - PRD count

I see two issues when changing the duty cycle

  • changing CMPA does not always change the duty cycle as expected. Most times increasing CMPA increases the on time (expected behaviour) but occasionally this will reduce the on time.
  • changing the duty cycle is glitchy.  For a short period of time the PWM output produces a signal at a constant level, before the updated PWM waveform appears.  This constant level is visibly noticeable on the LCD.
Enabling shadow register writes provides no improvement. 
Code to change the duty cycle is shown below.  I tried with shadow writes enabled and disabled.  With shadow write enabled I tried loading CMPA when the counter equals zero and the period.

void pwm_change_duty_cycle(uint32_t on_time)
{
    uint32_t on_period; 
    bool ret = 0;

    on_period = (pwm_period_counter * on_time)/100;

    /* Load Compare A value */

    //ret = EHRPWMLoadCMPA(SOC_EHRPWM_0_REGS, on_period, EHRPWM_SHADOW_WRITE_DISABLE,
    // EHRPWM_COMPA_NO_LOAD, EHRPWM_CMPCTL_OVERWR_SH_FL);

    ret = EHRPWMLoadCMPA(SOC_EHRPWM_0_REGS, on_period, EHRPWM_SHADOW_WRITE_ENABLE,
               EHRPWM_COMPA_LOAD_COUNT_EQUAL_PERIOD, EHRPWM_CMPCTL_OVERWR_SH_FL);

}

Code to initialize and start PWM is shown below:

uint32_t clock_div_val = 0x700;
uint32_t pwm_period_counter = 1820;

void pwm_start(uint32_t pwm_module_freq)
{

    /* TimeBase configuration */
    /* Configure the clock frequency */
    EHRPWMTimebaseClkConfig(SOC_EHRPWM_0_REGS, pwm_module_freq/clock_div_val, pwm_module_freq);

    /* Configure the period of the output waveform */
    EHRPWMPWMOpFreqSet(SOC_EHRPWM_0_REGS, pwm_module_freq/clock_div_val,
    (pwm_module_freq/clock_div_val)/pwm_period_counter, EHRPWM_COUNT_UP, EHRPWM_SHADOW_WRITE_DISABLE);

    /* Disable synchronization*/
    EHRPWMTimebaseSyncDisable(SOC_EHRPWM_0_REGS);

    /* Disable syncout*/
    EHRPWMSyncOutModeSet(SOC_EHRPWM_0_REGS, EHRPWM_SYNCOUT_DISABLE);

    /* Configure the emulation behaviour*/
    EHRPWMTBEmulationModeSet(SOC_EHRPWM_0_REGS, EHRPWM_STOP_AFTER_NEXT_TB_INCREMENT);

   /* Configure Counter compare sub-module */
   /* Load Compare A value */
   EHRPWMLoadCMPA(SOC_EHRPWM_0_REGS, (pwm_period_counter/2), EHRPWM_SHADOW_WRITE_DISABLE,
                     EHRPWM_COMPA_NO_LOAD, EHRPWM_CMPCTL_OVERWR_SH_FL);

    /* Load Compare B value */
   EHRPWMLoadCMPB(SOC_EHRPWM_0_REGS, pwm_period_counter, EHRPWM_SHADOW_WRITE_DISABLE,
                     EHRPWM_COMPB_NO_LOAD, EHRPWM_CMPCTL_OVERWR_SH_FL);

   /* Configure Action qualifier */
   /* Toggle when CTR = CMPA OR CMPB */
   EHRPWMConfigureAQActionOnA(SOC_EHRPWM_0_REGS, EHRPWM_AQCTLA_ZRO_DONOTHING, EHRPWM_AQCTLA_PRD_DONOTHING,
              EHRPWM_AQCTLA_CAU_EPWMXATOGGLE, EHRPWM_AQCTLA_CAD_DONOTHING, EHRPWM_AQCTLA_CBU_EPWMXATOGGLE,
              EHRPWM_AQCTLA_CBD_DONOTHING, EHRPWM_AQSFRC_ACTSFA_DONOTHING);

   /* Bypass dead band sub-module */
   EHRPWMDBOutput(SOC_EHRPWM_0_REGS, EHRPWM_DBCTL_OUT_MODE_BYPASS);

   /* Disable Chopper sub-module */
   EHRPWMChopperDisable(SOC_EHRPWM_0_REGS);

   /* Disable trip events */
   EHRPWMTZTripEventDisable(SOC_EHRPWM_0_REGS, EHRPWM_TZ_ONESHOT);
   EHRPWMTZTripEventDisable(SOC_EHRPWM_0_REGS, EHRPWM_TZ_CYCLEBYCYCLE);

   /* Event trigger */
   /* Generate interrupt every 3rd occurance of the event */
   EHRPWMETIntPrescale(SOC_EHRPWM_0_REGS, EHRPWM_ETPS_INTPRD_THIRDEVENT);
   /* Generate event when CTR = CMPB */
   EHRPWMETIntSourceSelect(SOC_EHRPWM_0_REGS, EHRPWM_ETSEL_INTSEL_TBCTREQUCMPBINC);
   /* Enable interrupt */
   EHRPWMETIntEnable(SOC_EHRPWM_0_REGS);

   /* Disable High resolution capability */
   EHRPWMHRDisable(SOC_EHRPWM_0_REGS);

}


Viewing all articles
Browse latest Browse all 17527

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>