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.

How to use ENC + QEP modules to measure motor speed by an Incremental Encoder?

Other Parts Discussed in Thread: MOTORWARE, CONTROLSUITE, TMS320F28069M

Dear Motorware team,

I'm trying to read motor speed which is used by an Encoder (1024 pulses per revolution and the output signals are A, B and Z). I referenced the lab12a, b and included two  modules (qep.h/qep.c and enc.h/enc.c) in my project and used the following functions in order to get the speed info from the encoder. 

So that, I declared in user.h

#elif (USER_MOTOR == My_Motor_ACIM)
#define USER_MOTOR_TYPE                 MOTOR_Type_Induction
#define USER_MOTOR_NUM_POLE_PAIRS       (2)						//!> PAIRS, not total poles. Used to calculate user RPM from rotor Hz only
#define USER_MOTOR_Rr                   (0.9621)				//!> Identified phase to neutral in a Y equivalent circuit (Ohms, float)
#define USER_MOTOR_Rs                   (1.05)					//!> Identified phase to neutral in a Y equivalent circuit (Ohms, float)
#define USER_MOTOR_Ls					(0.0842)
#define USER_MOTOR_Ls_d                 (0.0842)				//!> For Induction, Identified average stator inductance  (Henry, float)
#define USER_MOTOR_Ls_q                 (0.0842)				//!> For Induction, Identified average stator inductance  (Henry, float)
#define USER_MOTOR_RATED_VOLTAGE		(350)					//!> The rated volate of the motor
#define USER_MOTOR_RATED_FREQ_Hz		(52.7)					//!> The rated frequency of the motor
#define USER_MOTOR_RATED_FLUX           (0.8165*350.0/52.7)			//!> The rated flux = sqrt(2/3)* Rated V (line-line) / Rated Freq (Hz)
#define USER_MOTOR_MAGNETIZING_CURRENT  (7.2509)				//!> Identified magnetizing current for induction motors, else NULL
#define USER_MOTOR_RES_EST_CURRENT      (1.0)					//!> During Motor ID, maximum current (Amperes, float) used for Rs estimation, 10-20% rated current
#define USER_MOTOR_IND_EST_CURRENT      (NULL)					//!> Must be ZERO/NULL for ACIM motors
#define USER_MOTOR_MAX_CURRENT          (13.0)					//!> Max. nameplate current of the motor.
																//!> CRITICAL: Used during ID and run-time, sets a limit on the maximum current command output of the provided Speed PI Controller to the Iq controller
#define USER_MOTOR_FLUX_EST_FREQ_Hz     (5.0)					//!> For IPM, set to 20.0Hz; for ACIM, set to 5.0Hz
#define USER_MOTOR_ENCODER_LINES        (1024.0)				//!> Added by Duongtb (24-Mar-2016)
#define USER_MOTOR_MAX_SPEED_KRPM       (3.0)					//!> Added by Duongtb (24-Mar-2016)
#define USER_SYSTEM_INERTIA             (0.02)					//!> Added by Duongtb (24-Mar-2016)
#define USER_SYSTEM_FRICTION            (0.01)					//!> Added by Duongtb (24-Mar-2016)

In the HAL_setupGpios() function, I set up:

  // GPIO-20: PIN FUNCTION = EQEPA
  GPIO_setMode(obj->gpioHandle,GPIO_Number_20,GPIO_20_Mode_EQEP1A);
  GPIO_setQualification(obj->gpioHandle,GPIO_Number_20,GPIO_Qual_Sample_3);

  // GPIO-21: PIN FUNCTION = EQEPB
  GPIO_setMode(obj->gpioHandle,GPIO_Number_21,GPIO_21_Mode_EQEP1B);
  GPIO_setQualification(obj->gpioHandle,GPIO_Number_21,GPIO_Qual_Sample_3);

  // GPIO-23: PIN FUNCTION = EQEP1I
  GPIO_setMode(obj->gpioHandle,GPIO_Number_23,GPIO_23_Mode_EQEP1I);
  GPIO_setQualification(obj->gpioHandle,GPIO_Number_23,GPIO_Qual_Sample_3);

In the main() function, I setup:

halHandle = HAL_init(&hal,sizeof(hal));

// set the hardware abstraction layer parameters
HAL_setParams(halHandle,&gUserParams);

