Tool/software:
ADC SOC Triggering and Interrupt Generation for Three- Phase Interleaved Buck Converter
We are working on a hybrid EV battery charger to charge a 12V auxiliary battery from an 80V main traction battery.
In this system, we are using a three- phase interleaved synchronous buck converter, each phase are shifted by 120 degrees from each other. Phase U pwm is applied from EPWM1 module, Phase V via EPWM2 and Phase W via EPWM5. Center aligned PWM scheme is used so to capture each phase average current we want to trigger the ADC’s at midpoint of each inductor current which gets synchronized with zero crossing or period match of corresponding PWM counter. Three phase current are measured using ADCC module. ADCA module used for input voltage, output voltage and Heat sink temperature feedback. We are triggering ADCC as follows
static void INIT_fnEpwm1(void) { EPWM_setClockPrescaler(EPWM1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); EPWM_setTimeBasePeriod(EPWM1_BASE, tzPWM.uiPwmperiod_ticks); EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 0); EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_B, 0); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); EPWM_setActionQualifierAction(EPWM1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); EPWM_enableSyncOutPulseSource(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO); // Phase Shift Setup (similar to Program 1) EPWM_disablePhaseShiftLoad(EPWM1_BASE); EPWM_setPhaseShift(EPWM1_BASE, 0); EPWM_enablePhaseShiftLoad(EPWM1_BASE); EPWM_setSyncInPulseSource(EPWM1_BASE, EPWM_SYNC_IN_PULSE_SRC_DISABLE); // // Active high complementary PWMs - Set up the deadband EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM1_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO); EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM1_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO); EPWM_setDeadBandCounterClock(EPWM1_BASE, EPWM_DB_COUNTER_CLOCK_HALF_CYCLE); EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(EPWM1_BASE, EPWM_DB_FED, true); EPWM_setRisingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setFallingEdgeDeadBandDelayInput(EPWM1_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); EPWM_setDeadBandDelayPolarity(EPWM1_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setRisingEdgeDelayCount(EPWM1_BASE, tzPWM.uiDeadband_ticks); EPWM_setFallingEdgeDelayCount(EPWM1_BASE, tzPWM.uiDeadband_ticks); EPWM_forceTripZoneEvent(EPWM1_BASE, EPWM_TZ_FORCE_EVENT_OST); } static void INIT_fnEpwm2(void) { EPWM_setClockPrescaler(EPWM2_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); EPWM_setTimeBasePeriod(EPWM2_BASE, tzPWM.uiPwmperiod_ticks); EPWM_setTimeBaseCounterMode(EPWM2_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_A, 0); EPWM_setCounterCompareValue(EPWM2_BASE, EPWM_COUNTER_COMPARE_B, 0); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); EPWM_setActionQualifierAction(EPWM2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); // Phase Shift Setup (similar to Program 1) EPWM_disablePhaseShiftLoad(EPWM2_BASE); EPWM_setPhaseShift(EPWM2_BASE, 500); EPWM_enablePhaseShiftLoad(EPWM2_BASE); EPWM_setSyncInPulseSource(EPWM2_BASE, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1); EPWM_enableSyncOutPulseSource(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO); /// Active high complementary PWMs - Set up the deadband EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM2_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO); EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM2_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO); EPWM_setDeadBandCounterClock(EPWM2_BASE, EPWM_DB_COUNTER_CLOCK_HALF_CYCLE); EPWM_setDeadBandDelayMode(EPWM2_BASE, EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(EPWM2_BASE, EPWM_DB_FED, true); EPWM_setRisingEdgeDeadBandDelayInput(EPWM2_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setFallingEdgeDeadBandDelayInput(EPWM2_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setDeadBandDelayPolarity(EPWM2_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); EPWM_setDeadBandDelayPolarity(EPWM2_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setRisingEdgeDelayCount(EPWM2_BASE, tzPWM.uiDeadband_ticks); EPWM_setFallingEdgeDelayCount(EPWM2_BASE, tzPWM.uiDeadband_ticks); EPWM_forceTripZoneEvent(EPWM2_BASE, EPWM_TZ_FORCE_EVENT_OST); } static void INIT_fnEpwm3(void) { EPWM_setClockPrescaler(EPWM5_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); EPWM_setTimeBasePeriod(EPWM5_BASE, tzPWM.uiPwmperiod_ticks); EPWM_setTimeBaseCounterMode(EPWM5_BASE, EPWM_COUNTER_MODE_UP_DOWN); EPWM_setCounterCompareValue(EPWM5_BASE, EPWM_COUNTER_COMPARE_A, 0); EPWM_setCounterCompareValue(EPWM5_BASE, EPWM_COUNTER_COMPARE_B, 0); EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); EPWM_setActionQualifierAction(EPWM5_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB); EPWM_enableSyncOutPulseSource(EPWM5_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO); EPWM_disablePhaseShiftLoad(EPWM5_BASE); EPWM_setPhaseShift(EPWM5_BASE, 1000); EPWM_enablePhaseShiftLoad(EPWM5_BASE); EPWM_setSyncInPulseSource(EPWM5_BASE, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1); // Active high complementary PWMs - Set up the deadband EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM5_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO); EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM5_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO); EPWM_setDeadBandCounterClock(EPWM5_BASE, EPWM_DB_COUNTER_CLOCK_HALF_CYCLE); EPWM_setDeadBandDelayMode(EPWM5_BASE, EPWM_DB_RED, true); EPWM_setDeadBandDelayMode(EPWM5_BASE, EPWM_DB_FED, true); EPWM_setRisingEdgeDeadBandDelayInput(EPWM5_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setFallingEdgeDeadBandDelayInput(EPWM5_BASE, EPWM_DB_INPUT_EPWMA); EPWM_setDeadBandDelayPolarity(EPWM5_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); EPWM_setDeadBandDelayPolarity(EPWM5_BASE, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); EPWM_setRisingEdgeDelayCount(EPWM5_BASE, tzPWM.uiDeadband_ticks); EPWM_setFallingEdgeDelayCount(EPWM5_BASE, tzPWM.uiDeadband_ticks); EPWM_forceTripZoneEvent(EPWM5_BASE, EPWM_TZ_FORCE_EVENT_OST); } static void INIT_fnEpwm4(void) { // EPWM_setClockPrescaler(EPWM4_BASE, EPWM_CLOCK_DIVIDER_1, // EPWM_HSCLOCK_DIVIDER_1); // // EPWM_setTimeBasePeriod(EPWM4_BASE, tzPWM.uiPwmperiod_ticks); // EPWM_setTimeBaseCounterMode(EPWM4_BASE, EPWM_COUNTER_MODE_UP_DOWN); // EPWM_setCounterCompareValue(EPWM4_BASE, EPWM_COUNTER_COMPARE_A, 500); // EPWM_setCounterCompareValue(EPWM4_BASE, EPWM_COUNTER_COMPARE_B, 1000); // // ///// ist trigger//////////////////////////// // EPWM_disableADCTrigger(EPWM4_BASE, EPWM_SOC_A); // EPWM_setADCTriggerSource(EPWM4_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO); // EPWM_setADCTriggerEventPrescale(EPWM4_BASE, EPWM_SOC_A, 1); // EPWM_enableADCTrigger(EPWM4_BASE, EPWM_SOC_A); // // EPWM_forceTripZoneEvent(EPWM4_BASE, EPWM_TZ_FORCE_EVENT_OST); } static void INIT_fnADCA(void) { SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCA); ADC_setOffsetTrimAll(ADC_REFERENCE_EXTERNAL, ADC_REFERENCE_3_3V); ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_2_0); ADC_enableConverter(ADCA_BASE); DEVICE_DELAY_US(5000); ADC_disableBurstMode(ADCA_BASE); ADC_setSOCPriority(ADCA_BASE, ADC_PRI_ALL_ROUND_ROBIN); ADC_setupSOC(VOUT_FB_ADC_MODULE, VOUT_FB_ADC_SOC_NO, ADC_TRIGGER_EPWM1_SOCA, VOUT_FB_ADC_PIN, 15U); ADC_setupSOC(VIN_FB_ADC_MODULE, VIN_FB_ADC_SOC_NO, ADC_TRIGGER_EPWM1_SOCA, VIN_FB_ADC_PIN, 15U); ADC_setupSOC(HS_TEMP_FB_ADC_MODULE, HS_TEMP_FB_ADC_SOC_NO, ADC_TRIGGER_EPWM1_SOCA, HS_TEMP_FB_ADC_PIN, 15U); ADC_setInterruptSOCTrigger(ADCA_BASE, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_NONE); } static void INIT_fnADCC(void) { SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_ADCC); ADC_setOffsetTrimAll(ADC_REFERENCE_EXTERNAL, ADC_REFERENCE_3_3V); ADC_setPrescaler(ADCC_BASE, ADC_CLK_DIV_2_0); ADC_enableConverter(ADCC_BASE); DEVICE_DELAY_US(5000); ADC_disableBurstMode(ADCC_BASE); ADC_setSOCPriority(ADCC_BASE, ADC_PRI_THRU_SOC5_HIPRI); ADC_setupSOC(IPHU_CUR_FB_ADC_MODULE, IPHU_CUR_FB_ADC_SOC_NO, ADC_TRIGGER_EPWM1_SOCA, IPHU_CUR_FB_ADC_PIN, 15U); ADC_setupSOC(IPHW_CUR_FB_ADC_MODULE, IPHW_CUR_FB_ADC_SOC_NO, ADC_TRIGGER_EPWM5_SOCA, IPHW_CUR_FB_ADC_PIN, 15U); ADC_setupSOC(IPHV_CUR_FB_ADC_MODULE, IPHV_CUR_FB_ADC_SOC_NO, ADC_TRIGGER_EPWM2_SOCA, IPHV_CUR_FB_ADC_PIN, 15U); ADC_setInterruptSOCTrigger(ADCC_BASE, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_NONE); } static void INIT_fnCPUtimers(void) { CPUTimer_setPeriod(CPUTIMER0_BASE, 0xFFFFFFFF); CPUTimer_setPreScaler(CPUTIMER0_BASE, 0); CPUTimer_stopTimer(CPUTIMER0_BASE); CPUTimer_setPeriod(CPUTIMER0_BASE, TIMER0_PERIOD_CNT); CPUTimer_setEmulationMode(CPUTIMER0_BASE, CPUTIMER_EMULATIONMODE_RUNFREE); CPUTimer_enableInterrupt(CPUTIMER0_BASE); } static void Setup_ADCTrigger(void) { EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A); EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO); EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1); EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A); EPWM_disableADCTrigger(EPWM2_BASE, EPWM_SOC_A); EPWM_setADCTriggerSource(EPWM2_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO); EPWM_setADCTriggerEventPrescale(EPWM2_BASE, EPWM_SOC_A, 1); EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A); EPWM_disableADCTrigger(EPWM5_BASE, EPWM_SOC_A); EPWM_setADCTriggerSource(EPWM5_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO); EPWM_setADCTriggerEventPrescale(EPWM5_BASE, EPWM_SOC_A, 1); EPWM_enableADCTrigger(EPWM5_BASE, EPWM_SOC_A); } static void Setup_Interrupt(void) { ADC_setInterruptPulseMode(ADCC_BASE, ADC_PULSE_END_OF_CONV); ADC_setInterruptSource(ADCC_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER2); ADC_enableInterrupt(ADCC_BASE, ADC_INT_NUMBER1); ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1); ADC_enableContinuousMode(ADCC_BASE, ADC_INT_NUMBER1); Interrupt_register(INT_ADCC1, &adcA1ISR); Interrupt_enable(INT_ADCC1); Interrupt_enable(INT_TIMER0); Interrupt_register(INT_TIMER0, &cpuTimer0ISR); CPUTimer_startTimer(CPUTIMER0_BASE); }
static inline void ADC_readSensedSignals(void) { tzFOC.fIphu_Cur = ((float32_t) IPHU_CUR_FB_ADCREAD - 2266.0f) * PhCur_ADCPU_CONS*Ibase; tzFOC.fIphv_Cur = ((float32_t) IPHU_CUR_FB_ADCREAD - 2266.0f) * PhCur_ADCPU_CONS*Ibase; tzFOC.fIphw_Cur = ((float32_t) IPHU_CUR_FB_ADCREAD - 2266.0f) * PhCur_ADCPU_CONS*Ibase; uiHs_Temp_sense = HS_TEMP_FB_ADCREAD; tzFOC.fVout_fbk = ((float32_t) VOUT_FB_ADCREAD * PU_VOLTAGE_CONS)*Voutbase; tzFOC.fVin_fbk = ((float32_t) VIN_FB_ADCREAD * PU_VOLTAGE_CONS)*Vinbase; }
#define SysClk_Freq_MHz (120.0f) #define PWM_Freq_kHz (40.0f) #define DeadBand_ns (1000.0f) #define Base_Freq_Hz (400.0f) #define Base_Angle_Rad (6.28318531f) #define Base_Angle_Deg (360.0f) #define Base_Current (320.0f) #define Tsample (1.0f/PWM_Freq_kHz*1/1000.0f) #define Ibase (335.0f) #define Vinbase (153.0f) #define Voutbase (18.07f) /*============================================================================== Configuration Macros for PWM modules ==============================================================================*/ #define PH_U_PWM_BASE EPWM1_BASE #define PH_V_PWM_BASE EPWM2_BASE #define PH_W_PWM_BASE EPWM5_BASE /*============================================================================== CPU-Timer0 ISR Time Period ==============================================================================*/ #define TIMER0_PERIOD_CNT (240000U) //for 2 msec, 2msec*120MHz /*============================================================================== ADC results and measurements variables ==============================================================================*/ #define IPHU_CUR_FB_ADC_MODULE ADCC_BASE #define IPHU_CUR_FB_ADC_PIN ADC_CH_ADCIN15 #define IPHU_CUR_FB_ADC_SOC_NO ADC_SOC_NUMBER0 #define IPHU_CUR_FB_ADCRESULTREGBASE ADCCRESULT_BASE #define IPHU_CUR_FB_ADCREAD ADC_readResult(IPHU_CUR_FB_ADCRESULTREGBASE, \ IPHU_CUR_FB_ADC_SOC_NO) #define IPHW_CUR_FB_ADC_MODULE ADCC_BASE #define IPHW_CUR_FB_ADC_PIN ADC_CH_ADCIN14 #define IPHW_CUR_FB_ADC_SOC_NO ADC_SOC_NUMBER1 #define IPHW_CUR_FB_ADCRESULTREGBASE ADCCRESULT_BASE #define IPHW_CUR_FB_ADCREAD ADC_readResult(IPHW_CUR_FB_ADCRESULTREGBASE, \ IPHW_CUR_FB_ADC_SOC_NO) #define IPHV_CUR_FB_ADC_MODULE ADCC_BASE #define IPHV_CUR_FB_ADC_PIN ADC_CH_ADCIN0 #define IPHV_CUR_FB_ADC_SOC_NO ADC_SOC_NUMBER2 #define IPHV_CUR_FB_ADCRESULTREGBASE ADCCRESULT_BASE #define IPHV_CUR_FB_ADCREAD ADC_readResult(IPHV_CUR_FB_ADCRESULTREGBASE, \ IPHV_CUR_FB_ADC_SOC_NO) //////////A MODULES//////// #define VOUT_FB_ADC_MODULE ADCA_BASE #define VOUT_FB_ADC_PIN ADC_CH_ADCIN1 #define VOUT_FB_ADC_SOC_NO ADC_SOC_NUMBER0 #define VOUT_FB_ADCRESULTREGBASE ADCARESULT_BASE #define VOUT_FB_ADCREAD ADC_readResult(VOUT_FB_ADCRESULTREGBASE, \ VOUT_FB_ADC_SOC_NO) #define VIN_FB_ADC_MODULE ADCA_BASE #define VIN_FB_ADC_PIN ADC_CH_ADCIN3 #define VIN_FB_ADC_SOC_NO ADC_SOC_NUMBER2 #define VIN_FB_ADCRESULTREGBASE ADCARESULT_BASE #define VIN_FB_ADCREAD ADC_readResult(VIN_FB_ADCRESULTREGBASE, \ VIN_FB_ADC_SOC_NO) #define HS_TEMP_FB_ADC_MODULE ADCA_BASE #define HS_TEMP_FB_ADC_PIN ADC_CH_ADCIN10 #define HS_TEMP_FB_ADC_SOC_NO ADC_SOC_NUMBER1 #define HS_TEMP_FB_ADCRESULTREGBASE ADCARESULT_BASE #define HS_TEMP_FB_ADCREAD ADC_readResult(HS_TEMP_FB_ADCRESULTREGBASE, \ HS_TEMP_FB_ADC_SOC_NO)
By using this INIT function and rest of the code we are getting random values for ADCC module( adc sensing values:tzFOC.fIphu_Cur,tzFOC.fIphv_Cur,tzFOC.fIphw_Cur) . Can you please help us to resolve this issue.
Hello,
I see you're reading from same ADC for all three phase currents.
tzFOC.fIphu_Cur = ((float32_t) IPHU_CUR_FB_ADCREAD - 2266.0f) * PhCur_ADCPU_CONS*Ibase;
tzFOC.fIphv_Cur = ((float32_t) IPHU_CUR_FB_ADCREAD - 2266.0f) * PhCur_ADCPU_CONS*Ibase;
tzFOC.fIphw_Cur = ((float32_t) IPHU_CUR_FB_ADCREAD - 2266.0f) * PhCur_ADCPU_CONS*Ibase;
I suggest you to check TI's reference designs to get some picture in mind about the configuration.
Best Regards,
Masoud