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.

Inaccurate Speed measurement in 28335

Other Parts Discussed in Thread: TMS320F28335

Hi everyone!


I intend to perform FOC on 4 pole three phase motors using TMS320F28335. I am facing problems getting a constant speed. I edited the lab 6 example and included the eQEP.c file and initialized the eQEP registers as follows:

EQep1Regs.QDECCTL.bit.QSRC=00;        // QEP quadrature count mode
EQep1Regs.QEPCTL.bit.FREE_SOFT=2;
EQep1Regs.QEPCTL.bit.PCRM=01;

EQep1Regs.QPOSMAX=0xffffffff;
EQep1Regs.QEPCTL.bit.QPEN=1;         // QEP enable

In the timer ISR I calculate the velocity as follows:

   //Unfiltered

    p_new=(unsigned int)EQep1Regs.QPOSCNT; 
    Pos0 = (p_new*2*pi)/4096.0;
    Vel0 = (Pos0-Pos1)/0.0001;
    Pos1 = Pos0;

//filtered
    FPos0 = (p_new*2*pi)/4096.0;
    FVel0 = (FVel1 + g*FPos0 - g*FPos1)/(g*0.0001 + 1);
    FPos1 = FPos0;
    FVel1 = FVel0;


the sinusoidal angular frequency is 62.8 and I expect the measured speed to be 31.4 rad/s and the interrupt timer frequency is 10KHz.

The problem that I am facing is that I dont get a constant speed. 5 in 10 values are 31.4 and rest are 15 rad/s or 60 rad/s and 1 in 10 is a negative value as well. I tried the 2-3 different filters and with that too I do not get a constant value. With the filters the speed is continuously changing from 20 to 35 rad/s. I am observing at 100ms in the debug window and I get a count of 4096 from the encoder for one complete rotation.

Could you please let me know where I might be going wrong. I also tried with the inbuilt speed measurement code and it too gave similar results.

Thanks,

//
//      Lab5_1: TMS320F28335
//      (c) Frank Bormann
//
//###########################################################################
//
// FILE:	Lab5_1.c
//
// TITLE:	DSP28335ControlCARD; Digital Output
//			4 - bit - counter at 4 LEDs LD1(GPIO9), LD2(GPIO11), LD3(GPIO34)
//			and LD4 (GPIO49)
//			software delay loop; watchdog disabled
//			template file for Lab5_1
//###########################################################################
//  Ver | dd mmm yyyy | Who  | Description of changes
// =====|=============|======|===============================================
//  3.0 | 02 May 2008 | F.B. | Lab5_1 for F28335;
//  3.1 | 06 Nov 2009 | F.B  | Lab5_1 for F28335 and PE revision5
//###########################################################################
#include "DSP2833x_Device.h"
#include "math.h"
// Prototype statements for functions found within this file.
void Gpio_select(void);
void InitSystem(void);

extern void InitSysCtrl(void);

extern void InitPieCtrl(void);
extern void InitPieVectTable(void);

extern void InitCpuTimers(void);
interrupt  void cpu_timer0_isr(void);
extern void ConfigCpuTimer(struct CPUTIMER_VARS *, float, float);

void Setup_ePWM();
extern void InitEQep1Gpio(void);

float d1=0,d2=0,d3=0,t=0,f=10,i=0;
float p_old=0,Pos0,Pos1,Vel0,Vel1;
unsigned int p_new=0;
float FPos0,FPos1,FVel0,FVel1,g=100;