//!> initialize and setup the Encoder modude - Added by Duongtb (24-Mar-2016)
{
        // initialize the ENC module
	encHandle = ENC_init(&enc, sizeof(enc));

	// setup the ENC module
	ENC_setup(encHandle,
			1,
			USER_MOTOR_NUM_POLE_PAIRS,
			USER_MOTOR_ENCODER_LINES,
			0,
			USER_IQ_FULL_SCALE_FREQ_Hz,
			USER_ISR_FREQ_Hz,
			8000.0);
}

Notice that, the QEP_init() function is called in HAL_init() as following:

//! \Brief Initializes all Hardware Drives that is used in the project.
HAL_Handle HAL_init(void *pMemory,const size_t numBytes)
{
  uint_least8_t cnt;
  HAL_Handle handle;
  HAL_Obj *obj;
...
#ifdef QEP
  // initialize QEP driver
  obj->qepHandle[0] = QEP_init((void*)QEP1_BASE_ADDR,sizeof(QEP_Obj));
#endif
...

return;
}

and the QEP_setup() is called in the HAL_setupparams() as following:

//! \Brief Setting up the parameters which is used in every module of HAL
void HAL_setParams(HAL_Handle handle,const USER_Params *pUserParams)
{
  uint_least8_t cnt;
  HAL_Obj *obj = (HAL_Obj *)handle;
  _iq beta_lp_pu = _IQ(pUserParams->offsetPole_rps/(float_t)pUserParams->ctrlFreq_Hz);

...
#ifdef QEP
  // setup the QEP
  HAL_setupQEP(handle,HAL_Qep_QEP1);
#endif
...
return;
}

In the mainISR() function, I called:

	// compute the electrical angle which is get from Encoder
	ENC_calcElecAngle(encHandle, HAL_getQepPosnCounts(halHandle));

	// get the feedback speed in kilo rpm
	gMotorVars.Speed_krpm = ENC_getSpeedRPM(encHandle);

However, when I run motor in debug mode, I always see the value of gMotorVars.Speed_krpm = ZERO???

I think it maybe I have not know how to use two modules to get the right result, although I checked the A, B and Z signals on my hardware and the result is good.

Could you please guide me to resolve this problem.

Many thanks,

