Why is TPM input capture returning large distance values (~12 meters) with 24 MHz TPM clock on i.MX9

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Why is TPM input capture returning large distance values (~12 meters) with 24 MHz TPM clock on i.MX9

370 Views
Manjunathb
Contributor II

 

Hello NXP Community,

I’m using the i.MX93 (Cortex-M33) and trying to interface an ultrasonic distance sensor (like HC-SR04) using TPM input capture. I'm measuring the pulse width between the rising and falling edge on the ECHO pin using TPM3 (input capture on channel 2).

The TPM clock is configured at 24 MHz, and the distance is calculated using the formula:

 

float timeUs = (ticks / tpmClk) * 1e6;
float distanceCm = timeUs / 58.0f;

 

Here is my full code for reference:- 

#include "fsl_debug_console.h"
#include "board.h"
#include "app.h"
#include "fsl_tpm.h"
#include "fsl_rgpio.h"
#include "fsl_lpuart.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/
volatile bool tpmIsrFlag = false;
volatile uint32_t risingTime = 0;
volatile uint32_t fallingTime = 0;
volatile bool gotRisingEdge = false;

/*******************************************************************************
 * Code
 ******************************************************************************/
void Init_LPUART(void)
{
    lpuart_config_t config;

    /* Get default UART config (8N1, no parity, no flow control) */
    LPUART_GetDefaultConfig(&config);

    /* Modify parameters as needed */
    config.baudRate_Bps = 115200U;
    config.enableTx = true;
    config.enableRx = true;

    /* Initialize the UART with the specified parameters */
    LPUART_Init(BOARD_LPUART, &config, BOARD_LPUART_CLK_FREQ);
}

float CalculateDistance(void)
{
    uint32_t ticks;
    if (fallingTime >= risingTime)
        ticks = fallingTime - risingTime;
    else
        ticks = (TPM_MAX_COUNTER_VALUE(DEMO_TPM_BASEADDR) - risingTime) + fallingTime; /* Overflow handled */

    float tpmClk = CLOCK_GetIpFreq(LPTPM_CLOCK_ROOT); /* You may adjust to TPM clock */
    float timeUs = (ticks * 1.0f / tpmClk) * 1e6;
    PRINTF("TPM Clock : %.2f\r\n",tpmClk);

    float distanceCm = timeUs / 58.0f;

    return distanceCm;
}

void SetUp(void)
{
    rgpio_pin_config_t out_config ={
        kRGPIO_DigitalOutput,
        0,
    };
   
    /* Trigger pin */
    RGPIO_PinInit(BOARD_RGPIO,TRIG_PIN,&out_config);
    RGPIO_PinWrite(BOARD_RGPIO,TRIG_PIN,0);
}

void SendTrigPulse(void)
{
    RGPIO_PinWrite(BOARD_RGPIO, TRIG_PIN, 1);
    SDK_DelayAtLeastUs(10, SystemCoreClock);
    RGPIO_PinWrite(BOARD_RGPIO, TRIG_PIN, 0);
}

void TPM_INPUT_CAPTURE_HANDLER(void)
{
    uint32_t status = TPM_GetStatusFlags(DEMO_TPM_BASEADDR);

    if (status & TPM_CHANNEL_FLAG)
    {
        uint32_t capturedValue = TPM_GetChannelValue(DEMO_TPM_BASEADDR, BOARD_TPM_INPUT_CAPTURE_CHANNEL);

        if (!gotRisingEdge)
        {
            risingTime = capturedValue;
            gotRisingEdge = true;

            // Switch to falling edge detection
            TPM_SetupInputCapture(DEMO_TPM_BASEADDR,BOARD_TPM_INPUT_CAPTURE_CHANNEL,kTPM_FallingEdge);
        }
        else
        {
            fallingTime = capturedValue;
            tpmIsrFlag = true;
            gotRisingEdge = false;

            // Switch back to rising edge detection for next measurement
            TPM_SetupInputCapture(DEMO_TPM_BASEADDR,BOARD_TPM_INPUT_CAPTURE_CHANNEL,kTPM_RisingEdge);
        }

        // Clear interrupt flag for this channel
        TPM_ClearStatusFlags(DEMO_TPM_BASEADDR, TPM_CHANNEL_FLAG);
    }

    SDK_ISR_EXIT_BARRIER;
    // tpmIsrFlag = true;

    // /* Clear interrupt flag.*/
    // TPM_ClearStatusFlags(DEMO_TPM_BASEADDR, TPM_CHANNEL_FLAG);
    // SDK_ISR_EXIT_BARRIER;
}

/*!
 * @brief Main function
 */