#define DT  10e-5
#define pi  3.1415926535
//###########################################################################
//						main code
//###########################################################################
void main(void)
{

	InitSysCtrl();

	EALLOW;
	SysCtrlRegs.WDCR = 0x00AF;
	EDIS;

	DINT;				// Disable all interrupts
	
	Gpio_select();		// GPIO9,GPIO11,GPIO34 and GPIO49 as output (LEDs @ peripheral explorer)

	Setup_ePWM();

	InitPieCtrl();
	InitPieVectTable();

	EALLOW;
	PieVectTable.TINT0 = &cpu_timer0_isr;
	EDIS;

	InitCpuTimers();
	ConfigCpuTimer(&CpuTimer0, 150, 100);
	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;

	InitEQep1Gpio();


    EQep1Regs.QDECCTL.bit.QSRC=00;		// QEP quadrature count mode

    EQep1Regs.QEPCTL.bit.FREE_SOFT=2;
    EQep1Regs.QEPCTL.bit.PCRM=01;		// PCRM=00 mode - QPOSCNT reset on index event

    EQep1Regs.QEPCTL.bit.QCLM=1; 		// Latch on unit time out*/
    EQep1Regs.QPOSMAX=0xffffffff;
    EQep1Regs.QEPCTL.bit.QPEN=1; 		// QEP enable


	IER |= 1;
	EINT;
	ERTM;
	CpuTimer0Regs.TCR.bit.TSS = 0;

	while(1)
	{

		EALLOW;
		SysCtrlRegs.WDKEY = 0x55;	// service WD #1
		EDIS;

	}
}

void cpu_timer0_isr()
{
	CpuTimer0.InterruptCount=CpuTimer0.InterruptCount+1;

	EALLOW;
	SysCtrlRegs.WDKEY = 0xAA;	// service WD #2
	EDIS;

	p_new=(unsigned int)EQep1Regs.QPOSCNT;  //unsigned
	Pos0 = (p_new*2*pi)/4096.0;
	Vel0 = (Pos0-Pos1)/0.0001;
	Pos1 = Pos0;

	FPos0 = (p_new*2*pi)/4096.0;
	FVel0 = (FVel1 + g*FPos0 - g*FPos1)/(g*0.0001 + 1);
	FPos1 = FPos0;
	FVel1 = FVel0;

    d1=3600+3600*sin(2*pi*f*t);
    d2=3600+3600*sin(2*pi*f*t-(2*pi)/3);
    d3=3600+3600*sin(2*pi*f*t+(2*pi)/3);
    t=t+DT;

    EPwm1Regs.CMPA.half.CMPA = (int) d1;
    EPwm2Regs.CMPA.half.CMPA = (int) d2;
    EPwm3Regs.CMPA.half.CMPA = (int) d3;
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}



void Gpio_select(void)
{
	EALLOW;

		GpioCtrlRegs.GPADIR.all = 0;

		GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;	// ePWM1A active
		GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;	// ePWM3A active
		GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 1;	// ePWM4A active

		EDIS;
}

