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.

TMS320F280025C: digital loop control

Part Number: TMS320F280025C

Hi,

I would like to have your opinion concerning a regulation in a first step in open loop I perform the timing of the ADC via a PWM then a reading of the ADC via an interrupt triggered on an EOC.

I would like to include in a first step the averaging in another ISR. I see that the method is to set the interrupts via timer. I do it otherwise I trigger another interrupt via GPIO (putting an ouput in the ADC ISR and an input in the XINT ISR). Is this the right way to do it ?

Because if I use the timer, how to clock the timer with the end of the ADC interrupt ?

I'm going to establish a CAN communication to talk with a user interface afterwards so in this case I can use a CAN interrupt.
Last question, averaging is very greedy in cycle, should I do averaging or work in instantaneous with filtering and actions of the corrector ? You can see my code, if you have suggestions.

Thanks,

Damien

#include "config.h"
#include "input_users.h"
#include "driverlib.h"
#include "utils.h"
#include "device.h"
#include "variable.h"
#include "corrector.h"
#include "filter.h"

void epwm_init(uint32_t);
void cmpss_actions();
void cmpss_init();
void µc_config();
void adc_config(uint32_t);
void adc_run(void);
void device_config(void);
void regul();
void init_epwm_soc(uint32_t);
void init_adc_soc(void);
void average(void);

__interrupt void isr_adc(void);
__interrupt void isr_xint1(void);

uint16_t pointer_isr_adc = 0;
uint16_t adc_index_isr = 0;

void main(void)
{
    // Device config
    device_config();

    µc_config();

    // Disable sync and clock to PWM
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    epwm_init(myEPWM1_BASE);
    epwm_init(myEPWM2_BASE);
    epwm_init(myEPWM3_BASE);

    // Configure and actions CMPSS
    cmpss_init(CMPSS1_BASE);
    cmpss_init(CMPSS2_BASE);
    cmpss_init(CMPSS3_BASE);

    cmpss_actions(myEPWM1_BASE);
    cmpss_actions(myEPWM2_BASE);
    cmpss_actions(myEPWM3_BASE);

    // Interrupts that are used (la fonction isr_adc sera appelée dans un contexte d'interruption). See PIE Channel Mapping in Peripheral Interrupts doc
    Interrupt_register(INT_ADCC1, &isr_adc);
    Interrupt_register(INT_XINT1, &isr_xint1);

    // Set up the ADC / ePWM SOC and initialize the end of conversion
    adc_config(ADCA_BASE);
    adc_config(ADCC_BASE);
    init_epwm_soc(myEPWM4_BASE);
    init_adc_soc();

    // Enable interrupt
    Interrupt_enable(INT_ADCC1);
    Interrupt_enable(INT_XINT1);

    // Initialize results buffer
    for(adc_index = 0; adc_index < SAMPLES; adc_index++)
    {
        Vout_samples[adc_index] = 0;
        Vin_samples[adc_index] = 0;
        Is_boost_1[adc_index] = 0;
        Is_boost_2[adc_index] = 0;
        Is_boost_3[adc_index] = 0;
        Drv_u[adc_index] = 0;
        Drv_v[adc_index] = 0;
        Drv_w[adc_index] = 0;
    }

    adc_index = 0;

    // Enable sync and clock to PWM
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    EINT;
    ERTM;

    while(1)
    {
        // Wait while eWPM4 causes conversion and if trip zone is set shoot down ePWM

        // Trip flag is set when CTRIP signal is asserted
        if((EPWM_getTripZoneFlagStatus(myEPWM1_BASE) & EPWM_TZ_FLAG_DCBEVT1) != 0U || (EPWM_getTripZoneFlagStatus(myEPWM2_BASE) & EPWM_TZ_FLAG_DCBEVT1) != 0U || (EPWM_getTripZoneFlagStatus(myEPWM3_BASE) & EPWM_TZ_FLAG_DCBEVT1) != 0U)
        {
            // Clear trip flags
            EPWM_clearTripZoneFlag(myEPWM1_BASE, EPWM_TZ_FLAG_DCBEVT1 | EPWM_TZ_FLAG_OST);
            EPWM_clearTripZoneFlag(myEPWM2_BASE, EPWM_TZ_FLAG_DCBEVT1 | EPWM_TZ_FLAG_OST);
            EPWM_clearTripZoneFlag(myEPWM3_BASE, EPWM_TZ_FLAG_DCBEVT1 | EPWM_TZ_FLAG_OST);
        }
    }
}

