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.

• TI Thinks Resolved

TMS320F28379D: High-Resolution PWM Control mismatch with SFO() result

Part Number: TMS320F28379D

Using LaunchPad for experiments and existing Code as development starting point.

SFO() works, value written into EPwm1Regs.HRMSTEP.bit.HRMSTEP is 63; this is reasonably close to typical value of 67 based on PWM Clock 100MHz and typical MEP Step of 150pSec.

When utilizing Auto-Conversion (EPwm1Regs.HRCNFG.bit.AUTOCONV = 1), the resulting Voltage Command is clearly affected by fractional value in EPwm1Regs.CMPA.bit.CMPAHR, however the voltage is not continuous and has discontinuities close to points where the fraction is zero.

When avoiding Auto-Conversion (EPwm1Regs.HRCNFG.bit.AUTOCONV = 0) and calculating the value to enter into the High-Resolution Register CMPAHR, it is POSSIBLE to get Voltage Command that is continuous and consistent with expectation; however, the values that are entered into the CMPAHR Register are TWICE what is expected using the result from the SFO() Function. To illustrate:
1. DC Buss Voltage ~50VDC;
2. PWM Clock is 100MHz;
3. PWM Up-Down Counting, Period is 5,000, for a Triangular-Wave at 10kHz;
4. For Zero voltage between Motor Phases, the command at each PWM Output is 2,500;
5. To get 20mV between two Phases, one Phase would have EPwm1Regs.CMPA.bit.CMPA = 2,501 and the other Phase EPwm2Regs.CMPA.bit.CMPA = 2,499; for 40mV between two Phases set the values to 2,502 and 2,498; etc.
6. To get 30mV between two Phases, one Phase should have "1.5 PWM Counts" and the other Phase should have "-1.5 PWM Count"; represent that in "fractional notation", "EPwm1Regs.CMPA.bit.CMPA = 2,501.5" and "EPwm2Regs.CMPA.bit.CMPA = 2,498.5";
7. The values in EPwm1Regs.CMPA.bit.CMPAHR and EPwm2Regs.CMPA.bit.CMPAHR are expected to be about 8,192 in both (63 / 2 * 256);
8. However, these values cause INCORRECT Voltage between the two Phases, and the situation gets worse as different voltage commands are attempted, such as 20.5mV or 39mV (close to zero fraction points);
9. When calculating the fractional value as if the MSTEP calculation is 2 * 63 = 126, the result is continuous and accurate; thus the value of both CMPAHR Registers are 0.5 * 126 * 256 = 16,128.
10. It seems that the Auto-Conversion process gives the incorrect result BECAUSE it relies on the incorrect Micro-Step resolution as calculated by the SFO() Function.

What am I missing?

Another question: In the setup, only setting Rising-Edge-Positioning seems to have any effect. When setting "EPwmxRegs.HRCNFG.bit.EDGMODE = 2" there seems to be no effect of any value written into CMPAHR AT ALL.

Thanks, Alon Harpaz

• Hi,

First of all thank you for posting a query with a very detailed analysis.

I presume, the value returned by SFO() in the EPwm1Regs.HRMSTEP.bit.HRMSTEP register would be accurate.

One way to check this would be to focus on just one of the PWMs.
Say, set the EDGEMODE to rising edge delay and set EPwm1Regs.CMPA.bit.CMPA = 2,501 measure the PWM output duty cycle.
Now change CMPA:CMPAHR = 2,501.5 and measure the PWM duty cycle.
Does the change in the duty cycle correspond to the value updated in CMPAHR?
If so, then the calculated HRMSTEP is accurate.

For your second question,
Since you are trying to use dual edge control (both rising and falling edge) - can you enable HRPE? You can use it with TBPRDHR=0 since you are not trying to change the frequency. This should have the desired effect on both edges.

• In reply to Subrahmanya:

Hello Subrahmanya,

Some of the questions that you asked are already answered in my original post...

To ensure full coverage of all possible configurations, I conducted several experiments, each with a different configuration.  The results are listed below.

In general:

1.  Since I have no access to a high-speed Oscilloscope, I monitored the Output using a Resistor-Capacitor Circuit that provided aggressive filtering of the PWM Voltage, measuring the voltage across the Capacitor only.  Using a 3.75 Digit DVM, I was able to monitor the Voltage at 0.1mV resolution; out of a 40VDC Buss, this is 1 / 400,000 resolution.