void Setup_ePWM(void)
{
	EPwm1Regs.TBCTL.bit.CLKDIV =  0;	// CLKDIV = 1
	EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;	// HSPCLKDIV = 1
	EPwm1Regs.TBCTL.bit.CTRMODE = 0; //CTRMODE, 00 = count up mode

	EPwm1Regs.TBCTL.bit.SYNCOSEL = 3;  //SYNCOSEL, 11 = sync-out disabled
	EPwm1Regs.TBCTL.bit.PRDLD = 0; // PRDLD, 0 = reload PRD on counter=0
	EPwm1Regs.TBCTL.bit.PHSEN = 0x0; //PHSEN, 0 = phase control disabled
	EPwm1Regs.TBCTL.bit.FREE_SOFT = 3; //FREE/SOFT, 11 = ignore emulation suspend
	EPwm1Regs.TBCTL.bit.SWFSYNC = 0; //SWFSYNC, 0 = no software sync produced

	EPwm1Regs.TBPRD = 7500;				// 20 KHz - PWM signal
	EPwm1Regs.CMPA.half.CMPA = 1875; // set compare value
	d1=3750;  // initiaze duty value

    EPwm1Regs.AQCTLA.all = 0x0012;	//Set ePWM high when counter =0 and low when counter = compare value

	EPwm1Regs.ETPS.all = 0x100; //SOC on first event
	EPwm1Regs.ETSEL.all = 0xA00; // Enable SOC A and start of conversion when counter = period

	EPwm2Regs.TBCTL.bit.CLKDIV =  0;	// CLKDIV = 1
	EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0;	// HSPCLKDIV = 1

	EPwm2Regs.TBCTL.bit.CTRMODE = 0; //CTRMODE, 00 = count up mode

	EPwm2Regs.TBCTL.bit.SYNCOSEL = 3; //SYNCOSEL, 11 = sync-out disabled
	EPwm2Regs.TBCTL.bit.PRDLD = 0; // PRDLD, 0 = reload PRD on counter=0
	EPwm2Regs.TBCTL.bit.PHSEN = 0x0; //PHSEN, 0 = phase control disabled
	EPwm2Regs.TBCTL.bit.FREE_SOFT = 3; //FREE/SOFT, 11 = ignore emulation suspend
	EPwm2Regs.TBCTL.bit.SWFSYNC = 0; //SWFSYNC, 0 = no software sync produced

	EPwm2Regs.TBPRD = 7500;				// 20 KHz - PWM signal
	EPwm2Regs.CMPA.half.CMPA = 1875; // set compare value
	d2=3750; // initiaze duty value
    EPwm2Regs.AQCTLA.all = 0x0012; //Set ePWM high when counter =0 and low when counter = compare value


	EPwm3Regs.TBCTL.bit.CLKDIV =  0;	// CLKDIV = 1
	EPwm3Regs.TBCTL.bit.HSPCLKDIV = 0;	// HSPCLKDIV = 1
	//EPwm1Regs.TBCTL.bit.CTRMODE = 2;
	EPwm3Regs.TBCTL.bit.CTRMODE = 0; //CTRMODE, 00 = count up mode

	EPwm3Regs.TBCTL.bit.SYNCOSEL = 3;  //SYNCOSEL, 11 = sync-out disabled
	EPwm3Regs.TBCTL.bit.PRDLD = 0; // PRDLD, 0 = reload PRD on counter=0
	EPwm3Regs.TBCTL.bit.PHSEN = 0x0; //PHSEN, 0 = phase control disabled
	EPwm3Regs.TBCTL.bit.FREE_SOFT = 3;  //FREE/SOFT, 11 = ignore emulation suspend
	EPwm3Regs.TBCTL.bit.SWFSYNC = 0; //SWFSYNC, 0 = no software sync produced

	EPwm3Regs.TBPRD = 7500;				// 20 KHz - PWM signal
	EPwm3Regs.CMPA.half.CMPA = 1875; // set compare value
	d3=3750;  // initiaze duty value

    EPwm3Regs.AQCTLA.all = 0x0012;	//Set ePWM high when counter =0 and low when counter = compare value
}

//===========================================================================
// End of SourceCode.
//===========================================================================

  • Shoaib,

    If you compare your interrupt frequency with the quadrature clock frequency at this speed (40.96kHz) you'll see the average count change will be 4.096.  This means most of the time the interrupt will see four count difference since the last measurement, but sometimes will see five.  When the count difference is five, the current speed measurement will be higher and the next speed measurement lower.  I think the negative readings are probably when the counter wraps round, so Pos0-Pos1 is negative.  Basically, your ISR frequency is too close to the quadrature clock rate to get reliable speed measurement this way.

    Regards,

    Richard 

  • Thanks for the reply!

    As I intend to implement FOC the speed will be changing but the maximum I will be going is 60 rad/s. I was able to solve the problem of negative speed. I added a code just after the QPOS update to check if the new value is greater than the previous value and calculate the speed only if it is greater. But I still have inconsistent speed measurement but as you mentioned it is because the difference in count (Pos0-Pos1) in consecutive ISR's

    I guess I should measure the time interval between two consecutive pulses them then calculate speed accordingly.

    Thanks,
  • Shoaib,

    Yes, I think that would be a better approach.  There is a unit timer in the QEP module which can be configured to latch the position counter into the QPOSLAT register.  Your code can check the UTO bit in the QFLG register to see if there is a new value.

    Typically anglular information is required for FOC, but speed is used in an outer control loop with lower bandwidth.  You may be able to reduce the rate at which you're gathering speed information which will make it easier to get an accurate measurement.

    I hope this helps.

    Regards,

    Richard