This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Stop PWM

Given this code for a simple PWM:

  EPwm1Regs.TBPRD = PWM_TIME_50_USEC;
  EPwm1Regs.CMPA.half.CMPA = PWM_TIME_25_USEC;
  EPwm1Regs.TBPHS.all = 0;
  EPwm1Regs.TBCTR = 0;
  EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
  EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
  EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
  EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
  EPwm1Regs.TBCTL.bit.HSPCLKDIV = DIV_CLK_1;
  EPwm1Regs.TBCTL.bit.CLKDIV = DIV_CLK_1;
  EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
  EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_SHADOW;
  EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
  EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;

how does one stop the PWM?  After running for a while, I want the PWM stopped by command when the PWM pulse goes to zero.

  • I believe there are sevral ways to "stop" PWM but the most appropriate method will depend on the required state of the PWM outputs once the PWM is stopped.

  • There should be an easy way to stop the PWM … something other than interrupting it by switching it from PWM mode to GPIO mode.  What are the ways?

  • Well ePWM manual is the best source for this information but as I said the method will depend on the desired state of the PWM pins once you "stop" PWM operation. The best method is to use trip zone function to "stop" all or selected PWM outputs. The other methods can be to stop the clock to the timer (may not be desirable in various applications) , putting compare value such that the output becomes zero or high which again may not be applicable in many systems. Most likely you will find trip zone as the best method - We have systems where we turn off PWM outputs using trip zone functions.

  • I've read the manual ... don't see an answer.  I posted the code I'm using.  Please provide an example. I want to manually (code wise) shut down the PWM when it is low, and later, start up the PWM.

  • I agree with Arefeen.  Using the trip is the graceful way to shutdown the ePWM.   There is a trip example in the header files and peripheral examples (aka device_support) for each family.  You can tie a GPIO back into a trip input or you could force the trip in software.

    Regards,

    -Lori

     

  • So the only way to do this is to use an interrupt?

    I am writing code for an F2802 where the PWM is created on the GPIO0 / EPWM1A port.  How would I invoke a trip zone interrupt on this port?  An example would be nice.

  • Clyde Eisenbeis said:

    So the only way to do this is to use an interrupt?

    I am writing code for an F2802 where the PWM is created on the GPIO0 / EPWM1A port.  How would I invoke a trip zone interrupt on this port?  An example would be nice.

    You can select if you want to service the associated ISR or not.  The trip signal goes directly to the ePWM module and forces it high/low/tristate as configured.  There is a trip example in the device support.   In this case the associated interrupt is serviced, but it doesn't have to be.   There is also a software force for the trip.

    Regards,

    Lori

     

  • For 2802x the device support can be downloaded here:

    http://focus.ti.com/docs/toolsw/folders/print/sprc191.html

    Then have a look at the example in this directory:

    C:\tidcs\c28\DSP280x\v170\DSP280x_examples_ccsv4\epwm_trip_zone

    Thank you

    Lori

     

  • The example appears to apply only to Tz ports, not to GPIO0 / EPWM1A on the F2802. 

  • Clyde Eisenbeis said:
    The example appears to apply only to Tz ports, not to GPIO0 / EPWM1A on the F2802. 

    Clyde,

    The example uses the TZ pin as a source for the trip event.  When the trip event is detected, both the ePWM1 and ePWM2 outputs will react to it and go into the state configured (high/low/tristate).    So, as an example, in your application, the TZ pin could be tied externally to another GPIO.  Your application pulls the GPIO low (which in turn pulls the TZ input low) and the EPWMs will react as specified.

    Cheers,

    Lori

  • By "tying externally" do you mean soldering a wire on the PCB from the EPWM1A port to a TZ port?  I am working with an existing assy.  I don't have the option of adding wires or redirecting the signals to different ports. 

  • Clyde Eisenbeis said:

    By "tying externally" do you mean soldering a wire on the PCB from the EPWM1A port to a TZ port?  I am working with an existing assy.  I don't have the option of adding wires or redirecting the signals to different ports. 

    Hi Clyde,

    Yes, that is what I meant.  It would allow one signal to go to all of the ePWM modules at once.  

    The alternative if you can not connect pins externally is to use a software force of the trip.  This can be done using the TZFRC register but it will have to be done for each ePWM module.  

    Regards,

    -Lori

     

  • Not sure what is meant by each ePWM module.  Here is the code I have:

    //-----------------------------------------------------------------------------
    void gInitPwm(void)
    {
      EALLOW;
      PieVectTable.EPWM1_TZINT = &IsrPwm1;
      EDIS;
      IER |= M_INT2;
      PieCtrlRegs.PIEIER2.bit.INTx1 = 1;

      EPwm1Regs.TBCTL.bit.FREE_SOFT = 0;

      EPwm1Regs.TBPRD = PWM_TIME_50_USEC;
      EPwm1Regs.CMPA.half.CMPA = PWM_TIME_25_USEC;
      EPwm1Regs.TBPHS.all = 0;
      EPwm1Regs.TBCTR = 0;

      EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
      EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
      EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
      EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
      EPwm1Regs.TBCTL.bit.HSPCLKDIV = DIV_CLK_1;
      EPwm1Regs.TBCTL.bit.CLKDIV = DIV_CLK_1;

      EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
      EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_SHADOW;

      EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
      EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    }//gInitPwm
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    void gEnableDisablePwm(char cFlagEnableDisable)
    {
      switch(cFlagEnableDisable)
      {
        case gPWM_ENABLE:
          EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;
          break;
        case gPWM_DISABLE:
          EPwm1Regs.TZFRC.bit.OST = 1;
          break;
      }
    }//gEnableDisablePwm
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    interrupt void IsrPwm1(void)
    {
      EPwm1Regs.TBCTL.bit.FREE_SOFT = 0;
      EPwm1Regs.TZCLR.bit.OST = 1;
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
    }//IsrPwm1
    //-----------------------------------------------------------------------------

    The intent is to start with the PWM disabled ... start the PWM with the FREE_SOFT setting ... stop it by forcing an interrupt via TZFRC ... have the interrupt stop the PWM and clear appropriate flags.  Does this look correct?

     

  • Clyde,

    I think you missunderstood the function of the FREE_SOFT register. The settings you do in this register only apply when you are debugging the target. As soon as you are running let's say into a breakpoint, the ePWM module performs according to the setting in the FREE_SOFT register. But the reg is useless if you want to start/stop PWM.

    Clyde Eisenbeis said:
    //-----------------------------------------------------------------------------
    void gEnableDisablePwm(char cFlagEnableDisable)
    {
      switch(cFlagEnableDisable)
      {
        case gPWM_ENABLE:
          EPwm1Regs.TBCTL.bit.FREE_SOFT = 2;
          break;
        case gPWM_DISABLE:
          EPwm1Regs.TZFRC.bit.OST = 1;
          break;
      }
    }//gEnableDisablePwm
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    interrupt void IsrPwm1(void)
    {
      EPwm1Regs.TBCTL.bit.FREE_SOFT = 0;
      EPwm1Regs.TZCLR.bit.OST = 1;
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
    }//IsrPwm1
    //-----------------------------------------------------------------------------

    I suggest you to change your code as follows

     

    void gEnableDisablePwm(char cFlagEnableDisable)
    {
      switch(cFlagEnableDisable)
      {
        case gPWM_ENABLE:
          EALLOW;
          EPwm1Regs.TZCLR.bit.OST = 1;
          EDIS;
          break;
        case gPWM_DISABLE:
          EALLOW;
          EPwm1Regs.TZFRC.bit.OST = 1;
          EDIS
          break;
      }
    }//gEnableDisablePwm

    Then you can call the function "gEnableDisablePwm(gPWM_ENABLE)" to enable the PWM and "gEnableDisablePwm(gPWM_DISABLE)" to disable it.

    As far as I understand your requirements you don't need to have an ISR since you control the TZ within your application.

    BR Andreas

  • Unfortunately, sometimes the PWM stops when it is high ... needs to stop when it is low. 

  • Clyde,

    Do you have a solution based on the suggestions alread provided?

    In reviewing the TMS320x280x, 2801x, 2804x Enhanced Pulse Width Modulator (ePWM) Module RG (Rev. F) , there is also a software triggered Trip Zone event which could be used to force the PWM outputs low.  Take a look at Section 2.7 of the above reference guide.  There is a bullet in Section 2.7.1 that indicates a software-forced tripping is supported.  Table 2-18 indicates the possible configurable actions upon a trip event, including forcing the EPWMxA and EPWMxB outputs to a low state.

  • No solution.  Have yet to see specific code that would accomplish what is needed.

  • What have you tried so far with respect to the various suggestions?

    What results did you get?

  • I posted the code.  What changes / additions to the code do you recommend?

  • I realize you have posted your code.

    However, andreas has provided suggestion.  Did you implement it?  If so, what results did you achieve?

  • Read my response posted on 28 Feb 2011 at 9:02 am. 

  • Clyde Eisenbeis said:

    Unfortunately, sometimes the PWM stops when it is high ... needs to stop when it is low. 

    Clyde,

    You can define the action that the trip event will force - it can force each PWM output high, low or tristate.

    Or is the issue you only want to stop the PWM when it is already low as the result of a compare action?  If so you could read the state of the pin in the GPIO DAT register before forcing the trip.  Or depending on your waveform you could possibly use the direction (in up/down count) to determine if the PWM can be stopped. 

    Regards,

    Lori

     

  • What command forces that action to a high or low state?  Do you mean changing it from PWM mode to GPIO mode? 

  • This is a configuration of the Trip Zone sub-module of the ePWM.  This sub-module is described in Section 2.7 of the ePWM Users Guide (SPRU791).  Table 2-18 indicate the configuration register bit field that determines the "action" when a trip request is generated.  This action is what defines the behavior of the PWM output.  Figure 2-36 provides a visual illustration of the structure of the Trip Zone sub-module.

    Those bit fields are a part of the Trip Zone sub-module control and status registers which are described in Section 4.6.

    Specifically, in the Trip-Zone Control Register (TZCTL) described in Figure 4-19 and Table 4-19.

  • That, combined with Andreas reply, works.  Here is the final code:

    //-----------------------------------------------------------------------------
    #define DIV_CLK_1   0
    #define DIV_CLK_10  5

    #define TRIP_ZONE_CLEAR_TRIP  1
    #define TRIP_ZONE_FORCE_TRIP  1

    #define TRIP_ZONE_OUTPUT_HIGH  1
    #define TRIP_ZONE_OUTPUT_LOW   2
    #define TRIP_ZONE_OUTPUT_FLOAT 3
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    interrupt void IsrPwm1(void)
    {
      EPwm1Regs.TZCLR.bit.OST = TRIP_ZONE_CLEAR_TRIP;
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
    }//IsrPwm1
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    void gInitPwm(void)
    {
      EALLOW;
      PieVectTable.EPWM1_TZINT = &IsrPwm1;
      EDIS;

      IER |= M_INT2;
      PieCtrlRegs.PIEIER2.bit.INTx1 = 1;

      EPwm1Regs.TBPRD = PWM_TIME_50_USEC;
      EPwm1Regs.CMPA.half.CMPA = PWM_TIME_25_USEC;
      EPwm1Regs.TBPHS.all = 0;
      EPwm1Regs.TBCTR = 0;

      EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
      EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
      EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
      EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
      EPwm1Regs.TBCTL.bit.HSPCLKDIV = DIV_CLK_1;
      EPwm1Regs.TBCTL.bit.CLKDIV = DIV_CLK_1;

      EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
      EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_SHADOW;

      EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
      EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    }//gInitPwm
    //-----------------------------------------------------------------------------
    //-----------------------------------------------------------------------------
    void gSetPwmOutput(char cPwmOutput)
    {
      EALLOW;

      EPwm1Regs.TZFRC.bit.OST = TRIP_ZONE_FORCE_TRIP;
      switch(cPwmOutput)
      {
      case gPWM_LOW_OUTPUT:
        EPwm1Regs.TZCTL.bit.TZA = TRIP_ZONE_OUTPUT_LOW;
        break;
      case gPWM_PWM_OUTPUT:
        EPwm1Regs.TZCTL.bit.TZA = TRIP_ZONE_OUTPUT_FLOAT;
        break;
      case gPWM_HIGH_OUTPUT:
        EPwm1Regs.TZCTL.bit.TZA = TRIP_ZONE_OUTPUT_HIGH;
        break;
      }

      EDIS;
    }//gSetPwmOutput
    //-----------------------------------------------------------------------------