Mr. Tran

  • Hello,

    Anybody was successful in using ENC/QEP modules with F28054F to get exact speed motor info?

    Please help me to resolve the above problem.

    Many thanks.
  • Tran,

    The function ENC_calcElecAngle only calculates the motor electrical angle.  It does not calculate the motor speed.  In the enc.c file there is an additional function which will calculate the motor speed.

  • Hi Adam,

    Thank you for your guiding. I used the ENC_calcElecAngle() function is based on referring to the code in Lab12a, b. I looked deeply in the enc.h/enc.c and found that, it maybe I should use the function:

    void ENC_run(ENC_Handle encHandle, uint32_t posnCounts, uint16_t indextFlag, uint16_t dirFlag, int16_t log_flag);

    But I don't know how to use this function, I must put what parameters into this function? Because  I tried an call of this function as following:

    //! mainISR() function
    interrupt void mainISR(void)
    {
    
    ....
      // run the ENC module
      ENC_run(encHandle,
    		  HAL_getQepPosnCounts(halHandle),
    		  true,
    		  true,
    		  true);
    
    
      // get the speed from eQEP
      gMotorVars.SpeedQEP_krpm = _IQmpy(ENC_getSpeedRPM(encHandle), _IQ(1/1000.0));
    
    ...
    return;
    }

    but I still got the ZERO in the result of reading the motor speed!!!

    Could you please show me an example to use this function, and if you can, please explain me more the mean of every parameters which need to put in?

    Many thanks

  • Tran,

    I'm not too familiar with that function either.  I only use the ENC_calElecAngle function since SpinTAC Position Converter is used to calculate speed for the MOTION projects.  

    I believe that in order to use that function you should be be using passing flags from the QEP driver into the ENC module.  

    But even if the flags were set to true it probably should have calculated a speed.  My guess is that the ENC module may not be initialized in order to do the speed calculation.  Look inside the ENC_run function for the speed calculation and see what variables it uses and make sure that all of those are configured.  

    You might need one of the TIers in order to help answer this questions since I really only support the MOTION labs.

  • Hi Adam,

    I also understand that ENC_calElecAngle() function is only available when it accompany with SpinTAC functions. Unfortunately, I don't have F28054M or F2069M, we only develop my product with InstaSPIN-FOC DSP such as F28027F/F28054F. So that I cannot use SpinTAC for Position/Motion control.

    I only need for speed of the motor to complete the sensored speed control loop with FOC.

    Although I am very thankful you when you spent your time to discuss this problem with me.

    I must wait for someone else at TI to support this issue.

    Have a nice weekend to you.

  • all of the ENC_ APIs can work with all Piccolo devices.

    I've tagged this for Brett (our encoder expert) to look at.
  • Dear Chris,

    Thanks a lot for your help.

    I hope I will understand clearly the ENC module and apply it successfully in my project.

    Have a nice week to you!

  • Hi Tran Binh Duong,

    To help determine whether this issue is (A) a peripheral configuration problem or (B) a software usage problem, can you try the below?

    While your project is running, can you view the Registers window and see if eQEP1->QPOSCNT changes value as the encoder moves?


    Thank you,
    Brett

  • Dear Brett,

    Thank you so much for regarding to my problem.

    I can verify that the problem (A) is not the cause. Because I checked my hardware as well as peripheral with a controlSUITE project and make sure that there is no issue in here. I also checked the content of the register eQEP1->QPOSCNT in the debug window while the motor running, and verify that its value changed as the encoder rotate.

    But I don't understand your mean when regarding to "a software usage problem". What do you mean?You can read the usage of ENC/QEP module which I described above. 

    Please look at the description and tell me where am I wrong?

    PS: I guess Mr. Chris introduced my problem to you, so that please convey my thanks to him.

  • Hi Tran,

    First off, I am knowledgeable about the C2000's QEP and encoders, but am less aware of the MotorWare functions and API.  As a result, please be a bit patient with my advice.

    1) If you set a breakpoint within ENC_run (from enc.c), does enc->enc_elec_angle ever get updated (line 202 of MotorWare 1_01_00_16)
    2) Are you initializing the various variables that this function uses?

    Please be aware that I do not believe this function has been utilized too often by our team.  I believe that there are improvements that can be made.


    Thank you,
    Brett

  • Dear Brett,

    Thank you for your reply. I'm sorry about reply you late because I must go out of my office for two weeks, and now I return to my job. 

    I set up the ENC module as following:

    	// initialize the ENC module
    	encHandle = ENC_init(&enc, sizeof(enc));
    
    	// setup the ENC module
    	ENC_setup(encHandle,
    				1,
    				USER_MOTOR_NUM_POLE_PAIRS,
    				USER_MOTOR_ENCODER_LINES,
    				0,
    				USER_IQ_FULL_SCALE_FREQ_Hz,
    				USER_ISR_FREQ_Hz,
    				8000.0);
    

    I check the operation of ENC_run() function (in the module enc.c) and verify that to get the result, we need to call the function as following:

        // run the ENC module
        ENC_run(encHandle,
        		HAL_getQepPosnCounts(halHandle),
        		QEP_read_posn_index_latch(halHandle->qepHandle[0]),
        		QEP_read_dir(halHandle),
        		true);
    

    and then, get the result by putting the code lines in the main-loop:

        // get the real speed (in pu) from Encoder
        // notes: Added by Duongtb (5-Apr-2016)
        gMotorSpeedQEP_pu = ENC_getFilteredSpeed(encHandle);
    
        // get the real speed (rpm) from eQEP/Encoder
        // notes: Added by Duongtb (5-Apr-2016)
        gMotorSpeedQEP_rpm = (uint32_t)(ENC_getSpeedRPM(encHandle));

    However, according to my observation, the speed info which is get by ENC_getFilteredSpeed(encHandle) function was not stable, its value continues to change with big gap, although the speed of the motor is checked by a meter is stable. On the other hand, I checked the result of reading the speed info by a example of ControlSUITE, and the result is stable.

    So that, I think that the API functions in Motorware for ENCODER interface is not reliable.

    What did you check the operation of the Motorware functions?

    Waiting for your reply,

  • Dear all,

    I fixed the error which relates to reading speed of motor using ENC module. The problem is in setting the parameter for ENC_setup().

    According to Motorware's example:

    //!> initialize and setup the Encoder modude - Added by Duongtb (24-Mar-2016)
    {
            // initialize the ENC module
        encHandle = ENC_init(&enc, sizeof(enc));
    
        // setup the ENC module
        ENC_setup(encHandle,
                1,
                USER_MOTOR_NUM_POLE_PAIRS,
                USER_MOTOR_ENCODER_LINES,
                0,
                USER_IQ_FULL_SCALE_FREQ_Hz,
                USER_ISR_FREQ_Hz,
                8000.0);
    }

    But due to setting sample_period = 1 as above, an unstable result of speed will be received. If we setup the true value for this parameter, we will get the stable result of speed.

    //! \brief Defines the Encoder parameters
    #define USER_MOTOR_ENCODER_LINES        (1024.0)				//!> Number of lines on the motor's quadrature encoder
    #define USER_ENC_SAMPLE_PERIOD          (USER_ISR_FREQ_Hz/USER_NUM_PWM_TICKS_PER_ISR_TICK)/(USER_MOTOR_MAX_SPEED_KRPM*1000/60 *2)
    
    // setup the ENC module
    ENC_setup(encHandle,
    	USER_ENC_SAMPLE_PERIOD,
    	USER_MOTOR_NUM_POLE_PAIRS,
    	USER_MOTOR_ENCODER_LINES,
    	0,
    	USER_IQ_FULL_SCALE_FREQ_Hz,
    	USER_ISR_FREQ_Hz,
    	8000.0);
    

    Beside we also put the right parameter for the ENC_run() which is called in the main_ISR() as following:

        // run the ENC module
        ENC_run(encHandle,
        		HAL_getQepPosnCounts(halHandle),
        		HAL_getQepIndex(halHandle),
        		HAL_getQepDirection(halHandle),
        		true);

    where, we need to add two following function in hal.h file

    #ifdef QEP
    //! \brief 		Return the index info from the QEP module
    //! \param[in] encHandle                        Handle to the ENC object
    //! \return		The flag that indicate the index of encoder (true or false)
    inline uint16_t HAL_getQepIndex(HAL_Handle handle)
    {
    	HAL_Obj *obj = (HAL_Obj *)handle;
    
    	return (uint16_t)((QEP_QEPSTS_FIMF & QEP_read_status(obj->qepHandle[0]))>>1);
    }
    
    //! \brief 		Return the direction info from the QEP module
    //! \param[in] encHandle                        Handle to the ENC object
    //! \return		The flag that indicate the direction of rotation (true or false)
    inline uint16_t HAL_getQepDirection(HAL_Handle handle)
    {
    	HAL_Obj *obj = (HAL_Obj *)handle;
    
    	//Added by Duongtb (24/4/2016)
    	return (uint16_t)((QEP_QEPSTS_QDF&QEP_read_status(obj->qepHandle[0]))>>5);
    }
    #endif

    That's all!

  •  

    Hello,

    I am using the LaunchPadXL TMS320F28069M and the projects in motorware  for the boostxldrv8301_revB.

    I am trying to get some experience on how to include and get running the encoder module in a new project (enc.c, enc.h, qep.c, qep.h). To do so I started comparing proj_lab12a and proj_lab5c, and add the encoder module in the latter, but with some difficulties...

    1) Somewhere in proj_lab12a "QEP" is defined which enables all the good settings for the encoder module in the relative hal.c. where is this definition? I want to do the same for proj_lab5c, but I cannot find it anywhere I have looked so far.

    2) Even if I get rid of all the controls relative to the definition of QEP (basically following step by step the original "How to use ENC + QEP modules to measure motor speed by an Incremental Encoder?" post and the step by step instruction of the instaspin user manual section 18 sensored system) I am failing to compile because the ENC_Handle and ENC_Obj look to be undefined.

    Any advice?

    Thanks in advance

    Lorenzo

     

     

     

     

     

  • lorenzo mazza said:
    1) Somewhere in proj_lab12a "QEP" is defined which enables all the good settings for the encoder module in the relative hal.c. where is this definition? I want to do the same for proj_lab5c, but I cannot find it anywhere I have looked so far.

    It is defined in the project settings under Project Properties -> Build -> C2000 Compiler -> Advanced Options -> Predefined Symbols.

    lorenzo mazza said:
    2) Even if I get rid of all the controls relative to the definition of QEP (basically following step by step the original "How to use ENC + QEP modules to measure motor speed by an Incremental Encoder?" post and the step by step instruction of the instaspin user manual section 18 sensored system) I am failing to compile because the ENC_Handle and ENC_Obj look to be undefined.

    I'm assuming you are missing the include for the enc.h header file.

  • Hello Adam,

    thank you very much for your reply.

    Yes, I was missing the enc.h header file in ctrl.h.

    Regards

    lorenzo