void device_config(void)
{
    // Initialize device clock and peripherals
    Device_init();

    // Disable pin locks and enable internal pullups.
    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();
}

void epwm_init(uint32_t base)
{
    float PWM_TBPRD_1;
    float PWM_TBPRD_2;
    float PWM_TBPRD_3;
    float PWM_TBPRD_4;
    float PWM_CMPA_1;
    float PWM_CMPA_2;
    float PWM_CMPA_3;
    float PWM_CMPA_4;
    EPWM_ClockDivider PWM_PARAM_PRESCALER;
    EPWM_HSClockDivider PWM_PARAM_HIGHSPEEDPRESCALER;
    float TBCLK;

    if(base == myEPWM1_BASE)
    {
        // Parameters
        EPWM_setTimeBaseCounterMode(base, MODE_COUNT);
        get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_TBPRD_4 ,&PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_CMPA_4 ,&PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
        EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_1);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_1);
        EPWM_setClockPrescaler(base, PWM_PARAM_PRESCALER, PWM_PARAM_HIGHSPEEDPRESCALER);
        // Set up shadowing
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

        if(MODE_COUNT == EPWM_COUNTER_MODE_UP)
        {
            // Set actions
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        }
        else if(MODE_COUNT == EPWM_COUNTER_MODE_UP_DOWN)
        {
            // Set actions
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
        }

        // Configure ePMWs
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setPhaseShift(base, 0U);
        EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
    }

    else if (base == myEPWM2_BASE)
    {
        // Parameters
        EPWM_setTimeBaseCounterMode(base, MODE_COUNT);
        get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_TBPRD_4 ,&PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_CMPA_4 ,&PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
        EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_2);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_2);
        EPWM_setPhaseShift(base, 0U);
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setClockPrescaler(base, PWM_PARAM_PRESCALER, PWM_PARAM_HIGHSPEEDPRESCALER);
        // Set up shadowing
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

        if(MODE_COUNT == EPWM_COUNTER_MODE_UP)
        {
            // Set actions
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        }
        else if(MODE_COUNT == EPWM_COUNTER_MODE_UP_DOWN)
        {
            // Set actions
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
        }

        set_phase(base, myEPWM1_BASE, PHI);
        EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
        EPWM_enablePhaseShiftLoad(base);
    }

    else if(base == myEPWM3_BASE)
    {
        // Parameters
        EPWM_setTimeBaseCounterMode(base, MODE_COUNT);
        get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_TBPRD_4 ,&PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_CMPA_4 ,&PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
        EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_3);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_3);
        EPWM_setPhaseShift(base, 0U);
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setClockPrescaler(base, PWM_PARAM_PRESCALER, PWM_PARAM_HIGHSPEEDPRESCALER);
        // Set up shadowing
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

        if(MODE_COUNT == EPWM_COUNTER_MODE_UP)
        {
            // Set actions
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        }
        else if(MODE_COUNT == EPWM_COUNTER_MODE_UP_DOWN)
        {
            // Set actions
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
            EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
        }

        set_phase(base, myEPWM1_BASE, PHI);
        EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
        EPWM_enablePhaseShiftLoad(base);
    }
}

void cmpss_init(base)
{
    // Enable CMPSS and configure the negative input signal to come from the DAC
    CMPSS_enableModule(base);

    // Use VDDA as the reference for the DAC and set DAC value to midpoint for arbitrary reference.
    CMPSS_configDAC(base, CMPSS_DACREF_VDDA);

    // Configure the output signals. Both CTRIPH will be fed by the asynchronous comparator output.
    //1
    CMPSS_configHighComparator(base, CMPSS_INSRC_DAC);      // Threshold drive by GPIO or input DAC
    CMPSS_setDACValueHigh(base, 1024);                      // Define threshold
    CMPSS_configOutputsHigh(base, CMPSS_TRIP_SYNC_COMP);    // Set output comparator (synchronous or asynchronous)
    //2
    CMPSS_configLowComparator(base, CMPSS_INSRC_DAC);       // Threshold drive by GPIO or input DAC
    CMPSS_setDACValueLow(base, 1024);                       // Define threshold
    CMPSS_configOutputsLow(base, CMPSS_TRIP_SYNC_COMP);     // Set output comparator (synchronous or asynchronous)
}

