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.

TMS320F280049C: PWM generation for 3 phase inverter

Part Number: TMS320F280049C
Other Parts Discussed in Thread: C2000WARE,

Hi team,

Present we are working on TMS320F280049C, we are using the examples presented in “C:\ti\c2000\C2000Ware_MotorControl_SDK_3_00_01_00\c2000ware\driverlib\f28004x\examples”,

  1. We initialize the ADC
  2. And PWM modules individually, we generated the PWMs with 120-degree phase shift (for 3phase inverter application), as shown in below image. Yellow: PWM1A, Blue: PWM2A, Pink: PWM3A.

3. Now we are trying to change the Duty of the PWMs by using half of the ADC result, we integrated both ADC and PWMs code, (we have attached the code in below), the duty of the PWMs varies with respect to ADC values (we used POT for changing the result of ADC).but we are facing one problem, phase shift of the PWMs getting disturbed.

4. Phase_R PWM is 240-degree phase shift with Phase B, but Phase_R is not 120-degree phase shift with phase Y, can anyone help me to solve this problem? (Problem also shown in below image), 

#include "driverlib.h"
#include "device.h"
uint16_t pwm_period_ticks = 2500;
uint16_t adcAResults;  //Store the ADC result
uint16_t  K;
__interrupt void adcA1ISR(void);
void main(void)
{
    VIENNA_HAL_setupDevice();
    initADC();
    VIENNA_HAL_disablePWMClkCounting();
    VIENNA_HAL_configurePWMUpDwnCnt1(EPWM1_BASE,2500);
    VIENNA_HAL_configurePWMUpDwnCnt2(EPWM2_BASE,2500);
    VIENNA_HAL_configurePWMUpDwnCnt3(EPWM3_BASE,2500);
    VIENNA_HAL_setupPWM1(EPWM1_BASE);
    VIENNA_HAL_setupPWM2(EPWM2_BASE);
    VIENNA_HAL_setupPWM3(EPWM3_BASE);
    VIENNA_HAL_enablePWMClkCounting();
    PWMduty();
    Interrupt_register(INT_ADCA1, &adcA1ISR);
    // Enable ADC interrupt
    Interrupt_enable(INT_ADCA1);
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    EINT;
    ERTM;
    // Loop indefinitely
     while(1)
     {
         // Start ePWM1, enabling SOCA and putting the counter in up_Down-count mode
         EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
         EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
         K= adcAResults/2;
         PWMduty(K);
         // Stop ePWM1, disabling SOCA and freezing the counter
         EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
         EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
     }
}
void VIENNA_HAL_setupDevice(void)
{
  //Device initialization
    Device_init();
  // Disable pin locks and enable internal pull ups
    Device_initGPIO();
  // Initialize PIE and clear PIE registers. Disables CPU interrupts
    Interrupt_initModule();
  // Initialize the PIE vector table with pointers to the shell Interrupt
  // Service Routines (ISR)
    Interrupt_initVectorTable();
  //This function sets the pin type for specified pin
    GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
 //This function sets the pin configuration for EPWM1A
    GPIO_setPinConfig(GPIO_0_EPWM1A);

    GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_2_EPWM2A);

    GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_4_EPWM3A);
}
void initADC(void)
{
    // Setup VREF as internal
    ADC_setVREF(ADCA_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);
    // Set ADCCLK divider to /4
    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_4_0);
    // Set pulse positions to late
    ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);
    // Power up the ADC and then delay for 1 ms
    ADC_enableConverter(ADCA_BASE);
    DEVICE_DELAY_US(1000);
    // ADC start of conversion
    // Configure SOC0 of ADCA to convert pin A0 with a sample window of 10
    // SYSCLK cycles. The EPWM1SOCA signal will be the trigger.
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER5, ADC_TRIGGER_EPWM1_SOCA,
                    ADC_CH_ADCIN5, 10);
    // Set SOC0 to set the interrupt 1 flag. Enable the interrupt and make
    // sure its flag is cleared.
    ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER5);
    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}
