Other Parts Discussed in Thread: LAUNCHXL-F2800137
Hi all,
I've been testing with a LAUNCHXL-F2800137 and BOOSTXL-DRV8323S for a specific motor control application.
Now, an hardware engineer has made a custom PCB based on the mentioned boards but flipped something around.
On the LAUNCHXL board, the EPWM A outputs go to the High side phase input of the DRV8323S. See table below for clarification.
| Name | LAUNCHXL pin |
| Hin A | GPIO 0 (EPWM1 A) |
| Lin A | GPIO 1 (EPWM1 B) |
| Hin B | GPIO 2 (EPWM2 A) |
| Lin B | GPIO 3 (EPWM2 B) |
| Hin C | GPIO 10 (EPWM6 A) |
| Lin C | GPIO 11 (EPWM6 B) |
Now, on our hardware, the A and B channels are switched around (mistake).
The question is, how do i change the polarity of the two channels in the PWM setup in the Hal.c file of the motorcontrol lab? I've put the code below. I think it has something to do with the deadband generator. But i'm not sure. Can someone clarify how these two channels are linked to one another? Because i guess they are, since in the PWM write function, the same compare value is written to both channel A and B.
Thanks in advance!
PWM setup function:
void HAL_setupPWMs(HAL_MTR_Handle handle)
{
HAL_MTR_Obj *obj = (HAL_MTR_Obj *)handle;
uint16_t cnt;
uint16_t pwmPeriodCycles = (uint16_t)(MOTORCONFIG_PWM_TBPRD_NUM);
uint16_t numPWMTicksPerISRTick = MOTORCONFIG_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);
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_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);
// 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);
// 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);
// 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);
}
// 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);
// setup the Event Trigger Prescale Register (ETPS)
if(numPWMTicksPerISRTick > 15)
{
numPWMTicksPerISRTick = 15;
}
else if(numPWMTicksPerISRTick < 1)
{
numPWMTicksPerISRTick = 1;
}
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);
return;
}
Write PWM function:
//! \brief Writes PWM data to the PWM comparators for motor control
//! \param[in] handle The hardware abstraction layer (HAL) handle
//! \param[in] pPWMData The pointer to the PWM data
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;
}