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.

TMS320F28377S: eQEP , encoder for tms320f28377s

Part Number: TMS320F28377S
Other Parts Discussed in Thread: C2000WARE

Can you explain the problem in the GPIO initialization for eQEP because the position_now  is not getting updated , I have been debugging it but not able to find the speed.

#include "F28x_Project.h"
#include "math.h"
#define SYS_CLK 200000000
#define PI 3.14159265358979323846
void Setup_GPIO();
void initEQEP();
void InitEQep1Gpio();
void delay_loop();
uint16_t value1 = 0;
uint16_t value2 = 0;
uint16_t value3 = 0;
uint16_t value4 = 0;

int spcnt = 0;
float wr_mech = 0;
float RAD_PER_COUNT = 0.000785;// Encoder pulses per revolution
float lPrevPos = 0;
float lNowPos = 0 ;
int B= 0;
float lDifference = 0;
// uint32_t pulseCount = 0;

extern interrupt void cpu_timer0_isr(void);
int a=0;
void main(void)
{
// Initialize system clocks, GPIOs, and other necessary peripherals

// Initialize eQEP module
InitGpio();
//ENCODER
// GPIO_SetupPinMux(105 , GPIO_MUX_CPU1 , 0);
// GPIO_SetupPinOptions(105 , GPIO_OUTPUT , GPIO_PUSHPULL);
// GpioDataRegs.GPDSET.bit.GPIO105 = 1;

initEQEP();
InitSysCtrl();
// InitEQep1Gpio();
DINT;

// Setup the ADCs for software conversions

InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EALLOW;
PieVectTable.TIMER0_INT = &cpu_timer0_isr;
EDIS;
InitCpuTimers();
ConfigCpuTimer(&CpuTimer0,200,100);
CpuTimer0Regs.TCR.all = 0x4000;
IER |= M_INT1;
IER |= M_INT3;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
EINT;
ERTM;
while(1)
{

}
}
float ReadEncoder ()
{
float position_now;
position_now = EQep1Regs.QPOSCNT;
return position_now;
}
void InitEQep1Gpio()
//{
//// // pg 959 Table Mux, pg 965 Registers and spruhm8i.pdf - Technical reference
EALLOW;
//
// GpioCtrlRegs.GPAMUX1.all = 0;
// GpioCtrlRegs.GPAMUX2.all = 0;
//// GpioCtrlRegs.GPAPUD.bit.GPIO20 = 1; // Disable pull-up on GPIO10 (EQEP1A)
//// GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0; // Sync GPIO10 to SYSCLK (EQEP1A)
GpioCtrlRegs.GPAGMUX2.bit.GPIO20 = 1; // Configure GPIO6 as EQEP1A
//// GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1; // Configure GPIO6 as EQEP1A
////
//// GpioCtrlRegs.GPAPUD.bit.GPIO21 = 1; // Disable pull-up on GPIO7 (EQEP1B)
//// GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0; // Sync GPIO7 to SYSCLK (EQEP1B)
GpioCtrlRegs.GPAGMUX2.bit.GPIO21= 1; // Configure GPIO7 as EQEP1B
//// GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1; // Configure GPIO7 as EQEP1B
////
//// GpioCtrlRegs.GPAPUD.bit.GPIO22 = 1; // Disable pull-up on GPIO7 (EQEP1B)
//// GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0; // Sync GPIO7 to SYSCLK (EQEP1B)
GpioCtrlRegs.GPAGMUX2.bit.GPIO22= 1; // Configure GPIO7 as EQEP1B
//// GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1; // Configure GPIO7 as EQEP1B
////
//// GpioCtrlRegs.GPAPUD.bit.GPIO23 = 1; // Disable pull-up on GPIO9 (EQEP1I)
//// GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0; // Sync GPIO9 to SYSCLK (EQEP1I)
GpioCtrlRegs.GPAGMUX2.bit.GPIO23 = 1; // Configure GPIO9 as EQEP1I
//// GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1; // Configure GPIO9 as EQEP1I
//// EDIS;
//
//
// Enable internal pull-up for the selected pins.

GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0; // Enable pull-up on GPIO20 (EQEP1A)
GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0; // Enable pull-up on GPIO21 (EQEP1B)
GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0; // Enable pull-up on GPIO22 (EQEP1S)
GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0; // Enable pull-up on GPIO23 (EQEP1I)

// Inputs are synchronized to SYSCLKOUT by default.

GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0; // Sync to SYSCLKOUT GPIO20 (EQEP1A)
GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0; // Sync to SYSCLKOUT GPIO21 (EQEP1B)
GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0; // Sync to SYSCLKOUT GPIO22 (EQEP1S)
GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0; // Sync to SYSCLKOUT GPIO23 (EQEP1I)

// Configure eQEP-1 pins using GPIO regs
GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1; // Configure GPIO20 as EQEP1A
GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1; // Configure GPIO21 as EQEP1B
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1; // Configure GPIO22 as EQEP1S
GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1; // Configure GPIO23 as EQEP1I
// value1 = GpioDataRegs.GPADAT.bit.GPIO20 ;
// value2= GpioDataRegs.GPADAT.bit.GPIO21 ;
// value3 = GpioDataRegs.GPADAT.bit.GPIO22 ;
// value4 = GpioDataRegs.GPADAT.bit.GPIO23 ;

EDIS;
}
//

void initEQEP()
{
// CPUSysRegs.PCLKCR4.bit.EQEP1ENCLK = 1;
EQep1Regs.QUPRD = SYS_CLK ; // Unit timer period for 100Hz frequency (arbitrary, adjust as needed)
EQep1Regs.QDECCTL.bit.QSRC = 1; // Quadrature direction count mode
// EQep1Regs.QDECCTL.bit.QSP = 0; // 1x resolution (default)
EQep1Regs.QEPCTL.bit.FREE_SOFT = 2; // Run on emulation suspend
EQep1Regs.QDECCTL.bit.XCR = 0; // 0 for rising/falling edge . 1 for rising edge only also XCR = 1x resolution
// EQep1Regs.QDECCTL.bit.SWAP = 1; // 0 for no change. 1 for swap A and B.

EQep1Regs.QEPCTL.bit.PCRM = 2; // Position counter reset 0 means reset on index, 1 means reset once max ,
// 2 mean reset on first index , 3 mean reset on a unit time event
EQep1Regs.QEPCTL.bit.QCLM = 1; // Latch on unit time out
EQep1Regs.QEPCTL.bit.UTE = 1;
// Unit Timer Enable
EQep1Regs.QPOSINIT = 0;
EQep1Regs.QPOSMAX = 0xFFFFFFFF; //desired maximum count
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

}

//void dalcSpeed(float lEncCount)
//{
//
// wr_mech = lEncCount*RAD_PER_COUNT/(10);

extern interrupt void cpu_timer0_isr()
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
lNowPos = ReadEncoder();
a++;
spcnt++;
if(spcnt>9)
{ B++;
lDifference = lNowPos - lPrevPos;
wr_mech = lDifference *RAD_PER_COUNT*1000;
lPrevPos = lNowPos;
spcnt = 0;
}
// pulseCount = EQep1Regs.QPOSCNT; // Read the pulse count
// motorSpeed = pulseCount * 60 * SYS_CLK / (ENCODER_PPR * EQep1Regs.QPOSCNT); // Calculate motor speed in RPM

