AVR128Dx TCB Input Capture issue

Ive made a code for reading SENT sensor using TCB interrupt with event system. It works 90% of the time, but those 10% seems like it doesnt read correct high pulse duration, mby someone will see, what Im missing or have done incorretly

#define SAMPLES 40
#define TIMER_RESOLUTION 0.04166666666  // Timer resolution in microseconds
#define NEXT_PULSES_TO_PRINT 8    // Number of subsequent high and low pulses to print

volatile float highPulseBuff[SAMPLES] = {0};
volatile float lowPulseBuff[SAMPLES] = {0};
volatile bool pulseCaptured = false;
float oneTick = 0;

void TCB_init(void) {
    TCB0.CTRLB = TCB_CNTMODE_CAPT_gc;

    // Enable input capture
    TCB0.EVCTRL = TCB_CAPTEI_bm; // Enable Event Input

    // Configure Event System to connect the PA6 pin to TCB
    EVSYS.CHANNEL0 = EVSYS_CHANNEL0_PORTA_PIN6_gc;
    EVSYS.USERTCB0CAPT = 0x01;

    // Enable TCB interrupt
    TCB0.INTCTRL = TCB_CAPT_bm;

    // Enable TCB
    TCB0.CTRLA = TCB_ENABLE_bm;

    // Enable global interrupts
    sei();
}

// Interrupt Service Routine for TCB0 Capture interrupt

ISR(TCB0_INT_vect) {
    static uint16_t lastCapture = 0;
    static uint8_t idx = 0;
    uint16_t capture = TCB0.CNT; // Read the input capture register of TCB0
    uint16_t duration;

    // Handle overflow
    if (capture >= lastCapture) {
        duration = capture - lastCapture;
    } else {
        duration = (0xFFFF - lastCapture) + capture + 1; // Assuming a 16-bit counter
    }

    lastCapture = capture;

    if (TCB0.EVCTRL & TCB_EDGE_bm) {
        // Rising edge detected, so this is the end of the low pulse
        if (idx < SAMPLES) {
            highPulseBuff[idx] = duration;
        }
    } else {
        // Falling edge detected, so this is the end of the high pulse
        if (idx < SAMPLES) {
            lowPulseBuff[idx] = duration;
            idx++;
            if (idx >= SAMPLES) {
                pulseCaptured = true;
                idx = 0; // Reset index to prevent overflow
            }
        }
    }

    // Toggle edge detection
    TCB0.EVCTRL ^= TCB_EDGE_bm;
    TCB0.INTFLAGS = TCB_CAPT_bm; // Clear the interrupt flag
}

unsigned int combineDataNibbles(unsigned int d4, unsigned int d5, unsigned int d6) {
    return (d4 << 8) | (d5 << 4) | d6;
}

void decode_sent() {
    static uint8_t dataFrame[8] = {0};
    static float oneTickPeriods = 0;

    if (pulseCaptured) {
        // Disable interrupts temporarily to safely read shared variables
        TCB0.EVCTRL &= ~TCB_CAPTEI_bm;
        TCB0.CTRLA &= ~TCB_ENABLE_bm;

        static bool foundSync = false;
        int syncIndex = -1;

        print("\r\n");
        print("pulseCaptured!");
        print("\r\n");

        // Search for the sync pulse based on duty ratio criteria
        for (int i = 0; i < SAMPLES; i++) {
            // Calculate duty ratio (high / (high + low))
            float dutyRatio = (float) highPulseBuff[i] / ((float) highPulseBuff[i] + (float) lowPulseBuff[i]);

            print("H: ");
            print_float(highPulseBuff[i] * TIMER_RESOLUTION);
            print(" L: ");
            print_float(lowPulseBuff[i] * TIMER_RESOLUTION);
            print("\r\n");

            // Check if duty ratio meets criteria (approx. 0.89 with wiggle room)
            if (dutyRatio >= 0.90 * 0.99 && dutyRatio <= 0.90 * 1.01 && ((float) highPulseBuff[i] * TIMER_RESOLUTION) + ((float) lowPulseBuff[i]) * TIMER_RESOLUTION < 180) { // Adding a 1% wiggle room
                float totalPulseDurations = ((float) highPulseBuff[i] * TIMER_RESOLUTION) + ((float) lowPulseBuff[i] * TIMER_RESOLUTION);
                oneTickPeriods = totalPulseDurations / 56.0f;

                if (i < 11) {
                    print("---Sync--- ");
                    print_float(dutyRatio);
                    print("\r\n");
                    foundSync = true;
                    syncIndex = i;
                    break;
                } else {
                    print("----------");
                    print("\r\n");
                }
            }
        }

        //        print("\r\n");

        if (foundSync && syncIndex != -1) {
            // Print the next 8 sets of high and low pulses
            for (int j = syncIndex + 1; j < syncIndex + 1 + NEXT_PULSES_TO_PRINT && j < SAMPLES; j++) {
                float totalPulseDuration = ((float) highPulseBuff[j] * TIMER_RESOLUTION) + ((float) lowPulseBuff[j] * TIMER_RESOLUTION);
                float ticks = (totalPulseDuration / oneTickPeriods) - 12.0f;

                print("H: ");
                print_float(highPulseBuff[j] * TIMER_RESOLUTION);
                print(" L: ");
                print_float(lowPulseBuff[j] * TIMER_RESOLUTION);
                print(" D: ");
                print_float(totalPulseDuration);
                print(" T: ");
                print_float(oneTickPeriods);


                if ((uint8_t) round(ticks) < 16) {
                    dataFrame[j - syncIndex - 1] = (uint8_t) round(ticks);
                }
                print(" HEX: ");
                print_hex(dataFrame[j - syncIndex - 1]);
                print("\r\n");

            }

            print(" D1: ");
            sent_pressure = combineDataNibbles(dataFrame[1], dataFrame[2], dataFrame[3]);
            print_int(sent_pressure);
            print(" D2: ");
            sent_temperature = combineDataNibbles(dataFrame[6], dataFrame[5], dataFrame[4]);
            print_int(sent_temperature);
            print("\r\n");
            //            }
        } else {
            foundSync = false;
        }

        // Reset variables and enable interrupts
        cli();
        TCB0.CNT = 0;
        pulseCaptured = false;
        TCB0.CTRLA = TCB_ENABLE_bm;
        TCB0.EVCTRL = TCB_CAPTEI_bm;
        sei();
    }
}

int main(void) {
    // Initialize PA6 and TCB
    /* Set OSCHF as main clock source */
    _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCHF_gc);

    /* Wait for main clock oscillator changing to finish */
    while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) {
        ;
    }

    /* Change OSCHF frequency to 24 MHz */
    _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, CLKCTRL_FRQSEL_24M_gc);

    PA6_init();
    TCB_init();
    USART2_init(1000000);
    while (1) {
        decode_sent();
        _delay_ms(10);
    }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.