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: eQEP

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

I struggling to measure the angle and the phase using eQEP module.

I went through some examples in F2837xD for qep, but I cant understand where is the count period defined. As I know we need to define the count, the clock cycle. The positionangle.c file informs about the procedure how the angle and the phase is calculated but i did not see any calculation in the code.

Also if I dont want to include (my eQEP calculation inside EPWM1 interrupt, rather on eQEP interrupt), then how to do it....

I try to find a lot relevant examples but could not get any help.

I need to implement, SVPWM on F28x4x series, So I need some support in this regard.

Can someone please upload some sample examples on eQEP. And also some more examples related to SVPWM or any proper web source....

  • //
    // FILE: Example_posspeed.c
    //
    // TITLE: Pos/speed measurement using EQEP peripheral
    //
    // DESCRIPTION:
    //
    // This file includes the EQEP initialization and position and speed
    // calculation functions called by Eqep_posspeed.c. The position and speed
    // calculation steps performed by POSSPEED_Calc() at SYSCLKOUT = 200 MHz are
    // described below:
    //
    // 1. This program calculates: **theta_mech**
    //
    // theta_mech = QPOSCNT/mech_Scaler = QPOSCNT/4000, where 4000 is the number
    // of counts in 1 revolution.
    // (4000/4 = 1000 line/rev. quadrature encoder)
    //
    // 2. This program calculates: **theta_elec**
    //
    // theta_elec = (# pole pairs) * theta_mech = 2*QPOSCNT/4000
    //
    // 3. This program calculates: **SpeedRpm_fr**
    //
    // SpeedRpm_fr = [(x2-x1)/4000]/T - Equation 1
    // Note (x2-x1) = difference in number of QPOSCNT counts. Dividing (x2-x1)
    // by 4000 gives position relative to Index in one revolution.
    // If base RPM = 6000 rpm: 6000 rpm = [(x2-x1)/4000]/10ms - Equation 2
    // = [(x2-x1)/4000]/(.01s*1 min/60 sec)
    // = [(x2-x1)/4000]/(1/6000) min
    // max (x2-x1) = 4000 counts, or 1 revolution in 10 ms
    //
    //
    // If both sides of Equation 2 are divided by 6000 rpm, then:
    // 1 = [(x2-x1)/4000] rev./[(1/6000) min * 6000rpm]
    // Because (x2-x1) must be <4000 (max) for QPOSCNT increment,
    // (x2-x1)/4000 < 1 for CW rotation
    // And because (x2-x1) must be >-4000 for QPOSCNT decrement,
    // (x2-x1)/4000>-1 for CCW rotation
    // speed_fr = [(x2-x1)/4000]/[(1/6000) min * 6000rpm]
    // = (x2-x1)/4000 - Equation 3
    //
    // To convert speed_fr to RPM, multiply Equation 3 by 6000 rpm
    // SpeedRpm_fr = 6000rpm *(x2-x1)/4000 - Final Equation
    //
    // 2. **min rpm ** = selected at 10 rpm based on CCPS prescaler options
    // available (128 is greatest)
    //
    // 3. **SpeedRpm_pr**
    // SpeedRpm_pr = X/(t2-t1) - Equation 4
    // where X = QCAPCTL [UPPS]/4000 rev. (position relative to Index in
    // 1 revolution)
    // If max/base speed = 6000 rpm:
    // 6000 = (32/4000)/[(t2-t1)/(200MHz/64)]
    // where 32 = QCAPCTL [UPPS] (Unit timeout - once every 32 edges)
    // 32/4000 = position in 1 revolution (position as a fraction
    // of 1 revolution)
    // t2-t1/(200MHz/64), t2-t1= # of QCAPCLK cycles, and
    // QCAPCLK cycle = 1/(200MHz/64)
    // = QCPRDLAT
    //
    // So: 6000 rpm = [32(200MHz/64)*60s/min]/[4000(t2-t1)]
    // t2-t1 = [32(200MHz/64)*60s/min]/(4000*6000rpm) - Equation 5
    // = 250 CAPCLK cycles = maximum (t2-t1) = SpeedScaler
    //
    // Divide both sides by (t2-t1), and:
    // 1 = 32/(t2-t1) = [32(200MHz/64)*60 s/min]/(4000*6000rpm)]/(t2-t1)
    // Because (t2-t1) must be < 250 for QPOSCNT increment:
    // 250/(t2-t1) < 1 for CW rotation
    // And because (t2-t1) must be >-250 for QPOSCNT decrement:
    // 250/(t2-t1)> -1 for CCW rotation
    //
    // eed_pr = 250/(t2-t1)
    // or [32(200MHz/64)*60 s/min]/(4000*6000rpm)]/(t2-t1) - Equation 6
    //
    // To convert speed_pr to RPM:
    // Multiply Equation 6 by 6000rpm:
    // SpeedRpm_fr = 6000rpm * [32(200MHz/64)*60 s/min]/[4000*6000rpm*(t2-t1)]
    // = [32(200MHz/64)*60 s/min]/[4000*(t2-t1)]
    // or [(32/4000)rev * 60 s/min]/[(t2-t1)(QCPRDLAT)]-Final Equation
    //
    // More detailed calculation results can be found in the Example_freqcal.xls
    // spreadsheet included in the example folder.
    //
    // This file contains source for the posspeed module
    //
    //###########################################################################
    // $TI Release: F2837xD Support Library v210 $
    // $Release Date: Tue Nov 1 14:46:15 CDT 2016 $
    // $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
    // http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    //
    // Included Files
    //
    #include "F28x_Project.h"
    #include "Example_posspeed.h"
    
    //
    // POSSPEED_Init - Initialize EQEP1 configuration
    //
    void POSSPEED_Init(void)
    {
    EQep1Regs.QUPRD = 2000000; // Unit Timer for 100Hz at 200 MHz
    // SYSCLKOUT
    EQep1Regs.QDECCTL.bit.QSRC = 00; // QEP quadrature count mode
    EQep1Regs.QEPCTL.bit.FREE_SOFT = 2;
    EQep1Regs.QEPCTL.bit.PCRM = 00; // PCRM=00 mode - QPOSCNT reset on
    // index event
    EQep1Regs.QEPCTL.bit.UTE = 1; // Unit Timeout Enable
    EQep1Regs.QEPCTL.bit.QCLM = 1; // Latch on unit time out
    EQep1Regs.QPOSMAX = 0xffffffff;
    EQep1Regs.QEPCTL.bit.QPEN = 1; // QEP enable
    EQep1Regs.QCAPCTL.bit.UPPS = 5; // 1/32 for unit position
    EQep1Regs.QCAPCTL.bit.CCPS = 6; // 1/64 for CAP clock
    EQep1Regs.QCAPCTL.bit.CEN = 1; // QEP Capture Enable
    }
    
    //
    // POSSPEED_Calc - Perform the position calculations
    //
    void POSSPEED_Calc(POSSPEED *p)
    {
    long tmp;
    unsigned int pos16bval,temp1;
    _iq Tmp1,newp,oldp;
    
    //
    // Position calculation - mechanical and electrical motor angle
    //
    p->DirectionQep = EQep1Regs.QEPSTS.bit.QDF; // Motor direction:
    // 0=CCW/reverse, 1=CW/forward
    
    pos16bval = (unsigned int)EQep1Regs.QPOSCNT; // capture position once
    // per QA/QB period
    p->theta_raw = pos16bval+ p->cal_angle; // raw theta = current pos. +
    // ang. offset from QA
    
    //
    // The following lines calculate
    // p->theta_mech ~= QPOSCNT/mech_scaler [current cnt/(total cnt in 1 rev.)]
    // where mech_scaler = 4000 cnts/revolution
    //
    tmp = (long)((long)p->theta_raw*(long)p->mech_scaler); // Q0*Q26 = Q26
    tmp &= 0x03FFF000;
    p->theta_mech = (int)(tmp>>11); // Q26 -> Q15
    p->theta_mech &= 0x7FFF;
    
    //
    // The following lines calculate p->elec_mech
    //
    p->theta_elec = p->pole_pairs*p->theta_mech; // Q0*Q15 = Q15
    p->theta_elec &= 0x7FFF;
    
    //
    // Check an index occurrence
    //
    if(EQep1Regs.QFLG.bit.IEL == 1)
    {
    p->index_sync_flag = 0x00F0;
    EQep1Regs.QCLR.bit.IEL = 1; // Clear __interrupt flag
    }
    
    //
    // High Speed Calculation using QEP Position counter
    //
    // Check unit Time out-event for speed calculation:
    // Unit Timer is configured for 100Hz in INIT function
    //
    if(EQep1Regs.QFLG.bit.UTO == 1) // If unit timeout (one 100Hz period)
    {
    //
    // Differentiator
    //
    // The following lines calculate
    // position = (x2-x1)/4000 (position in 1 revolution)
    //
    pos16bval = (unsigned int)EQep1Regs.QPOSLAT; // Latched POSCNT value
    tmp = (long)((long)pos16bval*(long)p->mech_scaler); // Q0*Q26 = Q26
    tmp &= 0x03FFF000;
    tmp = (int)(tmp>>11); // Q26 -> Q15
    tmp &= 0x7FFF;
    newp = _IQ15toIQ(tmp);
    oldp = p->oldpos;
    
    if(p->DirectionQep==0) // POSCNT is counting down
    {
    if(newp>oldp)
    {
    Tmp1 = - (_IQ(1) - newp + oldp); // x2-x1 should be negative
    }
    else
    {
    Tmp1 = newp -oldp;
    }
    }
    else if(p->DirectionQep == 1) // POSCNT is counting up
    {
    if(newp<oldp)
    {
    Tmp1 = _IQ(1) + newp - oldp;
    }
    else
    {
    Tmp1 = newp - oldp; // x2-x1 should be positive
    }
    }
    
    if(Tmp1>_IQ(1))
    {
    p->Speed_fr = _IQ(1);
    }
    else if(Tmp1<_IQ(-1))
    {
    p->Speed_fr = _IQ(-1);
    }
    else
    {
    p->Speed_fr = Tmp1;
    }
    
    //
    // Update the electrical angle
    //
    p->oldpos = newp;
    
    //
    // Change motor speed from pu value to rpm value (Q15 -> Q0)
    // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
    //
    p->SpeedRpm_fr = _IQmpy(p->BaseRpm,p->Speed_fr);
    
    EQep1Regs.QCLR.bit.UTO=1; // Clear __interrupt flag
    }
    
    //
    // Low-speed computation using QEP capture counter
    //
    if(EQep1Regs.QEPSTS.bit.UPEVNT == 1) // Unit position event
    {
    if(EQep1Regs.QEPSTS.bit.COEF == 0) // No Capture overflow
    {
    temp1 = (unsigned long)EQep1Regs.QCPRDLAT; // temp1 = t2-t1
    }
    else // Capture overflow, saturate the result
    {
    temp1 = 0xFFFF;
    }
    
    //
    // p->Speed_pr = p->SpeedScaler/temp1
    //
    p->Speed_pr = _IQdiv(p->SpeedScaler,temp1);
    Tmp1 = p->Speed_pr;
    
    if (Tmp1>_IQ(1))
    {
    p->Speed_pr = _IQ(1);
    }
    else
    {
    p->Speed_pr = Tmp1;
    }
    
    //
    // Convert p->Speed_pr to RPM
    //
    if(p->DirectionQep == 0) // Reverse direction = negative
    {
    //
    // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
    //
    p->SpeedRpm_pr = -_IQmpy(p->BaseRpm,p->Speed_pr);
    }
    else // Forward direction = positive
    {
    //
    // Q0 = Q0*GLOBAL_Q => _IQXmpy(), X = GLOBAL_Q
    //
    p->SpeedRpm_pr = _IQmpy(p->BaseRpm,p->Speed_pr);
    }
    
    EQep1Regs.QEPSTS.all = 0x88; // Clear Unit position event flag
    // Clear overflow error flag
    }
    }
    
    //
    // End of file
    //

  • Hi Faiz,

    Thank you for your question!

    I have modified your reply so that the code is in a "Code" section. This makes your code much more readable and prevents a difficult to read thread.

    In the future, you can add any code using the following steps:
    1. In the reply editor, choose "Insert"

    2. Choose "Code"

    3. From the dropdown, choose your programming language

    4. Paste your code in the text box.

    Please also note it is not typical to debug entire code projects in these forums, we focus on debugging issues with the device configuration and otherwise. In the future, please refrain from simply pasting the full code and instead provide a specific location where the issue is suspected.

    In the meantime, I have assigned to relevant expert for your question.

    Regards,

    Vince

  • Okay Vince,

    Thanks for letting me know

  • Hi Faiz,

    Can you let me know where you got the example you posted? There are a few examples using the eQEP peripheral located in our C2000Ware SDK, have you taken a look at these? They overview the process of getting the calculations from the eQEP peripheral. In regards to how to perform the calculations within the eQEP interrupt handler, you will need to use the unit timer. This is shown in eQEP ex4 and ex5 from the SDK.

    Regards,

    Peter

  • Hi Peter,

    I accessed the program from Motor C2000 ware package and could not find where are they defining the channel. All examples there are only using A0 it seems.

    I will search for c2000 sdk and let you know.

    Thanks 

  • Hi Faiz,

    Do you mean MotorWare or the MotorControl SDK? MotorWare is our deprecated SDK, while MotorControl SDK is our currently supported motor control package.

    Once the C2000Ware SDK is installed, you can find the examples at:

    <C2000ware_install_directory>/driverlib/f28004x/examples/eqep

    Regards,

    Peter

  • Yes I have been using motor c2000ware sdk and i cant find where the GPIO is defined for the eqep and where can I change it

    Please find attached code

    //#############################################################################
    //
    // FILE:   eqep_ex2_pos_speed.c
    //
    // TITLE:  Position and Speed Measurement Using eQEP
    //
    //! \addtogroup driver_example_list
    //! <h1> Position and Speed Measurement Using eQEP</h1>
    //!
    //! This example provides position and speed measurement using the
    //! capture unit and speed measurement using unit time out of the eQEP module.
    //! ePWM1 and a GPIO are configured to generate simulated eQEP signals. The
    //! ePWM module will interrupt once every period and call the position/speed
    //! calculation function. This example uses the IQMath library to simplify
    //! high-precision calculations.
    //!
    //! In addition to the main example file, the following files must be included
    //! in this project:
    //! - \b eqep_ex2_calculation.c - contains position/speed calculation function
    //! - \b eqep_ex2_calculation.h - includes initialization values for
    //!                               position/speed structure
    //!
    //! The configuration for this example is as follows
    //! - Maximum speed is configured to 6000rpm (baseRPM)
    //! - Minimum speed is assumed at 10rpm for capture pre-scalar selection
    //! - Pole pair is configured to 2 (polePairs)
    //! - Encoder resolution is configured to 4000 counts/revolution (mechScaler)
    //! - Which means: 4000 / 4 = 1000 line/revolution quadrature encoder
    //!   (simulated by ePWM1)
    //! - ePWM1 (simulating QEP encoder signals) is configured for a 5kHz frequency
    //!   or 300 rpm (= 4 * 5000 cnts/sec * 60 sec/min) / 4000 cnts/rev)
    //!
    //! \b SPEEDRPM_FR: High Speed Measurement is obtained by counting the QEP
    //! input pulses for 10ms (unit timer set to 100Hz).
    //!
    //! \b SPEEDRPM_FR = (Position Delta / 10ms) * 60 rpm
    //!
    //! \b SPEEDRPM_PR: Low Speed Measurement is obtained by measuring time period
    //! of QEP edges. Time measurement is averaged over 64 edges for better results
    //! and the capture unit performs the time measurement using pre-scaled SYSCLK.
    //!
    //! Note that the pre-scaler for capture unit clock is selected such that the
    //! capture timer does not overflow at the required minimum frequency. This
    //! example runs indefinitely until the user stops it.
    //!
    //! For more information about the position/speed calculation see the comments
    //! at the beginning of eqep_ex2_calculation.c and the XLS file provided with
    //! the project, eqep_ex2_calculation.xls.
    //!
    //! \b External \b Connections \n
    //! For External connections, Control Card settings are used by default. To use
    //! launchpad pins for output select them in SysConfig.
    //!
    //! - On controlCARD, Connect GPIO6/eQEP1A to GPIO0/ePWM1A 
    //!   (simulates eQEP Phase A signal)
    //! - On controlCARD, Connect GPIO7/eQEP1B to GPIO1/ePWM1B 
    //!   (simulates eQEP Phase B signal)
    //! - On controlCARD, Connect GPIO9/eQEP1I to GPIO4 
    //!   (simulates eQEP Index Signal)
    //! - On LaunchPad, Connect GPIO35/eQEP1A to GPIO10/ePWM6A 
    //!   (simulates eQEP Phase A signal)
    //! - On LaunchPad, Connect GPIO37/eQEP1B to GPIO11/ePWM6B 
    //!   (simulates eQEP Phase B signal)
    //! - On LaunchPad, Connect GPIO59/eQEP1I to GPIO8 
    //!   (simulates eQEP Index Signal)
    //!
    //! \b Watch \b Variables \n
    //!  - \b posSpeed.speedRPMFR - Speed meas. in rpm using QEP position counter
    //!  - \b posSpeed.speedRPMPR - Speed meas. in rpm using capture unit
    //!  - \b posSpeed.thetaMech  - Motor mechanical angle (Q15)
    //!  - \b posSpeed.thetaElec  - Motor electrical angle (Q15)
    //!
    //
    //#############################################################################
    //
    //
    // $Copyright:
    // Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //#############################################################################
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "IQmathLib.h"
    #include "eqep_ex2_calculation.h"
    #include "board.h"
    
    
    //
    // Defines
    //
    #define TB_CLK    DEVICE_SYSCLK_FREQ        // Time base clock is SYSCLK
    #define PWM_CLK   5000                      // We want to output at 5 kHz
                                                // (300 rpm)
    #define PRD_VAL   (TB_CLK / (PWM_CLK * 2))  // Calculate value period value
                                                // for up-down count mode
    
    // .9999 / 4000 converted to IQ26 fixed point format
    #define MECH_SCALER     16776
    // 2 pole pairs in this example
    #define POLE_PAIRS      2
    // Angular offset between encoder and Phase A
    #define CAL_ANGLE       0
    // See Equation 5 in eqep_ex2_calculation.c
    #define SPEED_SCALER    ((((uint64_t)32 * DEVICE_SYSCLK_FREQ / 64) * 60) / (24000000))
    // Base/max rpm is 6000rpm
    #define BASE_RPM        6000
    
    
    //
    // Function Prototypes
    //
    void initEPWM(void);
    __interrupt void epwmISR(void);
    
    //
    // Globals
    //
    PosSpeed_Object posSpeed =
    {
        0, 0, 0, 0,     // Initialize outputs to zero
        MECH_SCALER,    // mechScaler
        POLE_PAIRS,     // polePairs
        CAL_ANGLE,      // calAngle
        SPEED_SCALER,   // speedScaler
        0,              // Initialize output to zero
        BASE_RPM,       // baseRPM
        0, 0, 0, 0      // Initialize outputs to zero
    };
    
    uint16_t interruptCount = 0;
    //
    // Main
    //
    void main(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();
    
        //
        // Board Initialization
        // Setup eQEP1, configuring the unit timer and quadrature capture units
        // Initialize GPIOs for use as EQEP1A, EQEP1B, and EQEP1I
        //
        Board_init();
    
        //
        // On controlCARD, Initialize GPIO0 to ePWM1A, GPIO1 to ePWM1B, and GPIO4 
        // as an output. (On LaunchPad, use GPIO10 on ePWM6A, GPIO11 on ePWM6B, and 
        // GPIO8 as an output.)
        // They will be used to simulate incoming eQEP Phase A, Phase B, and Index
        // signals respectively.
        //
        GPIO_setPinConfig(DEVICE_GPIO_CFG_EPWMxA);
        GPIO_setPadConfig(DEVICE_GPIO_PIN_EPWMxA, GPIO_PIN_TYPE_STD);
    
        GPIO_setPinConfig(DEVICE_GPIO_CFG_EPWMxB);
        GPIO_setPadConfig(DEVICE_GPIO_PIN_EPWMxB, GPIO_PIN_TYPE_STD);
        
        //
        // Interrupts that are used in this example are re-mapped to ISR functions
        // found within this file.
        //
        Interrupt_register(DEVICE_PERIPHERAL_INT_EPWM, &epwmISR);
    
        //
        // Setup ePWM1 to generate a 5 kHz signal to be an input to the eQEP
        //
        initEPWM();
    
        //
        // Enable interrupts required for this example
        //
        Interrupt_enable(DEVICE_PERIPHERAL_INT_EPWM);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // Loop indefinitely
        //
        while(1)
        {
            ;
        }
    }
    
    //
    // Function to configure ePWM1 to generate a 5 kHz signal.
    //
    void initEPWM(void)
    {
        //
        // Disable the ePWM time base clock before configuring the module
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Set phase shift to 0 and clear the time base counter
        //
        EPWM_setPhaseShift(DEVICE_PERIPHERAL_BASE_EPWM, 0);
        EPWM_setTimeBaseCounter(DEVICE_PERIPHERAL_BASE_EPWM, 0);
    
        //
        // Disable the shadow load; the load will be immediate instead
        //
        EPWM_disableCounterCompareShadowLoadMode(DEVICE_PERIPHERAL_BASE_EPWM,
                                                 EPWM_COUNTER_COMPARE_A);
        EPWM_disableCounterCompareShadowLoadMode(DEVICE_PERIPHERAL_BASE_EPWM,
                                                 EPWM_COUNTER_COMPARE_B);
    
        //
        // Set the compare A value to half the period value, compare B to 0
        //
        EPWM_setCounterCompareValue(DEVICE_PERIPHERAL_BASE_EPWM, 
                                    EPWM_COUNTER_COMPARE_A, PRD_VAL/2);
        EPWM_setCounterCompareValue(DEVICE_PERIPHERAL_BASE_EPWM, 
                                    EPWM_COUNTER_COMPARE_B, 0);
    
        //
        // Set action qualifier behavior on compare A events
        // - EPWM1A --> 1 when CTR = CMPA and increasing
        // - EPWM1A --> 0 when CTR = CMPA and decreasing
        //
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
        //
        // Set action qualifier behavior on compare B events
        // - EPWM1B --> 1 when CTR = PRD and increasing
        // - EPWM1B --> 0 when CTR = 0 and decreasing
        //
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
        EPWM_setActionQualifierAction(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    
        //
        // Enable interrupt when the counter is equal to PRD
        //
        EPWM_setInterruptSource(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_INT_TBCTR_PERIOD);
        EPWM_enableInterrupt(DEVICE_PERIPHERAL_BASE_EPWM);
    
        //
        // Interrupt on first event
        //
        EPWM_setInterruptEventCount(DEVICE_PERIPHERAL_BASE_EPWM, 1);
    
        //
        // Set the time base clock prescaler to /1
        //
        EPWM_setClockPrescaler(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_CLOCK_DIVIDER_1,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Set the period value; don't shadow the register
        //
        EPWM_setPeriodLoadMode(DEVICE_PERIPHERAL_BASE_EPWM, EPWM_PERIOD_DIRECT_LOAD);
        EPWM_setTimeBasePeriod(DEVICE_PERIPHERAL_BASE_EPWM, PRD_VAL);
    
        //
        // Put the time base counter into up-down count mode
        //
        EPWM_setTimeBaseCounterMode(DEVICE_PERIPHERAL_BASE_EPWM,  
                                    EPWM_COUNTER_MODE_UP_DOWN);
    
    
        //
        // Sync the ePWM time base clock
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    }
    
    //
    // ePWM1 ISR--interrupts once every 4 QCLK counts (one period)
    //
     __interrupt void epwmISR(void)
    {
        uint16_t i;
    
        //
        // Position speed and measurement
        //
        PosSpeed_calculate(&posSpeed);
    
    
        //
        // Control loop for position control and speed control
        //
        interruptCount++;
        if(interruptCount == 1000)
        {
            //
            // Pulse index signal (1 pulse/rev)
            //
            GPIO_writePin(DEVICE_GPIO_PIN_IOINDEX, 1);
            for(i = 0; i < 700; i++)
            {
                ;
            }
            GPIO_writePin(DEVICE_GPIO_PIN_IOINDEX, 0);
        }
    
        //
        // Clear interrupt flag and issue ACK
        //
        EPWM_clearEventTriggerInterruptFlag(DEVICE_PERIPHERAL_BASE_EPWM);
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }

  • Hi Faiz,

    This looks like the example from C2000Ware version 4.01.00.00, which uses our SysConfig GUI to configure the C2000 device's modules. You can find the configurations in the eqep_ex2_pos_speed.syscfg file. More information about SysConfig can be found here: https://training.ti.com/sysconfig-development-tool-c2000-real-time-mcus

    If you prefer a driverlib implementation, you will have to use an older version of C2000Ware like version 3.04.00.00 or earlier.

    Regards,

    Peter

  • Hi Peter,

    I will look into it 

    Thanks

  • Hi Faiz,

    Looking forward to your response. I recommend using examples 4 and 5 since these were created specifically for floating point devices, which the TMS320F280049C is. Ex1 and ex2 are ported over from fixed-point devices and hence have to use the IQ math library, which makes the calculations more complex. 

    Regards,

    Peter

  • Hi Peter,

    Really thanks for the guidance. I will go through your recommendation and if there is anything, I will let you know

    Thanks and Regards

    Faiz 

  • My pleasure, Faiz