// Clear interrupt flags if necessary
// EQep1Regs.QCLR.bit.UTO = 1;
}

  • Hi SWAPNIL,

    Are you starting with our C2000Ware examples? We have several examples calculating the speed measurment in RPM. The examples can be found within our C2000Ware SDK located at C:\ti\c2000\C2000Ware_x_xx_xx_xx\device_support\f2837xs\examples\cpu1\eqep_pos_speed\cpu01\Eqep_pos_speed.c

    Please refer to these for the GPIO setup.

    Best,

    Ryan Ma

  • Thanks for the reply Ryan Ma,

    I have tried the eqep_posspeed example by making changes according to my requirements the program is even getting build but still no outputs although I have removed the EPWM part as I don't need to simulate the signals.I have posted the code can you please take a look and get back to me

    //
    #include "F28x_Project.h"
    #include "Example_posspeed.h"
    int samplingtime = 100;
    //

    //
    // Globals
    //
    POSSPEED qep_posspeed=POSSPEED_DEFAULTS;
    Uint16 Interrupt_Count = 0;

    //
    // Function Prototypes
    //
    //void initEpwm();
    interrupt void TIMER1_ISR(void);

    //
    // Main
    //
    void main(void)
    {
    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xS_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xS_Gpio.c file and
    // illustrates how to set the GPIO to its default state.
    //
    // InitGpio(); // Skipped for this example

    //
    // For this case only init GPIO for eQEP1 and ePWM1
    // This function is found in F2837xS_EQep.c
    //
    InitEQep1Gpio();
    // InitEPwm1Gpio();
    EALLOW;
    GpioCtrlRegs.GPADIR.bit.GPIO4 = 1; // GPIO4 as output simulates Index signal
    GpioDataRegs.GPACLEAR.bit.GPIO4 = 1; // Normally low
    EDIS;

    //
    // Step 3. Clear all __interrupts and initialize PIE vector table:
    // Disable CPU __interrupts
    //
    DINT;

    //
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE __interrupts disabled and flags
    // are cleared.
    // This function is found in the F2837xS_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Disable CPU __interrupts and clear all CPU __interrupt flags:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the __interrupt
    // is not used in this example. This is useful for debug purposes.
    // The shell ISR routines are found in F2837xS_DefaultIsr.c.
    // This function is found in F2837xS_PieVect.c.
    //
    InitPieVectTable();

    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.TIMER1_INT = &TIMER1_ISR;
    EDIS; // This is needed to disable write to EALLOW protected registers
    InitCpuTimers();
    ConfigCpuTimer(&CpuTimer1,200,samplingtime);
    CpuTimer1Regs.TCR.all = 0x4000;
    //
    // Step 4. Initialize all the Device Peripherals:
    //
    //initEpwm(); // This function exists in Example_EPwmSetup.c

    //
    // Step 5. User specific code, enable __interrupts:
    // Enable CPU INT1 which is connected to CPU-Timer 0:
    //
    IER |= M_INT3;

    //
    // Enable TINT0 in the PIE: Group 3 __interrupt 1
    //
    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;

    //
    // Enable global Interrupts and higher priority real-time debug events:
    //
    EINT; // Enable Global __interrupt INTM
    ERTM; // Enable Global realtime __interrupt DBGM

    qep_posspeed.init(&qep_posspeed);

    for(;;)
    {
    }
    }
    void InitEQep1Gpio()
    {


    GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0; // Enable pullup on GPIO20
    GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0; // Enable pullup on GPIO21
    GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0; // Enable pullup on GPIO22
    GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0; // Enable pullup on GPIO23
    GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0; // Synch to SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0; // Synch to SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0; // Synch to SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0; // Synch to SYSCLKOUT
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1; // GPIO20 = EQEP1A
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1; // GPIO21 = EQEP1B
    GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1; // GPIO22 = EQEP1S
    GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1; // GPIO23 = EQEP1I
    EDIS;
    }

    //
    // prdTick - EPWM1 Interrupts once every 4 QCLK counts (one period)
    //
    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;
    _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

    }

    interrupt void TIMER1_ISR(void)
    { PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    Uint16 i;

    //
    // Position and Speed measurement
    //
    qep_posspeed.calc(&qep_posspeed);

    //
    // Control loop code for position control & Speed control
    //
    Interrupt_Count++;

    //
    // Every 1000 __interrupts(4000 QCLK counts or 1 rev.)
    //
    if (Interrupt_Count==1000)
    {
    EALLOW;
    GpioDataRegs.GPASET.bit.GPIO4 = 1; // Pulse Index signal (1 pulse/rev.)
    for (i=0; i<700; i++)
    {
    }
    GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;
    Interrupt_Count = 0; // Reset count
    EDIS;
    }

    //
    // Acknowledge this __interrupt to receive more __interrupts from group 1
    //

    // EPwm1Regs.ETCLR.bit.INT=1;
    }

  • Does the example work as expected for you? Does the ePWM simulated signals work with the eQEP? If that works then there must be some issue with the input signals coming into your GPIOs.

    If the example works, instead of passing in the EPWM signals to the eQEP inputs, can you connect your signals to the same GPIOs?

    Best,

    Ryan Ma