void cmpss_actions(base)
{
    // Configure ePWMx to output low on TZx TRIP
    EPWM_setTripZoneAction(base, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(base, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_LOW);

    // Trigger event when DCBH is high
    EPWM_setTripZoneDigitalCompareEventCondition(base, EPWM_TZ_DC_OUTPUT_B1, EPWM_TZ_EVENT_DCXH_HIGH);

    // Configure DCBH to use TRIP4 as an input
    EPWM_enableDigitalCompareTripCombinationInput(base, EPWM_DC_COMBINATIONAL_TRIPIN4, EPWM_DC_TYPE_DCBH);

    // Enable DCB as OST
    EPWM_enableTripZoneSignals(base, EPWM_TZ_SIGNAL_DCBEVT1);

    //AIO224 -> myAIO0 Pinmux
    GPIO_setPinConfig(GPIO_224_GPIO224);
    //AIO230 -> myAIO1 Pinmux
    GPIO_setPinConfig(GPIO_230_GPIO230);
    //AIO226 -> myAIO2 Pinmux
    GPIO_setPinConfig(GPIO_226_GPIO226);
    // To use CMP1_HP0
    ASysCtl_selectCMPLPMux(ASYSCTL_CMPLPMUX_SELECT_1, 0);
    // To use CMP2_HP3
    ASysCtl_selectCMPHPMux(ASYSCTL_CMPHPMUX_SELECT_2, 3);
    // To use CMP3_HP0
    ASysCtl_selectCMPHPMux(ASYSCTL_CMPHPMUX_SELECT_3, 0);

    // Configure TRIP4 to be CTRIP1H using the ePWM X-BAR. Attach CMPSS output to TRIPINx via EPWMXBAR module
    XBAR_setEPWMMuxConfig(XBAR_TRIP4, XBAR_EPWM_MUX01_CMPSS1_CTRIPL);
    XBAR_setEPWMMuxConfig(XBAR_TRIP4, XBAR_EPWM_MUX02_CMPSS2_CTRIPH);
    XBAR_setEPWMMuxConfig(XBAR_TRIP4, XBAR_EPWM_MUX04_CMPSS3_CTRIPH);

    // See the ePWM X-BAR Mux configuration table, see Crossbar(X-BAR) doc for more informations
    XBAR_enableEPWMMux(XBAR_TRIP4, XBAR_MUX01 | XBAR_MUX02 | XBAR_MUX04);

    // Clear trip flags
    EPWM_clearTripZoneFlag(base, EPWM_TZ_FLAG_DCBEVT1);
}

void µc_config()
{
    EALLOW;

    //EPWM1 -> myEPWM1 Pinmux
    GPIO_setPinConfig(GPIO_0_EPWM1_A);
    GPIO_setPinConfig(GPIO_1_EPWM1_B);
    //EPWM2 -> myEPWM2 Pinmux
    GPIO_setPinConfig(GPIO_2_EPWM2_A);
    GPIO_setPinConfig(GPIO_3_EPWM2_B);
    //EPWM3 -> myEPWM3 Pinmux
    GPIO_setPinConfig(GPIO_4_EPWM3_A);
    GPIO_setPinConfig(GPIO_15_EPWM3_B);
    //EPWM4 -> myEPWM4 Pinmux
    GPIO_setPinConfig(GPIO_6_EPWM4_A);

    // level pin to enter in isr_adc (level 0 to enter in isr_xint1)
    GPIO_setPinConfig(GPIO_40_GPIO40);
    GPIO_setDirectionMode(40, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(40, GPIO_PIN_TYPE_STD);

    // input pin (connect GPIO40 to GPIO42)
    GPIO_setPinConfig(GPIO_42_GPIO42);
    GPIO_setDirectionMode(42, GPIO_DIR_MODE_IN);
    GPIO_setPadConfig(42, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(42, GPIO_QUAL_SYNC);
    GPIO_setInterruptPin(42,GPIO_INT_XINT1);
    // Falling edge interrupt
    GPIO_setInterruptType(GPIO_INT_XINT1, GPIO_INT_TYPE_FALLING_EDGE);
    // Enable XINT1
    GPIO_enableInterrupt(GPIO_INT_XINT1);

    // To visualize isr_xint1 with toggle pin
    GPIO_setPinConfig(GPIO_27_GPIO27);
    GPIO_setDirectionMode(27, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(27, GPIO_PIN_TYPE_STD);

    EDIS;
}

void adc_config(uint32_t adc_base)
{
    // Enable ADC
    ADC_setVREF(adc_base, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);

    ADC_setPrescaler(adc_base, ADC_CLK_DIV_1_0);

    // Set pulse ADCINTx at the end of conversion
    ADC_setInterruptPulseMode(adc_base, ADC_PULSE_END_OF_CONV);

    ADC_enableConverter(adc_base);

    //Delay to allow ADC time to power up
    DEVICE_DELAY_US(ADC_POWERUP_US);
}

void init_epwm_soc(uint32_t base)
{
    float PWM_TBPRD_1;
    float PWM_TBPRD_2;
    float PWM_TBPRD_3;
    float PWM_TBPRD_4;
    float PWM_CMPA_1;
    float PWM_CMPA_2;
    float PWM_CMPA_3;
    float PWM_CMPA_4;
    EPWM_ClockDivider PWM_PARAM_PRESCALER;
    EPWM_HSClockDivider PWM_PARAM_HIGHSPEEDPRESCALER;
    float TBCLK;

    // Disable SOCA
    EPWM_disableADCTrigger(base, EPWM_SOC_A);

    // Configure the SOC to occur on the first up-count event
    EPWM_setADCTriggerSource(base, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);

    // To set ADCCLK
    EPWM_setADCTriggerEventPrescale(base, EPWM_SOC_A, ADC_SOC_COUNT);

    // Parameters
    get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_TBPRD_4 ,&PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_CMPA_4 ,&PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
    EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_4);
    EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_4);
    EPWM_setPhaseShift(base, 0U);
    EPWM_disablePhaseShiftLoad(base);
    EPWM_setClockPrescaler(base, PWM_PARAM_PRESCALER, PWM_PARAM_HIGHSPEEDPRESCALER);

    // Set actions
    EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);

    // Set in phase with ePWM1
    set_phase(base, myEPWM1_BASE, 0);
    EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
    EPWM_enablePhaseShiftLoad(base);

    // Start ePWM4, enabling SOCA and putting the counter in up-count mode
    EPWM_setTimeBaseCounterMode(base, MODE_COUNT_SOC);

    EPWM_enableADCTrigger(base, EPWM_SOC_A);
}

void init_adc_soc(void)
{
    // Corresponding module ADCx -> SOC -> pin. Enchainement des SOC une fois la conversion terminée sur un SOC.SOC0 will start at 1 / PWM_SOC_FREQ and an another SOC0 at 1 / PWM_SOC_FREQ after.
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM4_SOCA, VOUT_ADC_PIN, VOUT_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM4_SOCA, VIN_ADC_PIN, VIN_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM4_SOCA, IS_BOOST_1_ADC_PIN, IS_BOOST_1_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCC_BASE, ADC_SOC_NUMBER3, ADC_TRIGGER_EPWM4_SOCA, IS_BOOST_2_ADC_PIN, IS_BOOST_2_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM4_SOCA, IS_BOOST_3_ADC_PIN, IS_BOOST_3_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER1, ADC_TRIGGER_EPWM4_SOCA, DRV_U_ADC_PIN, DRV_U_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER2, ADC_TRIGGER_EPWM4_SOCA, DRV_V_ADC_PIN, DRV_V_ADC_ACQPS_WINDOW);
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER3, ADC_TRIGGER_EPWM4_SOCA, DRV_W_ADC_PIN, DRV_W_ADC_ACQPS_WINDOW);

    // Corresponding EOC to ADCINTX pulse to enter on interrupt for read ADCRESULTx registers. Refer to ADCINTSEL1N2 and ADCRESULTx registers.
    ADC_setInterruptSource(ADCC_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER3);

    ADC_enableInterrupt(ADCC_BASE, ADC_INT_NUMBER1);

    ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);
}

