Because of the Thanksgiving holiday in the U.S., TI E2E™ design support forum responses may be delayed from November 25 through December 2. Thank you for your patience.

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.

HAL_setTrigger() clarification

When calculating the next trigger point for the Start-of-Conversion in the MainISR, I'd like a couple clarifications on a couple of things. I've also reading the spruge9e-datasheet for the ePWM-module, but I'd still like a couple explanations.

Does the InstaSPIN library use center-aligned (dual edge) PWM pulse as a default?

Difference between CMPA (counter-compare A register) and CMPAM (counter-compare A register mirror)? Is it that CMPAM reads the currently active CMPA value, which is then updated to the earlier written CMPA value in HAL_writePwmData() when the counter = 0?

If shadow registers are enabled, then they act as a buffer register from which to load the new value to actual register at counter = 0? If shadow registers are disabled, then the new value written for example to CMPA takes effect immediately, possibly causing a glitch depending on the time of write?

Based on these I added some comments to explain the actions taken in HAL_setTrigger()

//! \brief     Set trigger point in the middle of the low side pulse
//! \param[in] handle    The hardware abstraction layer (HAL) handle
//! \param[in] ignoreShunt  The low side shunt that should be ignored
//! \param[in] midVolShunt  The middle length of output voltage
static inline void HAL_setTrigger(HAL_Handle handle,const SVGENCURRENT_IgnoreShunt_e ignoreShunt,
									const SVGENCURRENT_VmidShunt_e midVolShunt)
{
  HAL_Obj *obj = (HAL_Obj *)handle;

  PWM_Obj *pwm1 = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
  PWM_Obj *pwm2 = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
  PWM_Obj *pwm3 = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
  PWM_Obj *pwm;

  uint16_t nextPulse1 = (pwm1->CMPA + pwm1->CMPAM) / 2; // nextPulsex = ((to be written CMPA value, when counter = 0) + (currently active CMPA value)) / 2
  uint16_t nextPulse2 = (pwm2->CMPA + pwm2->CMPAM) / 2;
  uint16_t nextPulse3 = (pwm3->CMPA + pwm3->CMPAM) / 2;

  if(ignoreShunt == use_all) // if we can use all shunts, then figure out which ePWM-module has the shortest LOW-pulse and use that to set the time so all 3 outputs are LOW when we trigger ADC SoC?
    {
      if((nextPulse1 <= nextPulse2) && (nextPulse1 <= nextPulse3))
        {
          pwm = pwm1;
        }
      else if((nextPulse2 <= nextPulse1) && (nextPulse2 <= nextPulse3))
        {
          pwm = pwm2;
        }
      else
        {
          pwm = pwm3;
        }
    }
  else // if we can't use all 3 shunts, but only 2 at high duty cycles, then figure out again which ePWM-module to base the SoC timing
  {
	  if(midVolShunt == Vmid_a)
	  {
		  pwm = pwm1;
	  }
	  else if(midVolShunt == Vmid_b)
	  {
		  pwm = pwm2;
	  }
	  else
	  {
		  pwm = pwm3;
	  }
  }

  if(pwm->CMPAM >= (pwm->CMPA + pwm->DBFED))
  {
	  pwm1->CMPB = (pwm->CMPAM - (pwm->CMPA + pwm->DBFED)) / 2 + 1;  //Here I get a bit confused why are we using the CMPAM register if it holds (cont below.)
	  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBDecr);  // the currently active CMPA to calculate the new trigger point for ADC SoC?
  }
  else
  {
	  pwm1->CMPB = ((pwm->CMPA + pwm->DBFED) - pwm->CMPAM ) / 2 + 1;
	  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBIncr);
  }

  • Simo,

    I don't have all the answers to your questions however I can answer some.

    Simo Sihvonen said:

    Difference between CMPA (counter-compare A register) and CMPAM (counter-compare A register mirror)? Is it that CMPAM reads the currently active CMPA value, which is then updated to the earlier written CMPA value in HAL_writePwmData() when the counter = 0?

    Correct, CMPAM shows the active value while CMPA show the last value written to CMPA. When using shadowing CMPA will be updated depending on the value in CMPCTL[LOADAMODE]...CTR = 0, CTR = PRD, etc. the details can be found in the document you referenced.

    Simo Sihvonen said:

    If shadow registers are enabled, then they act as a buffer register from which to load the new value to actual register at counter = 0? If shadow registers are disabled, then the new value written for example to CMPA takes effect immediately, possibly causing a glitch depending on the time of write?

    Again it may or may not load at counter = 0, that depends on the value of CMPCTL[LOADAMODE]. Yes, if you don't use Shadow registers, glitching may occur. Longer than expected low times or high times may happen as well.

    Regards,
    Cody

  • I also figured out that it uses center-aligned PWM pulse from these two lines in the HAL_setTrigger function:

    PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBDecr);

    PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBIncr);

    Other sets the SoC on the timer's up count: PWM_SocPulseSrc_CounterEqualCmpBIncr

    and the other on the down count:                    PWM_SocPulseSrc_CounterEqualCmpBDecr

  • Simo,

    Great! Does that answer all of you questions about this?(please mark the helpful posts with the "verify answer" button)

    If you have another question about something else, feel free to start another thread.

    Regards,
    Cody

  • Does the InstaSPIN library use center-aligned (dual edge) PWM pulse as a default?
    A: It's count-up-and-down mode and shadow mode for CMPA in default, the use center-aligned (dual edge) as you mentioned. The CMPA controls both PWM_H and PWM_L output for the PWM is complement mode with deadband, and CMPA will be load from CMPAM when time base counter is equal to 0.
    Calculate CMPB which uses immediate mode in Hal_setTigger, and the CMPB only is used for trig ADC, not control PWM output.
  • I did understand the CMPB for the ePWM1 was used as the trigger for the start-of-conversion for the whole ADC sequence.

    The one last thing I'd like to hear is what is logic for calculating the actual trigger point in the second to last if() statement.

      if(pwm->CMPAM >= (pwm->CMPA + pwm->DBFED))
      {
    	  pwm1->CMPB = (pwm->CMPAM - (pwm->CMPA + pwm->DBFED)) / 2 + 1;
    	  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBDecr);
      }
      else
      {
    	  pwm1->CMPB = ((pwm->CMPA + pwm->DBFED) - pwm->CMPAM ) / 2 + 1;
    	  PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBIncr);
      }

    It seems a bit weird to use the CMPAM and the upcoming CMPA + DBFED to set the trigger point and not just the CMPA + DBFED value?

    I made a little diagram to show how the trigger points behave in each of the if() case statements.

    if (CMPAM >= (CMPA + DBFED))

    if (CMPAM < (CMPA + DBFED)) (the else() case)

    Point is, why not just use a simpler CMPB = CMPA + DBFED + "small constant to add a little bit of delay" and set it on the rising count? or just set CMPB = TBPRD to be right in the center? Why have this weird calculation for it, what are the benefits of this?

    Actually, looking at the diagrams. Why are the trigger points on the around the counter zero side?

  • I now understand why the trigger points are around the zero counter point.

    I took a closer look the HAL_writePwmData and I now see that TI uses the reverse logic levels for their PWM outputs. AKA high MOSFET output starts LOW (counter = 0) and at CMPAM goes HIGH.

    The calculations in HAL_writePwmData produce a value between IQ(0.0) and IQ(1.0) and then multiply it with the PERIOD register value to scale it and then write it to the CMPA. gPwmData->Tabc.value[cnt] contains values between IQ(-0.5) and IQ(0.5), but the calculations cause the IQ(-0.5) input to become IQ(1.0) and IQ(0.5) becomes IQ(0.0). Logically thinking if the gPwmData->Tabc.value[cnt] value is near the IQ(-0.5) it would mean you would want the low side mosfet to be switched on all the time, but considering that HAL_writePwmData would then set the CMPA = PERIOD and that must mean that the positive mosfet output would need start LOW for this to be true.

    My earlier question still stands though. Why have the weird calculation in HAL_setTrigger for the trigger point, if you could just set it to counter zero?

  • It's for over modulation to sample the currents easily, you can refer to lab10a of InstaSPIN lab guide to understand detailed information.

  • Oh, I had forgotten to look in the instaspin_labs.pdf guide, thanks!

    I'll refer to it to figure out the logic for the trigger point timing.

    And with that I feel like I've gotten my answers I seeked. Thanks for the help guys!