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 Overflow Interrupt and data integrity

Part Number: TMS320F28377S

Hallo,

I'm using eQEP as quadrature encoder within TMS320F28377S. Every overflow and underflow is used to increment/decrement rotation counter.

As a result is total rotor position expected. The total position is calculated from rotor position (eQEP counter) and total rotation counter (Interrupt).

Unfortunately it can happen that Overflow-Interrupt is blocked or has lower priority, what leads to invalid data: read actual, just overloaded EQEP_O_QPOSCNT but interrupt-driven rotation counter is not updated.

Please help me to reach always valid data.


Additional info:

Index impulse interrupt is used for counter corrections, reference is taken at first index.

Overload interrupt is used for extended counter.


Greetings

  • Hi,

    Can you please provide more details on the counter value mismatch or invalid due to delayed entry into ISR due to interrupt being low priority?

    It will help if you can show the counter values during normal operation and when it is delayed.

    Have you looked into latching the QPOSCNT?

    Best Regards,

    Nirav

  • Rotor position is calculated in radians as: 2*PI*total_rotations + 2*PI*QPOSCNT/enoder_pulse_count
    During stable speed driving (nearly constant position increment is expected) it comes sometimes to single read of nearly -2*PI increment read (in place of expected e.g. 0.01*PI).
    I other worlds, the faulty value consists of QPOSCNT nearly 0 or nearly MAX.


    It means QPOSCNT has just overflown but total_rotations counter is not incremented at this moment.
    I read QPOSCNT directly using EQEP_getPosition() function, without latching it.
    I suppose, I get QPOSCNT before overflow ISR is executed.

    What schould I do with QPOSCNT latching?

    Init_QEP(void){
        // Configure the decoder for quadrature count mode, count edges of both A and B signals.
        EQEP_setDecoderConfig(EQEP_BASE, (EQEP_CONFIG_2X_RESOLUTION |EQEP_CONFIG_QUADRATURE |EQEP_CONFIG_NO_SWAP | EQEP_QDECCTL_IGATE));
    
        EQEP_setEmulationMode(EQEP_BASE, EQEP_EMULATIONMODE_RUNFREE);
    
        // Configure the position counter to reset on overflow, set maximum value (overflow)
        EQEP_setPositionCounterConfig(EQEP_BASE, EQEP_POSITION_RESET_MAX_POS, m_pulse_count - 1);
    
        // Configure the position counter to be latched on - correction of lost impulses
        EQEP_setLatchMode( EQEP_BASE, EQEP_LATCH_SW_INDEX_MARKER );
    
        // Enable Interrupt
        EQEP_enableInterrupt (EQEP_BASE, EQEP_INT_INDEX_EVNT_LATCH | EQEP_INT_PHASE_ERROR | EQEP_INT_DIR_CHANGE | EQEP_INT_OVERFLOW | EQEP_INT_UNDERFLOW);
    
        // Enable the eQEP3 module
        EQEP_enableModule(EQEP_BASE);
    
        // Set counter to zero (will be reset again when over/underflow)
        EQEP_setPosition(EQEP_BASE, 0);
    	
    	// Configure the position counter to reset on overflow, set maximum value (overflow)
        EQEP_setPositionCounterConfig(EQEP_BASE, EQEP_POSITION_RESET_MAX_POS, m_pulse_count - 1);
    }
    
    
    interrupt void index_interrupt_handler(void){
    	...
    
        //IRQ: Over- / Under-flow supports revolution counting
        if ((EQEP_getInterruptStatus(EQEP_BASE) & EQEP_INT_OVERFLOW) != 0U)    {
            m_revolution_counter++; //UPCOUNTING
        }
    	
        if ((EQEP_getInterruptStatus(EQEP_BASE) & EQEP_INT_UNDERFLOW) != 0U)    {
            m_revolution_counter--; //DOWNCOUNTING
        }
    
    
        EQEP_clearInterruptStatus(EQEP_BASE, 0x0FFF);
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP5);
    }

  • When do you get the position count? Meaning, when is EQEP_getPosition() function executed. I don't see it inside the ISR.

    I am still not clear on how do you time the QPOSCNT read, meaning are you doing it on INDEX event or unit time out? It is possible that when you are reading QPOSCNT has reached the max value, so by the time Overflow Interrupt gets generated and you read the QPOSCNT the counter has reset.

    You can latch the QPOSCNT on Unit time out event. For that you will need to configure Unit timer.

    Best Regards,

    Nirav

  • The function EQEP_getPosition() is called on demand, totally asynchronously from eQEP Events, e.g. from other Interrupts.

    You can latch the QPOSCNT on Unit time out event. For that you will need to configure Unit timer.

    That is probably what I Need. But how can I latch QPOSCNT and my overload counter coherent?

  • If EQEP_getPosition() is called asynchronously, then I dont think Unit timer will help. 

    Why cant you just increment/decrement rotation counter (m_revolution_counter) when you read QPOSCNT=0 or Max value, that way you get correct rotation count. You will also have to clear the interrupt flag when you increment/decrement so that it does not increment/decrement it twice inside the ISR.

    Best Regards,

    Nirav

  • There is no waranty that asynchronous read of QPOSCNT will return 0, it can be e.g. 4 or 7.
    I have implemented simmilar solution. If software read detects  0 <=> MAX transition (with some tolerance boundary) then Rotation counter is incremented / decremented. Then ISR from overload isno more needed. 

    Thank you Nirav