__interrupt void isr_adc(void) // Enter on interrupt when SOC3 on ADCC will end. Enter on interrupt when EOC3 is set 1 / PWM_SOC_FREQ
{
    // Set GPIO type output
    GPIO_writePin(40, 1);

    // Circular buffer
    pointer_isr_adc = (SAMPLES - adc_index_isr) % SAMPLES;

    Vout_samples[pointer_isr_adc] = Vout_read();
    Vin_samples[pointer_isr_adc] = Vin_read();
    Is_boost_1[pointer_isr_adc] = Is_boost_1_read();
    Is_boost_2[pointer_isr_adc] = Is_boost_2_read();
    Is_boost_3[pointer_isr_adc] = Is_boost_3_read();
    Drv_u[pointer_isr_adc] = Drv_u_read();
    Drv_v[pointer_isr_adc] = Drv_v_read();
    Drv_w[pointer_isr_adc] = Drv_w_read();

    adc_index_isr = (adc_index_isr + 1) % SAMPLES;

    // Clear the interrupt flag
    ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);

    // Check if overflow has occurred
    if(ADC_getInterruptOverflowStatus(ADCC_BASE, ADC_INT_NUMBER1) == true)
    {
        ADC_clearInterruptOverflowStatus(ADCC_BASE, ADC_INT_NUMBER1);
        ADC_clearInterruptStatus(ADCC_BASE, ADC_INT_NUMBER1);
    }

    // Acknowledge the interrupt, see PIE Interrupt Vectors table
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);

    GPIO_writePin(40, 0);
}

