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.

LAUNCHXL-F280025C: eCAP detect both pulse and period

Part Number: LAUNCHXL-F280025C


Tool/software:

Hi,

I have bicycle cadence sensor, it's generate 48 interrupt per one revolution (with 48 magnets on disc), I would like to trigger 48 interrupt per revolution, see below I modified the ecap_ex2_capture_pwm example, I can calculate both pulse width and period, but only trigger 24 interrupt per revolution since the interrupt only on event 4

ECAP_clearInterrupt(ECAP1_BASE, ECAP_ISR_SOURCE_CAPTURE_EVENT_4);

how can I trigger interrupt on each RISING EDGE (48 trigger per revolution)  together with 4 event captured for duty cycle and pulse width calculation

void initeCAP(void)
{
    XBAR_setInputPin(INPUTXBAR_BASE, XBAR_INPUT7, 17);

    // Disable ,clear all capture flags and interrupts
    ECAP_disableInterrupt(ECAP1_BASE,
       (ECAP_ISR_SOURCE_CAPTURE_EVENT_1  |
        ECAP_ISR_SOURCE_CAPTURE_EVENT_2  |
        ECAP_ISR_SOURCE_CAPTURE_EVENT_3  |
        ECAP_ISR_SOURCE_CAPTURE_EVENT_4  |
        ECAP_ISR_SOURCE_COUNTER_OVERFLOW |
        ECAP_ISR_SOURCE_COUNTER_PERIOD   |
        ECAP_ISR_SOURCE_COUNTER_COMPARE));

    ECAP_clearInterrupt(ECAP1_BASE,
       (ECAP_ISR_SOURCE_CAPTURE_EVENT_1  |
        ECAP_ISR_SOURCE_CAPTURE_EVENT_2  |
        ECAP_ISR_SOURCE_CAPTURE_EVENT_3  |
        ECAP_ISR_SOURCE_CAPTURE_EVENT_4  |
        ECAP_ISR_SOURCE_COUNTER_OVERFLOW |
        ECAP_ISR_SOURCE_COUNTER_PERIOD   |
        ECAP_ISR_SOURCE_COUNTER_COMPARE));

    // Disables time stamp capture.
    ECAP_disableTimeStampCapture(ECAP1_BASE);

    // Stops Time stamp counter.
    ECAP_stopCounter(ECAP1_BASE);

    // Sets eCAP in Capture mode.
    ECAP_enableCaptureMode(ECAP1_BASE);

    // Sets the capture mode.
    ECAP_setCaptureMode(ECAP1_BASE,ECAP_ONE_SHOT_CAPTURE_MODE,ECAP_EVENT_4);

    // Sets the Capture event prescaler.
    ECAP_setEventPrescaler(ECAP1_BASE, 0U);

    ECAP_setEventPolarity(ECAP1_BASE,ECAP_EVENT_1,ECAP_EVNT_RISING_EDGE);
    ECAP_setEventPolarity(ECAP1_BASE,ECAP_EVENT_2,ECAP_EVNT_FALLING_EDGE);
    ECAP_setEventPolarity(ECAP1_BASE,ECAP_EVENT_3,ECAP_EVNT_RISING_EDGE);
    ECAP_setEventPolarity(ECAP1_BASE,ECAP_EVENT_4,ECAP_EVNT_FALLING_EDGE);


    // Configure counter reset on events
    ECAP_enableCounterResetOnEvent(ECAP1_BASE,ECAP_EVENT_1);
    ECAP_enableCounterResetOnEvent(ECAP1_BASE,ECAP_EVENT_2);
    ECAP_enableCounterResetOnEvent(ECAP1_BASE,ECAP_EVENT_3);
    ECAP_enableCounterResetOnEvent(ECAP1_BASE,ECAP_EVENT_4);

    // Select eCAP input.
    ECAP_selectECAPInput(ECAP1_BASE, ECAP_INPUT_INPUTXBAR7);

    // Sets a phase shift value count.
    ECAP_setPhaseShiftCount(ECAP1_BASE, 0U);

    // Enable counter loading with phase shift value.
    ECAP_enableLoadCounter(ECAP1_BASE);

    // Configures Sync out signal mode.
    ECAP_setSyncOutMode(ECAP1_BASE, ECAP_SYNC_OUT_SYNCI);

    // Configures emulation mode.
    ECAP_setEmulationMode(ECAP1_BASE,ECAP_EMULATION_STOP);

    // Set up the source for sync-in pulse..
    ECAP_setSyncInPulseSource(ECAP1_BASE,ECAP_SYNC_IN_PULSE_SRC_DISABLE);

    // Starts Time stamp counter for myECAP0.
    ECAP_startCounter(ECAP1_BASE);

    // Enables time stamp capture for myECAP0.
    ECAP_enableTimeStampCapture(ECAP1_BASE);

    // Re-arms the eCAP module for myECAP0.
    ECAP_reArm(ECAP1_BASE);

    // Enables interrupt source for myECAP0.
    //
    ECAP_enableInterrupt(ECAP1_BASE, ECAP_ISR_SOURCE_CAPTURE_EVENT_4);

    Interrupt_register(INT_ECAP1, &CadenceISR);
    Interrupt_enable(INT_ECAP1);

    return;
}