2.  PWM Clock is 100MHz, the Period Counter counts Up-Down (no Saw-Tooth waveform for PWM Control); Period is 5,000.

3.  Phase A is kept at 50% Duty-Cycle, Phase B is manipulated using both CMPA and CMPAHR; RC Circuit is connected between Phase A and Phase B.

4.  Voltage Command is given writing to motor1.VqTesting; CMPA and CMPAHR of all three PWM Outputs are monitored.

Experiments:

A.  Direct calculation of CMPAHR value, no High-Res. Period Enable:

EPwmnRegs.HRPCTL.bit.HRPE = 0

u16_HrStep = 126; // internal Variable to be used in HRPWM Calculations, value is twice the nominal estimate

PWM Calclations:
motor->PwmARegs->CMPA.bit.CMPA = u16_Pwm1 = (Uint16)((INV_PWM_HALF_TBPRD * motor->svgen.Ta) + INV_PWM_HALF_TBPRD);
motor->PwmARegs->CMPA.bit.CMPAHR = (Uint16)(((INV_PWM_HALF_TBPRD * motor->svgen.Ta) + INV_PWM_HALF_TBPRD - u16_Pwm1) * u16_HrStep * 256 + 0x0080);
motor->PwmBRegs->CMPA.bit.CMPA = u16_Pwm2 = (Uint16)((INV_PWM_HALF_TBPRD * motor->svgen.Tb) + INV_PWM_HALF_TBPRD);
motor->PwmBRegs->CMPA.bit.CMPAHR = (Uint16)(((INV_PWM_HALF_TBPRD * motor->svgen.Tb) + INV_PWM_HALF_TBPRD - u16_Pwm2) * u16_HrStep * 256 + 0x0080);
motor->PwmCRegs->CMPA.bit.CMPA = u16_Pwm3 = (Uint16)((INV_PWM_HALF_TBPRD * motor->svgen.Tc) + INV_PWM_HALF_TBPRD);
motor->PwmCRegs->CMPA.bit.CMPAHR = (Uint16)(((INV_PWM_HALF_TBPRD * motor->svgen.Tc) + INV_PWM_HALF_TBPRD - u16_Pwm3) * u16_HrStep * 256 + 0x0080);

Result - ~8.7mV for each PWM Count; smooth continuity between Integer values, down to available resolution.

B.  Direct calculation of CMPAHR value, with High-Res. Period Enable:

EPwmnRegs.HRPCTL.bit.HRPE = 1

u16_HrStep = 126; // internal Variable to be used in HRPWM Calculations, value is twice the nominal estimate

PWM Calculations as in Experiment A above.

Result - ~8.7mV for each PWM Count (as before); NO EFFECT of CMPAHR Content AT ALL.

C.  Auto-Conversion with SFO, no HRPE:

EPwmnRegs.HRPCTL.bit.HRPE = 0;

EPwmnRegs.HRCNFG.bit.AUTOCONV = HR_AUTOCONV_ON;

EPwm1Regs.HRMSTEP.bit.HRMSTEP = 63; (calculated by SFO())

PWM Calculations:
motor->PwmARegs->CMPA.all = (65536 * INV_PWM_HALF_TBPRD * (motor->svgen.Ta + 1));
motor->PwmBRegs->CMPA.all = (65536 * INV_PWM_HALF_TBPRD * (motor->svgen.Tb + 1));
motor->PwmCRegs->CMPA.all = (65536 * INV_PWM_HALF_TBPRD * (motor->svgen.Tc + 1));