__interrupt void isr_xint1(void)
{
    GPIO_writePin(27, 1);

    average();
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);

    GPIO_writePin(27, 0);
}

void average(void)
{
    Vout_average = average_Vout(Vout_samples);
    Vin_average = average_Vin(Vin_samples);
    Is_boost_1_average = average_Is_boost_1(Is_boost_1);
    Is_boost_2_average = average_Is_boost_2(Is_boost_2);
    Is_boost_3_average = average_Is_boost_3(Is_boost_3);
    Drv_u_average = average_Drv_u(Drv_u);
    Drv_v_average = average_Drv_v(Drv_v);
    Drv_w_average = average_Drv_w(Drv_w);
}

  • Hi Damien,

    I cannot tell from your code how fast signal sampling is, or how fast the EPWM triggers are happening.  Sorry, I got a bit lost in the EPWM setup, but what I can tell from your  ADC setup is that you are sampling 8 signals/channels and have assigned one SOC each per signal on ADCA and ADCC (basically 4 signals per ADC).  There are 16 available SOCs per ADC module so one quick suggestion is to spread the SOCs to all the signals that you are sampling, for instance:

                VOUT_ADC_PIN-> assign to ADCC SOC0-3

                VIN_ADC_PIN-> assign to ADCC SOC4-7

                IS_BOOST_1_ADC_PIN-> assign to ADCC SOC8-11

                IS_BOOST_2_ADC_PIN-> assign to ADCC SOC12-15

                IS_BOOST_3_ADC_PIN-> assign to ADCA SOC0-3

                DRV_U_ADC_PIN-> assign to ADCA SOC4-7

                DRV_V_ADC_PIN-> assign to ADCA SOC8-11

                DRV_W_ADC_PIN-> assign to ADCA SOC12-15

    At the moment trigger for conversion on these signals is just coming from ADC_TRIGGER_EPWM4_SOCA.  You probably can modify the EPWM setup to trigger independent conversion of these signals or in groups, depending on how fast you want the sampling to be.  The point to distributing the samples to the available SOCs is to get more samples (oversampling) per signal, for instance, a conversion trigger for VOUT_ADC_PIN from the above SOC allocation will populate the ADC results in corresponding ADCC ADRESULT0-3 where you can sum up the results and shift it right by 2 and attain an averaging (oversampling) by 4.  You can process the results in the ISR and make it more efficient.  It also looks like there is only one ADC ISR used in the code.  You can add independent ISR to each ADC as well to make processing more efficient.  Let me know if this helps.

    Regards,

    Joseph