__interrupt void CadenceISR(void)
{
    MOTOR_Vars_t *obj = (MOTOR_Vars_t *)motorHandle_M1;

   
    obj->cmdPot.cap1Count = ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_1);
    obj->cmdPot.cap2Count = ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_2);
    obj->cmdPot.cap3Count = ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_3);
    obj->cmdPot.cap4Count = ECAP_getEventTimeStamp(ECAP1_BASE, ECAP_EVENT_4);

    // Calculate pulse width (time high)
    if (obj->cmdPot.cap3Count > obj->cmdPot.cap2Count)
    {
        obj->cmdPot.pulseWidth = obj->cmdPot.cap3Count - obj->cmdPot.cap2Count;
        obj->cmdPot.pulseWidthBigger++;
    }
    else if (obj->cmdPot.cap3Count < obj->cmdPot.cap2Count)
    {
        obj->cmdPot.pulseWidth = obj->cmdPot.cap2Count - obj->cmdPot.cap3Count;
        obj->cmdPot.pulseWidthSmaller++;
    }


    if (obj->cmdPot.cap4Count > obj->cmdPot.cap2Count)
    {
        obj->cmdPot.periodCycles = obj->cmdPot.cap4Count - obj->cmdPot.cap2Count;
        obj->cmdPot.periodBigger++;
    }
    else if (obj->cmdPot.cap4Count < obj->cmdPot.cap2Count)
    {
        obj->cmdPot.periodCycles = obj->cmdPot.cap2Count - obj->cmdPot.cap4Count;
        obj->cmdPot.periodSmaller++;
    }

    if (obj->cmdPot.periodCycles > 0)
    {
        obj->cmdPot.plusecounter++;
        obj->cmdPot.periodSec = (float)obj->cmdPot.periodCycles / 20000000.0f; // Convert to seconds
        obj->cmdPot.revTimeSec = obj->cmdPot.periodSec * 48.0f; // Time for one revolution (48 pulses)

        if (obj->cmdPot.revTimeSec > 0.0f)
        {
            obj->cmdPot.cadenceRPM = 60.0f / obj->cmdPot.revTimeSec; // RPM = 60 / time per revolution (seconds)
        }
    }

    ECAP_clearInterrupt(ECAP1_BASE, ECAP_ISR_SOURCE_CAPTURE_EVENT_4);
    ECAP_clearGlobalInterrupt(ECAP1_BASE);
    ECAP_reArm(ECAP1_BASE);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP4);

    return;
}

Danny

  • Hi Danny,

    You can enable on another event to fire an interrupt in addition to ECAP_EVENT_4, however if you fire on on event 2 for example, event 4 will not have came yet so you may need to read what event was triggered and only read from event's 1/2 and clear the interrupt flags all before the event4 occurs.

    Why do you need to trigger an interrupt on every rising edge?

    Best regards,

    Ryan Ma

  • Hi Ryan,

    Why do you need to trigger an interrupt on every rising edge?

    yes, my rotary disc has 48 magnets on it and trigger 48 interrupts, i need to do some work on EACH interrupt (better real time quick response), as well as duty cycle / period for cadence RPM calculation

    do you think only solution is use other eCAP + interrupt event :

    eCAP1 : interrupt on ECAP_EVENT_1 rising edge for pulse count ? 

    eCAP2 : interrupt on ECAP_EVENT_4 rising falling rising falling for duty cycle calculation ?

    Danny

  • Hi Danny,

    Yes that will work.

    Best regards,

    Ryan Ma