int main(void)
{
    tpm_config_t tpmInfo;

    /* Board pin, clock, debug console init */
    BOARD_InitHardware();

    SetUp(); /* Set up the GPIO */

    // Init_LPUART(); /* Initialise one more UART */

    /* Print a note to terminal */
    PRINTF("\r\nTPM input capture example\r\n");
    PRINTF("\r\nOnce the input signal is received the input capture value is printed\r\n");

    TPM_GetDefaultConfig(&tpmInfo);

    /* Initialize TPM module */
    TPM_Init(DEMO_TPM_BASEADDR, &tpmInfo);

    /* Setup input capture on a TPM channel */
    TPM_SetupInputCapture(DEMO_TPM_BASEADDR, BOARD_TPM_INPUT_CAPTURE_CHANNEL, kTPM_RisingEdge);

    /* Set the timer to be in free-running mode */
    TPM_SetTimerPeriod(DEMO_TPM_BASEADDR, TPM_MAX_COUNTER_VALUE(DEMO_TPM_BASEADDR));

    /* Enable channel interrupt when the second edge is detected */
    TPM_EnableInterrupts(DEMO_TPM_BASEADDR, TPM_CHANNEL_INTERRUPT_ENABLE);

    /* Enable at the NVIC */
    EnableIRQ(TPM_INTERRUPT_NUMBER);

    TPM_StartTimer(DEMO_TPM_BASEADDR, kTPM_SystemClock);

    while (1)
    {
        tpmIsrFlag = false;

        SendTrigPulse();

        while (!tpmIsrFlag)
        {
            __NOP(); // Wait for capture
        }

        float distance = CalculateDistance();
        PRINTF("RisingTime : %u\r\n",risingTime);
        PRINTF("FallingTime : %u\r\n",fallingTime);
        PRINTF("Distance: %.2f cm\r\n", distance);

        SDK_DelayAtLeastUs(60000,SystemCoreClock);
    }
}
 

However, I'm consistently getting distance values around 1228 cm to 1260 cm, which is abnormally large, even when there's a wall very close to the sensor (e.g., <50 cm). Here are some example readings:

TPM Clock : 24000000.00
RisingTime : 1172965159
FallingTime : 1174675524
Distance: 1228.71 cm

TPM Clock : 24000000.00
RisingTime : 1283028325
FallingTime : 1284738837
Distance: 1228.82 cm

TPM Clock : 24000000.00
RisingTime : 1448107508
FallingTime : 1449851665
Distance: 1252.99 cm

TPM Clock : 24000000.00
RisingTime : 269392922
FallingTime : 269436317
Distance: 31.17 cm

TPM Clock : 24000000.00
RisingTime : 278665048
FallingTime : 278708444
Distance: 31.18 cm

TPM Clock : 24000000.00
RisingTime : 287937289
FallingTime : 287977974
Distance: 29.23 cm

TPM Clock : 24000000.00
RisingTime : 297205949
FallingTime : 297248662
Distance: 30.68 cm

TPM Clock : 24000000.00
RisingTime : 306477012
FallingTime : 306519726
Distance: 30.69 cm

I'm unsure why these values are consistently too large. 

 

i.MX93EVK 

 

Labels (1)
0 Kudos
Reply
2 Replies

342 Views
Bio_TICFSL
NXP TechSupport
NXP TechSupport

Hello,

Large distance values (~12 meters) from an HC-SR04 ultrasonic sensor using TPM input capture often stem from incorrect pulse width measerement of signal. The sensor measures distance by timing the duration of the echo pulse, and if the measurement includes the trigger pulse or is otherwise inaccurate, it can lead to inflated distance readings. 

 
Here's a breakdown of the potential causes and solutions:
1. Incorrect Pulse Width Measurement:
  • Trigger Pulse Included:
    The input capture might be capturing the time from the rising edge of the trigger pulse to the falling edge of the echo pulse, instead of just the echo pulse itself. 
     

 

  • Solution:
    Ensure the input capture is configured to measure the duration of the echo pulse only. This typically involves setting up the timer to trigger on the rising edge of the echo signal and capture the falling edge. 
     

 

2. Signal Interference:
  • Early Echo Detection:
    The sensor's receiver might detect the signal from the transmitter before it bounces off an object, leading to an artificially long pulse width. 
     

 

  • Oblique Reflections:
    Reflections from angled surfaces can cause the echo signal to be weak or delayed, leading to inaccurate distance readings. 
     
  • Solution:
    • Shielding: Use a small tube or shroud over the transmitter and receiver to minimize early detection and improve signal directionality. 
       
  • Multiple Readings: Take multiple readings and filter out excessively large values or calculate an average. 
     
  • NewPing Library: Consider using the NewPing library, which is designed to handle these issues. 
4. Software Implementation:
  • Timer Configuration:
    Incorrect timer prescaler or clock settings can affect the accuracy of the pulse width measurement. 
     
    Delay between Pings:
    The sensor has a minimum time between pings, and exceeding this can lead to inaccurate readings. 
     

 

  • Solution:
    • Check Timer Settings: Verify the timer's prescaler and clock configuration to ensure accurate time measurement. 
       
  • Appropriate Delays: Ensure sufficient delay between pings to allow the sensor to reset and stabilize. 
     
     
    Regards
     
0 Kudos
Reply

329 Views
Manjunathb
Contributor II
Thank you for your response!
0 Kudos
Reply