Result:  ~8.7mV for each PWM Count (as before); Fractional values are off by a factor of two.  For example - setting 1/4 step causes 16,384 to be written in CMPAHR (as expected), BUT the resulting voltage difference from Integer value is 1.1mV (instead of ~2.2mV); setting 15/16 step causes 61,440 to be written in CMPAHR (as expected, BUT the resulting voltage difference from Integer value is 4.1mV (instead of ~8.2mV); etc.

D.  Auto-Conversion based on Estimate, no HRPE:

EPwmnRegs.HRPCTL.bit.HRPE = 0;

EPwmnRegs.HRCNFG.bit.AUTOCONV = HR_AUTOCONV_ON;

EPwm1Regs.HRMSTEP.bit.HRMSTEP = 126; (estimated from 2 * result from SFO())

PWM Calculations as in Experiment C above.

Result - ~8.7mV for each PWM Count; smooth continuity between Integer values, down to available resolution.

E.  Auto-Conversion with SFO, High-Res. Period Enable:

EPwmnRegs.HRPCTL.bit.HRPE = 1;

EPwmnRegs.HRCNFG.bit.AUTOCONV = HR_AUTOCONV_ON;

EPwm1Regs.HRMSTEP.bit.HRMSTEP = 63; (calculated by SFO())

PWM Calculations as in Experiment C above.

Result - ~8.7mV for each PWM Count (as before); NO EFFECT of CMPAHR Content AT ALL.

[Please note that Auto-Conversion based on Estimate (as in Experiment D above) with HRPE was not run, as it seems that setting HRPE completely disables High-Res. MEP anyway.]

Conclusions:

i.  HRPE somehow disables High-Res. MEP, regardless of other configuration settings.

ii.  The MEP value that gives the correct results seems to be twice the calculation results of the SFO() Function.

iii.  It is possible to utilize Auto-Conversion Setting "EPwmnRegs.HRCNFG.bit.AUTOCONV = 1", BUT an estimate for MEP which is twice the result from the SFO() Function has to be used.

Please review and comment.

• In reply to Alon Harpaz:

Hi,

Would you be able to start with the example provided in C2000Ware

C:\ti\c2000\C2000Ware_2_00_00_02\device_support\f2837xd\examples\cpu1\hrpwm_prdupdown_sfo_v8

This project is for period control but you can use this for testing and not have High resolution period configured.

For controlling both the edges in Up-Down count mode, you've to have the HPRE enabled. Otherwise, both the edges will see same amount of fine delay and not effecting duty cycle.
So, I wonder you may be missing some configuration related to HRPE, hence please refer to the example and cross check the configuration.
Ideally, it'll be good if you can test with the same example code, so that i can reproduce, if you are seeing any issue, at my end.

• In reply to Subrahmanya:

Hi,

I'm adding more details upon receiving the note from FAE regarding clarification of the suggested example and need to enable HRPE.

1. Why HRPE is needed for your configuration-
You've stated that you are using up-down count mode and achieve duty cycle control.
The only way this can be achieved is by enabling HRPE.
If HRPE is not enabled, as you have observed "applying HR MEP to both Rising-Edge and Falling-Edge would result in a Phase-Shift, which is NOT beneficial to PWM Duty-Cycle Control". Where as with HRPE enabled, symmetric duty cycle control can be achieved as the edges will now move in opposite direction - as needed in up-down count mode. Hence HRPE is needed for symmetric mode (Up-down) even when you are using this only for duty cycle control.

2. Why I suggested example hrpwm_prdupdown_sfo_v8 -
The other example hrpwm_duty_sfo_v8 intended to showcase duty cycle control (which you intend to use) is only using up-count mode. Not the up-down count mode. Where as the example I suggested hrpwm_prdupdown_sfo_v8 uses up-down count mode, though it is not actually configured for duty-cycle control. This example has all the configuration needed for dual edge control in up-down count mode (including HRPE enabled).
I totally understand that this is not the exact configuration you want but something you can start with, so that we are on the same page in case I need to reproduce the issue at my end. Since I do not have access to your complete PWM configuration - I was trying to suggest the best possible option among the available examples.
This would at least validate the theory of whether sfo() computations are accurate or not. One of your conclusions was "HRPE somehow disables High-Res. MEP, regardless of other configuration settings." - this can be validated by the above example.

Other 2 conclusions you've are interrelated.
ii.  The MEP value that gives the correct results seems to be twice the calculation results of the SFO() Function.
iii.  It is possible to utilize Auto-Conversion Setting "EPwmnRegs.HRCNFG.bit.AUTOCONV = 1", BUT an estimate for MEP which is twice the result from the SFO() Function has to be used.

As of now, my understand still is that there is something missing in the configuration with HRPE enabled. If we can sort that our via example or some other means conclusions 2 and 3 would not be necessary.

Please let us know if you need any additional details.

• In reply to Subrahmanya:

Hello!

Thank you very much for your reply.  I will rephrase your comments here, please review and confirm or correct my understanding:

Setting "HRPCTL.bit.HRPE  = 1"would cause BOTH Edges of the COMPA-CMPAHR comparison to move, only when this Bit is set they move in OPPOSITE directions; therefore this Bit is required for Duty-Cycle Control with Up-Down Counting.

If this understanding is correct - does that mean that Edge-Mode has to be set to Both, such as "HRCNFG.bit.EDGMODE = HR_BEP"?

Please answer at your convenience; I will continue with experiments on Sunday next week.

Thanks, Alon Harpaz

• In reply to Alon Harpaz:

Hi,

Alon Harpaz
If this understanding is correct - does that mean that Edge-Mode has to be set to Both, such as "HRCNFG.bit.EDGMODE = HR_BEP"?

That's correct. You need to set HR_BEP. That's precisely the reason I asked you to refer to the example to start with.

If you were applying delay on rising edge only - this probably explains your initial observation of having to write 2x the MEP values.
In the up-down count mode, changing the compare value should change the edge position symmetrically from the centre of the PWM (say period match).
For instance, if you are not using HR, and you've changed the CMPA the duty would be symmetrical w.r.t. the center like the diagram shows "Figure 15-24. Up-Down-Count Mode Symmetrical Waveform". Similar symmetrical waveform would have to be generated even with HR enabled.
Now, if you are applying delay to only one edge - it means that the duty is effectively being modulated by half of what you actually intended, given the symmetric mode of operation. So, applying twice the delay is having desired effect on the duty cycle - but note that the PWM will not be symmetric w.r.t. the centre of the PWM. I think, this explains what could be happening in your experiments with HRPE=0. Let me know if you concur with my theory.

• In reply to Subrahmanya:

Hello SubrahManya,

I attempted to follow your advice, using a configuration that is similar to the Code in hrpwm_updown_sfo_v8.c

I attached my Code here (nothing two original that would warrant secrecy) after I compared this Code to the Code in the file mentioned above There are no significant differences that I could tell.

The Configuration Function is called for all three ePWM Modules (1, 2, and 3) that are used as Motor1 PwmARegs PwmBRegs, and PwmCRegs, respectively; with parameters period = 10,000 and db = 5.

void PWM_1ch_UpDwnCnt_CNF(volatile struct EPWM_REGS * ePWM, Uint16 period, int16 db)
{
EALLOW;
// Time Base SubModule Registers
ePWM->TBCTL2.all = 0; // Legacy settings - Period-Load at Zero, no Sync. Out, no One-Shot
ePWM->TBPRD = period / 2; // For Triangular Wave; PWM frequency = 1 / period
ePWM->TBCTR = 0; // Start at Counter Zero
ePWM->TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Triangular Wave (Up-Down Counting)
ePWM->TBCTL.bit.HSPCLKDIV = TB_DIV1; // High-Speed Clock Divider of 1
ePWM->TBCTL.bit.CLKDIV = TB_DIV1; // Clock Divider of 1.

// High-Resolution Period Control
ePWM->HRPCTL.all = 0x0; // Reset all Bits first
ePWM->HRPCTL.bit.TBPHSHRLOADE = 1; // Enable TBPHSHR sync (required for up-down count HR control)
ePWM->HRPCTL.bit.HRPE = HR_PRD_EN; // Enabled

ePWM->TBCTL.bit.PHSEN = TB_DISABLE; // Disable all Syncing, enable specific Modules in Configuration
ePWM->TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // sync "down-stream" on Counter at Zero
ePWM->TBPHS.bit.TBPHS = 0;
ePWM->TBPHS.bit.TBPHSHR = 0x0; // No HR for Time-Base Phase settings

// Counter Compare A Submodule Registers
ePWM->CMPA.bit.CMPA = ePWM->TBPRD / 2; // set duty 50% initially
ePWM->CMPA.bit.CMPAHR = 0; // initialize HRPWM extension
ePWM->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD; // Load Shadow at ZERO and at PRD

// High-Resolution Configuration
ePWM->HRCNFG.all = 0x0; // Zero all Bits first
ePWM->HRCNFG.bit.EDGMODE = HR_BEP; // Control both Rising and Falling Edge Position
ePWM->HRCNFG.bit.CTLMODE = HR_CMP; // CMPAHR controls the MEP
ePWM->HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD; // Shadow load on both CTR==ZERO & CTR==PRD

// Auto-Conversion for High-Res
ePWM->HRCNFG.bit.AUTOCONV = HR_AUTOCONV_ON;
// Initial value for Micro-Edge Positioning Step
ePWM->HRMSTEP.bit.HRMSTEP = 66; // Initial value only, overwritten by SFO().

// Compare-A Action Qualifier SubModule Registers
ePWM->AQCTLA.bit.CAU = AQ_CLEAR;

// Active high complementary PWMs - Set up the deadband
ePWM->DBCTL.bit.IN_MODE = DBA_ALL; // Source A, both edges
ePWM->DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // Both Edges
ePWM->DBCTL.bit.POLSEL = DB_ACTV_HIC;
ePWM->DBRED.all = db; // porting change
ePWM->DBFED.all = db; // porting change
EDIS;
}

The Macro below is called for EPwm2Regs and EPwm3Regs, chaining their Sync. Sources to EPwm1Regs.

//-----------------------------------------------------------------------------
// PWM SYNCing MACRO
#define SYNC_EPWM(EPwmXRegs_Ptr) \
EPwmXRegs_Ptr->TBCTL.bit.SYNCOSEL = TB_SYNC_IN; \
EPwmXRegs_Ptr->TBCTL.bit.PHSEN = TB_ENABLE; \
EPwmXRegs_Ptr->TBPHS.bit.TBPHS = 0; \
EPwmXRegs_Ptr->TBCTL.bit.PHSDIR = TB_UP;
//-----------------------------------------------------------------------------

// configure Epwms B and C as slaves of A (EPWM highest up is chosen as A)
SYNC_EPWM(motor1.PwmBRegs);
SYNC_EPWM(motor1.PwmCRegs);

The PWM Generating Code is listed here (writing the full 32-Bit Wide result into CMPA ad CMPAHR simultaneously):
motor->PwmARegs->CMPA.all = (65536 * INV_PWM_HALF_TBPRD * (motor->svgen.Ta + 1));
motor->PwmBRegs->CMPA.all = (65536 * INV_PWM_HALF_TBPRD * (motor->svgen.Tb + 1));
motor->PwmCRegs->CMPA.all = (65536 * INV_PWM_HALF_TBPRD * (motor->svgen.Tc + 1));

When I operate the PWM Sources this way (using Build_Level1 of the LaunchPad Example Code), I get NO effect from any value written into CMPAHR at all; this is similar to my previous experiments, except that here (per your advice) the HRPE Bit is set and Auto-Convert is enabled.

Just to ensure that there was no matter of reversed polarity somewhere, I also checked the configuration as listed here with the Action-Qualifiers swapped; again, there seemed to be no effect of anything written into the HR Registers.

The theory of operation suggests strongly that some other setting is missing.  Can you fill me in please?

Thanks, Alon Harpaz

• In reply to Alon Harpaz:

Hi,

Further to our discussion, I've gone ahead and tested the example project I suggested above.
I've loaded the hrpwm_updown_sfo_v8 and disabled UpdateFine - by writing UpdateFine=0. When I run this code it produces a fixed duty output.
Now, through the debugger window, I've modified the CMPAHR value and I do observe the duty cycle change as expected.
So, the duty cycle change, when HRPE is enabled, is happening as expected.
I tried multiple values of CMPAHR (0x8000, 0xC000, 0xAA00.... etc) and I do see the expected result.
I've also checked your configuration code you provided - and it seems to be correct as well.
At this stage i'm not sure why you are not observing the duty cycle changes.
Can you do this simple step as above and confirm your observation - before we start digging into your application code?

• In reply to Subrahmanya:

Hi,

Did you get a chance to check the duty cycle variation with the example as suggested above?

• In reply to Subrahmanya:

Hello!

My apologies, I just got back to some experiments yesterday.  I am still in the process of setting up the SW/HW configuration so I can test the results within our limited resources (no high-bandwidth oscilloscope).

One thing which I already noticed - the SFO() result (as read from EPwm1Regs.HRMSTEP.bit.HRMSTEP is 130, which is roughly TWICE the value that was obtained with my setup, as based on the FCL_379XL Example Code.  Please note that this ALONE would be sufficient to allow me to operate the HRPWM with the Auto-Conversion feature and SFO() Calibration.

I am not sure what the cause for this difference is.  One thing which I noticed - the EPwm1Regs.HRPWR.bit.CALPWRON occasionally toggles '1' and back to '0'.  Is that part of the expected behavior?  Is there any significance to other Bits in that Register?

Thanks, Alon Harpaz

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.