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.

LAUNCHXL-F28379D: C2000™︎ Microcontroller Forum

Part Number: LAUNCHXL-F28379D
Other Parts Discussed in Thread: DRV8301

Hi Team,

There's an issue from the customer need your help:

I use the main controller LAUNCHXL-F2837D and the driver board is drv8301-REVB. After transplanting the user guide, the three-phase PWM duty cycle is not equal to 50% in the first-level incremental construction according to the guide. CMPA is not equal to half of TBPRD. There is also voltage bias not equal to 0. Why?

Thanks & Regards,

Ben

  • Which example lab are you using?

    Did you configure the right PWM according to the using kits? Seems NO.

  • Hi Yanming,

    Hello, I built the f28379d project according to the document User's Guide Motor Control SDK Universal Project and Lab.

    I personally also think that there is a problem with the pwm configuration. I removed the driver and only used the control board to measure the pin output. The voltage of pwm is displayed as 0.

    Below is the relevant part of the code that I modified

    void HAL_setupPWMs(HAL_MTR_Handle handle)
    {
        HAL_MTR_Obj    *obj = (HAL_MTR_Obj *)handle;
        uint16_t  cnt;
    
        uint16_t       pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM);
        uint16_t       numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
    
        // disable the ePWM module time base clock sync signal
        // to synchronize all of the PWMs
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        // turns off the outputs of the EPWM peripherals which will put the power
        // switches into a high impedance state.
        EPWM_forceTripZoneEvent(obj->pwmHandle[0], EPWM_TZ_FORCE_EVENT_OST);
        EPWM_forceTripZoneEvent(obj->pwmHandle[1], EPWM_TZ_FORCE_EVENT_OST);
        EPWM_forceTripZoneEvent(obj->pwmHandle[2], EPWM_TZ_FORCE_EVENT_OST);
    
    #if defined(BSXL8323RS_REVA) || defined(BSXL8323RH_REVB) || \
        defined(BSXL8353RS_REVA) || defined(BSXL8316RT_REVA) || \
        defined(BSXL3PHGAN_REVA) || defined(HVMTRPFC_REV1P1) || \
        defined(BSXL8301_REVB)
    
        for(cnt=0; cnt<3; cnt++)
        {
            // setup the Time-Base Control Register (TBCTL)
            EPWM_setTimeBaseCounterMode(obj->pwmHandle[cnt],
                                        EPWM_COUNTER_MODE_UP_DOWN);
    
            EPWM_disablePhaseShiftLoad(obj->pwmHandle[cnt]);
    
            EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_DIRECT_LOAD);
    
            //EPWM_enableSyncOutPulseSource(obj->pwmHandle[cnt],
            //                              EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
            EPWM_setSyncOutPulseMode(obj->pwmHandle[cnt],
                                     EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
    
            EPWM_setClockPrescaler(obj->pwmHandle[cnt], EPWM_CLOCK_DIVIDER_1,
                                     EPWM_HSCLOCK_DIVIDER_1);
    
            EPWM_setCountModeAfterSync(obj->pwmHandle[cnt],
                                       EPWM_COUNT_MODE_UP_AFTER_SYNC);
    
            EPWM_setEmulationMode(obj->pwmHandle[cnt], EPWM_EMULATION_FREE_RUN);
    
            // setup the Timer-Based Phase Register (TBPHS)
            EPWM_setPhaseShift(obj->pwmHandle[cnt], 0);
    
            // setup the Time-Base Counter Register (TBCTR)
            EPWM_setTimeBaseCounter(obj->pwmHandle[cnt], 0);
    
            // setup the Time-Base Period Register (TBPRD)
            // set to zero initially
            EPWM_setTimeBasePeriod(obj->pwmHandle[cnt], 0);
    
            // setup the Counter-Compare Control Register (CMPCTL)
            EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                                 EPWM_COUNTER_COMPARE_A,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
            EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                                 EPWM_COUNTER_COMPARE_B,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
            EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                                 EPWM_COUNTER_COMPARE_C,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
            EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
                                                 EPWM_COUNTER_COMPARE_D,
                                                 EPWM_COMP_LOAD_ON_CNTR_ZERO);
    #else   //!MOTOR1_ISBLDC
    #if defined(MOTOR1_DCLINKSS)   
        .......
    #else  // !(MOTOR1_DCLINKSS)
            // setup the Action-Qualifier Output A Register (AQCTLA)
            EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                          EPWM_AQ_OUTPUT_A,
                                          EPWM_AQ_OUTPUT_HIGH,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
            EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                          EPWM_AQ_OUTPUT_A,
                                          EPWM_AQ_OUTPUT_HIGH,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    
            EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                          EPWM_AQ_OUTPUT_A,
                                          EPWM_AQ_OUTPUT_LOW,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
            EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
                                          EPWM_AQ_OUTPUT_A,
                                          EPWM_AQ_OUTPUT_LOW,
                                          EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
    #endif  // !(MOTOR1_DCLINKSS)             
      // setup the Dead-Band Generator Control Register (DBCTL)
            EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, true);
            EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, true);
    
            // select EPWMA as the input to the dead band generator
            EPWM_setRisingEdgeDeadBandDelayInput(obj->pwmHandle[cnt],
                                                 EPWM_DB_INPUT_EPWMA);
    
            // configure the right polarity for active high complementary config.
            EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt],
                                          EPWM_DB_RED,
                                          EPWM_DB_POLARITY_ACTIVE_HIGH);
            EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt],
                                          EPWM_DB_FED,
                                          EPWM_DB_POLARITY_ACTIVE_LOW);
    
            // setup the Dead-Band Rising Edge Delay Register (DBRED)
            EPWM_setRisingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBRED_CNT);
    
            // setup the Dead-Band Falling Edge Delay Register (DBFED)
            EPWM_setFallingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBFED_CNT);
    
    #endif  //!MOTOR1_ISBLDC  
    
            // setup the PWM-Chopper Control Register (PCCTL)
            EPWM_disableChopper(obj->pwmHandle[cnt]);
    
            // setup the Trip Zone Select Register (TZSEL)
            EPWM_disableTripZoneSignals(obj->pwmHandle[cnt], HAL_TZSEL_SIGNALS_ALL);
        }
    #if defined(MOTOR1_ISBLDC)
    ..........
    #elif
    .........                   
    #else   //!(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
        // setup the Event Trigger Selection Register (ETSEL)
        EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO);
    
        EPWM_enableInterrupt(obj->pwmHandle[0]);
    
        EPWM_setADCTriggerSource(obj->pwmHandle[0],
                                 EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC);
    
        EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
    #endif  // !(MOTOR1_ISBLDC || MOTOR1_DCLINKSS)
     // setup the Event Trigger Prescale Register (ETPS)
        if(numPWMTicksPerISRTick > 15)
        {
            EPWM_setInterruptEventCount(obj->pwmHandle[0], 15);
    
            EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A, 15);
            EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B, 15);
             }
        else if(numPWMTicksPerISRTick < 1)
        {
            EPWM_setInterruptEventCount(obj->pwmHandle[0], 1);
    
            EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A, 1);
            EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B, 1);
             }
        else
        {
            EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);
    
            EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A,
                                            numPWMTicksPerISRTick);
            EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B,
                                            numPWMTicksPerISRTick);
                                             }
    
        // setup the Event Trigger Clear Register (ETCLR)
        EPWM_clearEventTriggerInterruptFlag(obj->pwmHandle[0]);
        EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_A);
        EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_B);
    
        // since the PWM is configured as an up/down counter, the period register is
        // set to one-half of the desired PWM period
        EPWM_setTimeBasePeriod(obj->pwmHandle[0], pwmPeriodCycles);
        EPWM_setTimeBasePeriod(obj->pwmHandle[1], pwmPeriodCycles);
        EPWM_setTimeBasePeriod(obj->pwmHandle[2], pwmPeriodCycles);
    
        // write the PWM data value  for ADC trigger
        EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_C, 10);
            // enable the ePWM module time base clock sync signal
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        return;
    }  // end of HAL_setupPWMs() function
    
    
    static inline void
    HAL_writePWMData(HAL_MTR_Handle handle, HAL_PWMData_t *pPWMData)
    {
        HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle;
    
        float32_t period = (float32_t)(EPWM_getTimeBasePeriod(obj->pwmHandle[0]));
    
        uint16_t pwmCnt;
    
        for(pwmCnt=0; pwmCnt<3; pwmCnt++)
        {
          // compute the value
            float32_t V_pu = -pPWMData->Vabc_pu.value[pwmCnt];      // Negative
            float32_t V_sat_pu = __fsat(V_pu, 0.5, -0.5);           // -0.5~0.5
            float32_t V_sat_dc_pu = V_sat_pu + 0.5;                 // 0~1.0
            pPWMData->cmpValue[pwmCnt]  = (int16_t)(V_sat_dc_pu * period);  //
    
            if(pPWMData->cmpValue[pwmCnt] < pPWMData->minCMPValue)
            {
                pPWMData->cmpValue[pwmCnt] = pPWMData->minCMPValue;
            }
    
            // write the PWM data value
            EPWM_setCounterCompareValue(obj->pwmHandle[pwmCnt],
                                        EPWM_COUNTER_COMPARE_A,
                                        pPWMData->cmpValue[pwmCnt]);
    
            EPWM_setCounterCompareValue(obj->pwmHandle[pwmCnt],
                                        EPWM_COUNTER_COMPARE_B,
                                        pPWMData->cmpValue[pwmCnt]);
        }
    
        return;
    } // end of HAL_writePWMData() function
    
    void runMotor1OffsetsCalculation(MOTOR_Handle handle)
    {
    
           .................
            ADC_setPPBReferenceOffset(MTR1_IU_ADC_BASE, MTR1_IU_ADC_PPB_NUM, 0);
            ADC_setPPBReferenceOffset(MTR1_IV_ADC_BASE, MTR1_IV_ADC_PPB_NUM, 0);
            ADC_setPPBReferenceOffset(MTR1_IW_ADC_BASE, MTR1_IW_ADC_PPB_NUM, 0);
    
            obj->adcData.offset_I_ad.value[0] =
                     obj->adcData.offset_I_ad.value[0] * obj->adcData.current_sf;
            obj->adcData.offset_I_ad.value[1] =
                     obj->adcData.offset_I_ad.value[1] * obj->adcData.current_sf;
            obj->adcData.offset_I_ad.value[2] =
                     obj->adcData.offset_I_ad.value[2] * obj->adcData.current_sf;
    
          // Set the 3-phase output PWMs to 50% duty cycle
            obj->pwmData.Vabc_pu.value[0] = 0.0f;
            obj->pwmData.Vabc_pu.value[1] = 0.0f;
            obj->pwmData.Vabc_pu.value[2] = 0.0f;
    //        obj->pwmData.Vabc_pu.value[0] = 0.4f;
    //        obj->pwmData.Vabc_pu.value[1] = 0.5f;
    //        obj->pwmData.Vabc_pu.value[2] = 0.5f;
    
    ......................
    }
    
    __interrupt void motor1CtrlISR(void)
    {................
    #if(DMC_BUILDLEVEL == DMC_LEVEL_1)
        // output 50%
        obj->pwmData.Vabc_pu.value[0] = 0.0f;
        obj->pwmData.Vabc_pu.value[1] = 0.0f;
        obj->pwmData.Vabc_pu.value[2] = 0.0f;
    //    obj->pwmData.Vabc_pu.value[0] = 0.5f;
    //    obj->pwmData.Vabc_pu.value[1] = 0.5f;
    //    obj->pwmData.Vabc_pu.value[2] = 0.5f;
    #endif
    }

    Best Regards,

    Ben

  • Hi Yanming,

    Is there any updates?

    Best Regards,

    Ben

  • Currently, the Universal Motor Control doesn't support f28379d and DRV8301 kit, you need to follow the lab user's guide to port this project for f28379d. Make sure that you change the configuration correctly for f28379d and drv8301 kit.

    Universal Project and Lab User’s Guide: https://www.ti.com/lit/spruj26

    Is it a project for customer? Which customer? Or just a learning project for you?

  • Is it a project for customer? Which customer? Or just a learning project for you?

    no, it is modified by customer.

  • Got it. Please ask your customer to follow the lab user's guide to port the lab to f28379d and DRV8301 kit. The issue should be from the PWM or GPIOs configuration.