void VIENNA_HAL_setupPWM1(uint32_t base1)
{
    EPWM_disablePhaseShiftLoad(EPWM1_BASE);
    EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
}
void VIENNA_HAL_setupPWM2(uint32_t base1)
{
    EPWM_enablePhaseShiftLoad(EPWM2_BASE);
    EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);

    EPWM_setPhaseShift(EPWM2_BASE, 833);
    EPWM_setCountModeAfterSync(EPWM2_BASE, EPWM_COUNT_MODE_UP_AFTER_SYNC);
}
void VIENNA_HAL_setupPWM3(uint32_t base1)
{
    EPWM_enablePhaseShiftLoad(EPWM3_BASE);
    EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);

    EPWM_setPhaseShift(EPWM3_BASE, 1666);
    EPWM_setCountModeAfterSync(EPWM3_BASE, EPWM_COUNT_MODE_UP_AFTER_SYNC);
}
// configurePWM1chUpDwnCnt()
void VIENNA_HAL_configurePWMUpDwnCnt1(uint32_t base1, uint16_t pwm_period_ticks1)
{
    // Time Base SubModule Registers
    EPWM_setPeriodLoadMode(EPWM1_BASE, EPWM_PERIOD_SHADOW_LOAD);
    EPWM_setTimeBasePeriod(EPWM1_BASE, pwm_period_ticks);
    EPWM_setTimeBaseCounter(EPWM1_BASE, 0);
    EPWM_setPhaseShift(EPWM1_BASE, 0);
    EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A,
                                pwm_period_ticks >> 1);
    EPWM_setCounterCompareShadowLoadMode(EPWM1_BASE, EPWM_COUNTER_COMPARE_A,
                                       EPWM_COMP_LOAD_ON_CNTR_ZERO);
    // Action Qualifier SubModule Registers
    // CTR = CMPA@UP , set to 1
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH,
                                    EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    // CTR = CMPA@Down , set to 0
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW,
                                        EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    // CTR = 0 , set to 0
    EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW,
                                        EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    // Configure the SOC to occur on the first up_Down-count event
    EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_PERIOD);
    EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);
    EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
}
void VIENNA_HAL_configurePWMUpDwnCnt2(uint32_t base1, uint16_t pwm_period_ticks2)
{
    // Time Base SubModule Registers
    EPWM_setPeriodLoadMode(EPWM2_BASE, EPWM_PERIOD_SHADOW_LOAD);
    EPWM_setTimeBasePeriod(EPWM2_BASE, pwm_period_ticks);
    EPWM_setTimeBaseCounter(EPWM2_BASE, 0);
    EPWM_setPhaseShift(EPWM2_BASE, 833);
    EPWM_setTimeBaseCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setClockPrescaler(EPWM2_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A,
                                pwm_period_ticks >> 1);
    EPWM_setCounterCompareShadowLoadMode(EPWM2_BASE, EPWM_COUNTER_COMPARE_A,
                                       EPWM_COMP_LOAD_ON_CNTR_ZERO);
    // Action Qualifier SubModule Registers
    // CTR = CMPA@Down, set to 1
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    //  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA
    // CTR = CMPA@UP , set to 0
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    // CTR = 0 , set to 1
    EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH,
                                        EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
}
void VIENNA_HAL_configurePWMUpDwnCnt3(uint32_t base1, uint16_t pwm_period_ticks3)
{
    // Time Base SubModule Registers
    EPWM_setPeriodLoadMode(EPWM3_BASE, EPWM_PERIOD_SHADOW_LOAD);
    EPWM_setTimeBasePeriod(EPWM3_BASE, pwm_period_ticks);
    EPWM_setTimeBaseCounter(EPWM3_BASE, 0);
    EPWM_setPhaseShift(EPWM3_BASE, 1666);
    EPWM_setTimeBaseCounterMode(EPWM3_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setClockPrescaler(EPWM3_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A,
                                pwm_period_ticks >> 1);
    EPWM_setCounterCompareShadowLoadMode(EPWM3_BASE, EPWM_COUNTER_COMPARE_A,
                                       EPWM_COMP_LOAD_ON_CNTR_ZERO);
    // Action Qualifier SubModule Registers
    // CTR = CMPA@UP , set to 1
    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    //  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA
    // CTR = CMPA@Down , set to 0
    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    // CTR = 0 , set to 0
    EPWM_setActionQualifierAction(EPWM3_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW,
                                        EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
}
// setPinAsPWM()
void VIENNA_HAL_disablePWMClkCounting(void)
{
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
}
void VIENNA_HAL_enablePWMClkCounting(void)
{
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
}
void initEPWMGPIO(void)
{
    // Disable pull up on GPIO 0,GPIO 2 and GPIO 3 and configure them as PWM1A,
    // PWM2A,PWM3A output respectively.
    GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_0_EPWM1A);
    GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_2_EPWM2A);
    GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD);
    GPIO_setPinConfig(GPIO_4_EPWM3A);
}
__interrupt void adcA1ISR(void)
{
    // Add the latest result to the buffer
    adcAResults = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER5);
    //Clear the interrupt flag
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
    //Acknowledge the interrupt
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}
void PWMduty(uint16_t duty)
{
    EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A,
                                      duty);
    EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A,
                                      duty);
    EPWM_setCounterCompareValue(EPWM3_BASE, EPWM_COUNTER_COMPARE_A,
                                duty);
}