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.

Getting speed from QEP while running InstaSpin FOC for PMSM Sensorless F28069M

Other Parts Discussed in Thread: CONTROLSUITE

Hi All,

My code is for BLDC sensorless InstaSPIN FOC examle proj lab 05g

To verify the speed estimation I added an encoder and mixed with the example 12a (Sensored (quadrature encoder) feedback with SpinTAC)

but without using SpinTAC

So I added

// 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);

and 

in the main ISR


// compute the electrical angle
ENC_calcElecAngle(encHandle, HAL_getQepPosnCounts(halHandle));

gives me the angle

but to compute the speed what do I have to do ? (I avoid derivating the given angle)

call

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

or ?

in the 12a example it is used with 

  // get the speed from eQEP
  gMotorVars.SpeedQEP_krpm = _IQmpy(STPOSCONV_getVelocityFiltered(stObj->posConvHandle), _IQ(ST_SPEED_KRPM_PER_PU));

but I don't have InstaSPIN, MOTION and SpinTAC

So how to get it

Also, in the ENC_setup, I must specify the enc_zero_offset, this is when the rotor d axis is aligned with the phase a coil ?

can I changed online (encHandle ->enc_zero_offset) with GUI composer variable to see the impact

Thanks

Lotfi

  • I added the following code


    //-------------------------------------------------------------------------------------------------
    // HAL QEP Index add on
    inline uint32_t HAL_read_qep_posn_index_latch (HAL_Handle handle)
    {
    HAL_Obj *obj = (HAL_Obj *)handle;
    #ifdef J5
    QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[1];
    #else
    QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    #endif

    return qep->QPOSILAT; // Reads position counter value index pulse latch register
    }

    and in the mainISR

    // compute the electrical angle
    ENC_calcElecAngle(encHandle, HAL_getQepPosnCounts(halHandle));
    // compute speed
    ENC_run( encHandle, HAL_getQepPosnCounts(halHandle), HAL_read_qep_posn_index_latch(halHandle), 0, false);

    t_SpeedQEP_krpm[t_k] = - ENC_getSpeedRPM( encHandle); // gMotorVars.SpeedQEP_krpm; //debug

    the speed has a low resolution (Encoder of 500 dot per round) and there are many resets

    I think this is because of the 3 last parameters of ENC_run

    I have no documents of that function

    Can anyone tell me how to use this function

    Is there another solution 

    Thanks

  • what do you mean you don't have InstSPIN-MOTION?

    if you use proj_lab12b it is exactly doing what you need.. Speed from the QEP is calculated with

    // get the speed from eQEP
    gMotorVars.SpeedQEP_krpm = _IQmpy(STPOSCONV_getVelocityFiltered(stObj->posConvHandle), _IQ(ST_SPEED_KRPM_PER_PU));
  • I mean I don't want to use InstaSPIN MOTION, only FOC
    (towards 28027F)
    Can You gave me the parameters of

    ENC_run( encHandle, HAL_getQepPosnCounts(halHandle), ??? , ???, false);

    I got a lot of glitches
    wheras the Angle computed by ENC_calcElecAngle(encHandle, HAL_getQepPosnCounts(halHandle));
    is correct
    Thanks
  • 28027F doesn't have an eQEP peripheral, so you won't be able to interface to a standard encoder.
    I assume you are just using the encoder during development and testing, so you can use 28069M
    Our only encoder examples use InstaSPIN-MOTION
  • :-(
    Yes I am using during devlopment and in the future perhaps just one Index to get a top

    So I will chnage my strategy:
    How can I implement a simple ISR on Index of the QEP, then using a timer, I can get the speed (I run over 1000 rpm)
    Is there an example somewhere
    Thanks
  • you can try the encoder examples in controlSUITE where the SPEED_FR macro is used from the DMC Library
    C:\ti\controlSUITE\development_kits\HVMotorCtrl+PfcKit_v2.1\HVPM_Sensored
  • thanks, I tried to decode your example, it seems that it is written in  midway using Direct Register Access and HAL

    My big problem with the HAL API/Library is that I don't see how it interacts with low level (Direct Register Access)

    the example :

    \ti\controlSUITE\device_support\f2806x\v150\F2806x_examples_ccsv5\eqep_pos_speed\

    is interesting also

    but as I am stick with the HAL Hardaware abstraction layer routines like

    #ifdef QEP
    void HAL_setupQEP(HAL_Handle handle,HAL_QepSelect_e qep)
    {
      HAL_Obj   *obj = (HAL_Obj *)handle;
    
    
      // hold the counter in reset
      QEP_reset_counter(obj->qepHandle[qep]);
    
      // set the QPOSINIT register
      QEP_set_posn_init_count(obj->qepHandle[qep], 0);
    
      // disable all interrupts
      QEP_disable_all_interrupts(obj->qepHandle[qep]);
    
      // clear the interrupt flags
      QEP_clear_all_interrupt_flags(obj->qepHandle[qep]);
    
      // clear the position counter
      QEP_clear_posn_counter(obj->qepHandle[qep]);
    
      // setup the max position
      QEP_set_max_posn_count(obj->qepHandle[qep], (4*USER_MOTOR_ENCODER_LINES)-1);
    
      // setup the QDECCTL register
      QEP_set_QEP_source(obj->qepHandle[qep], QEP_Qsrc_Quad_Count_Mode);
      QEP_disable_sync_out(obj->qepHandle[qep]);
      QEP_set_swap_quad_inputs(obj->qepHandle[qep], QEP_Swap_Not_Swapped);
      QEP_disable_gate_index(obj->qepHandle[qep]);
      QEP_set_ext_clock_rate(obj->qepHandle[qep], QEP_Xcr_2x_Res);
      QEP_set_A_polarity(obj->qepHandle[qep], QEP_Qap_No_Effect);
      QEP_set_B_polarity(obj->qepHandle[qep], QEP_Qbp_No_Effect);
      QEP_set_index_polarity(obj->qepHandle[qep], QEP_Qip_No_Effect);
    
      // setup the QEPCTL register
      QEP_set_emu_control(obj->qepHandle[qep], QEPCTL_Freesoft_Unaffected_Halt);
      QEP_set_posn_count_reset_mode(obj->qepHandle[qep], QEPCTL_Pcrm_Max_Reset);
      QEP_set_strobe_event_init(obj->qepHandle[qep], QEPCTL_Sei_Nothing);
      QEP_set_index_event_init(obj->qepHandle[qep], QEPCTL_Iei_Nothing);
      QEP_set_index_event_latch(obj->qepHandle[qep], QEPCTL_Iel_Rising_Edge);
      QEP_set_soft_init(obj->qepHandle[qep], QEPCTL_Swi_Nothing);
      QEP_disable_unit_timer(obj->qepHandle[qep]);
      QEP_disable_watchdog(obj->qepHandle[qep]);
    
      // setup the QPOSCTL register
      QEP_disable_posn_compare(obj->qepHandle[qep]);
    
      // setup the QCAPCTL register
      QEP_disable_capture(obj->qepHandle[qep]);
    
      // renable the position counter
      QEP_enable_counter(obj->qepHandle[qep]);
    
    
      return;
    }
    #endif

    and how I can mix it with Direct Register Access

    to add an ISR for QEP Index, or so

    in e:\ti\controlSUITE\development_kits\HVMotorCtrl+PfcKit_v2.1\HVPM_Sensored\

    there is only ADC INT and no QEP INT

    // ------------------------------------------------------------------------------
    //    Detect calibration angle and call the QEP module
    // ------------------------------------------------------------------------------
    	if (lsw==0) {EQep1Regs.QPOSCNT=0; EQep1Regs.QCLR.bit.IEL = 1;} // Reset position cnt.
    
    	if ((EQep1Regs.QFLG.bit.IEL==1) && Init_IFlag==0)			   // Check the index occurrence  
    	   {qep1.CalibratedAngle= EQep1Regs.QPOSILAT; Init_IFlag++;}   // Keep the latched pos. at the first index
    
        if (lsw!=0) QEP_MACRO(1,qep1);
    

    I am puzzled

  • Hi again

    I need to put a QEP Index Interrupt

    so here is what I add, but I never go in the ISR

      // setup faults
      HAL_setupFaults(halHandle);
    
    
      // initialize the interrupt vector table
      HAL_initIntVectorTable(halHandle);
    
      // init QEP Int ISR to QEP_Index_ISR
      HAL_Obj *obj = (HAL_Obj *)halHandle;
      PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;
      ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    #ifdef J5
      pie->EQEP2_INT = &QEP_Index_ISR;
    #else
      pie->EQEP1_INT = &QEP_Index_ISR;
    #endif
      DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
    #ifdef QEP
    	// 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);
    	// configure QEP Index Interrupt
    	obj = (HAL_Obj *)halHandle;
    	#ifdef J5
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[1];
    	#else
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    	#endif
    
    	// clear the QEP interrupt flag
    	QEP_clear_interrupt_flag( qep, QEINT_Iel);
    	//QEP_QFLG_IEL  QEINT
    	QEP_enable_interrupt( qep, QEINT_Iel);
    #endif
    
    	// enable the ADC interrupts
      HAL_enableAdcInts(halHandle);
    
      // enable global interrupts
      HAL_enableGlobalInts(halHandle);
    
      // enable debug interrupts
      HAL_enableDebugInt(halHandle);
    

    and

    the ISR

    //-------------------------------------------------------------------------------------------------
    interrupt void QEP_Index_ISR(void)
    {
    	  // acknowledge the QEP interrupt
    	HAL_Obj *obj = (HAL_Obj *)halHandle;
    #ifdef J5
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[1];
    #else
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    #endif
    	  // clear the QEP interrupt flag
    	  QEP_clear_interrupt_flag( qep, QEINT_Iel);
    	  // Acknowledge interrupt from PIE group 5
    	  PIE_clearInt(obj->pieHandle,PIE_GroupNumber_5);
    
    	    HAL_toggleLed(halHandle,(GPIO_Number_e)HAL_Gpio_LED2);
    
    return;
    }
    

    what is wrong ?

  • modifed to add cpu int and enable them but still no QEP ISR fired...

    #ifdef QEP
    	// 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);
    	// configure QEP Index Interrupt
    	obj = (HAL_Obj *)halHandle;
    	#ifdef J5
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[1];
    	#else
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    	#endif
    
    	// clear the QEP interrupt flag
    	QEP_clear_interrupt_flag( qep, QEINT_Iel);
    	QEP_enable_interrupt( qep, QEINT_Iel);
    
    	// Enable PIE group 5 interrupt 1 for EQEP1_INT
    	 PIE_enableInt( obj->pieHandle, PIE_GroupNumber_5, PIE_InterruptSource_EQEP1 );
    
    	// enable the cpu interrupt for QEP interrupts
    	CPU_enableInt(obj->cpuHandle,CPU_IntNumber_5);
    
    #endif

  • Modified, now I enter once the ISR but never again, and also it enters on QEP A or B changes and not on Index as I want

    //-------------------------------------------------------------------------------------------------
    __interrupt void QEP_Index_ISR(void)
    {
    	//GpioDataRegs.GPBDAT.bit.GPIO34 = 1- GpioDataRegs.GPBDAT.bit.GPIO34;
    	//GpioDataRegs.GPBDAT.bit.GPIO39 = 1 - GpioDataRegs.GPBDAT.bit.GPIO34;
    	HAL_toggleLed(halHandle,(GPIO_Number_e)HAL_Gpio_LED2);
    
        // acknowledge the QEP interrupt
    	HAL_Obj *obj = (HAL_Obj *)halHandle;
    #ifdef J5
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[1];
    #else
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    #endif
    	  // clear the QEP interrupt flag
    //	  QEP_clear_interrupt_flag( qep, QEINT_Iel);
    	  // Acknowledge interrupt from PIE group 5
    	  PIE_clearInt(obj->pieHandle,PIE_GroupNumber_5);
    	  //PieCtrlRegs.PIEACK.all = PIEACK_GROUP5;
    }
    

    and the config

      // setup faults
      HAL_setupFaults(halHandle);
    
    
      // initialize the interrupt vector table
      HAL_initIntVectorTable(halHandle);
    
      // init QEP Int ISR to QEP_Index_ISR
      HAL_Obj *obj = (HAL_Obj *)halHandle;
      PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;
      EALLOW;
    #ifdef J5
      pie->EQEP2_INT = &QEP_Index_ISR;
    #else
      pie->EQEP1_INT = &QEP_Index_ISR;
    #endif
      EDIS;
    
    #ifdef QEP
    	// 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);
    	// configure QEP Index Interrupt
    	obj = (HAL_Obj *)halHandle;
    	#ifdef J5
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[1];
    	#else
    	QEP_Obj *qep = (QEP_Obj *)obj->qepHandle[0];
    	#endif
    
    	// clear the QEP interrupt flag
    	QEP_clear_interrupt_flag( qep, QEINT_Iel);
    	//QEP_QFLG_IEL  QEINT
    	QEP_enable_interrupt( qep, QEINT_Iel);
    
    	// Enable PIE group 5 interrupt 1 for EQEP1_INT
    	PIE_enableInt( obj->pieHandle, PIE_GroupNumber_5, PIE_InterruptSource_EQEP1 );
    	// PieCtrlRegs.PIEIER5.bit.INTx1 = 1;
    	// PieCtrlRegs.PIEIER5.all = M_INT1;
    
    	// enable the cpu interrupt for QEP interrupts
    	CPU_enableInt(obj->cpuHandle,CPU_IntNumber_5);
    
        HAL_enableGlobalInts(halHandle);
    	// enable debug interrupts
    	HAL_enableDebugInt(halHandle);
    
    while(1);