This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

using PWM to measure input period and pulse width

I have an input signal of unknown period and pulse width on a GPIO. I want to use the PWM capture capabilities to  retrieve those parameters.

I see in the documentation there is

pwm_pin_configure_capture, pwm_pin_enable_capture, pwm_pin_disable_capture, pwm_pin_capture_usec, pwm_capture_callback_handler

I did not see an example how to use these. could you show me a simple example of what I need to do to  get the period and pulse width from an input signal using a PWM. The functions seem to be exactly what I need but the implementation is not clear in the documentation and I am getting a lot of compile errors. I am sure it is something simple I am missing. I appreciate any help you can give.

  • Vkadal

    I am able to get microsecond accuracies when I changed the code to use hardware interrupts on the GPIO pin and not the user interface. I have it working now. thank you for your help. The user interface caused polling changes on the GPIO pin and had millisecond latencies.

  • Hello Timothy I have similar use case as yours and i am glad you have found the solution for the same.

    Can you please share your code here so that we can leverage and appreciate your work that you have shared!

  • when I changed the code to use hardware interrupts on the GPIO pin and not the user interface.

    Hello timothy

    It would be wonderful if you state the change as above quoted comment.

  • below is the code that I am using to measure the output of a Hall effect sensor. Their is a pulse width of 30 - 200us.

    typedef struct
    {
    uint32_t pulseWidth; //!< pulse width in us
    uint32_t period; //!< period in us
    } sensorDataStruct;
    sensorDataStruct sensorData[SENSOR_BUFFER_SIZE];
    iuint16_t sensorDataIn;
    uint16_t sensorDataOut;
    uint16_t sensorDataCount;
    nt32_t inputPulseWidth;
    int32_t inputPeriod;
    void hallSensorCallback(struct device *dev, struct gpio_callback *cb, uint32_t pins);
    void configurePins();

    main()

    {

    ...

    ...

    sensorDataIn = 0;
    sensorDataOut = 0;
    sensorDataCount = 0;
    timer_init();
    configurePins();

    ...

    ...

    }

    void timer_init()
    {
    NRF_TIMER1->TASKS_STOP = 1;
    NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
    NRF_TIMER1->PRESCALER = 4; // Fhck / 2^4 = 1us
    // NRF_TIMER1->CC[0] = 62500; // 62500 - 1s

    NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos);

    NRF_TIMER1->TASKS_CLEAR = 1;
    // NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);

    NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    }


    void hallSensorCallback(struct device *dev, struct gpio_callback *cb, uint32_t pins)
    {
    int pin;

    pin = gpio_pin_get(dev, HALL_SENSOR_PIN);
    gpio_pin_set(dev,LED3_PIN,pin);
    if(pin == 0)
    {
    NRF_TIMER1->TASKS_CAPTURE[0] = 1;
    inputPeriod = NRF_TIMER1->CC[0];
    NRF_TIMER1->TASKS_CLEAR = 1;
    if(sensorDataCount == 0) /* check if first pulse width measured */
    return;
    if( sensorDataIn == 0 )
    sensorData[SENSOR_BUFFER_SIZE - 1].period = inputPeriod;
    else
    sensorData[sensorDataIn - 1].period = inputPeriod;
    }
    else
    {
    NRF_TIMER1->TASKS_CAPTURE[0] = 1;
    inputPulseWidth = NRF_TIMER1->CC[0];
    if(inputPulseWidth >= 1000) /* check if valid pulse width */
    return;
    if(sensorDataCount < SENSOR_BUFFER_SIZE)
    {
    sensorData[sensorDataIn++].pulseWidth = inputPulseWidth;
    sensorData[sensorDataIn - 1].period = 0;
    if(sensorDataIn == SENSOR_BUFFER_SIZE) /* is it wrap around */
    sensorDataIn = 0;
    sensorDataCount++;
    }
    }
    }

    void configurePins()
    {
    /* configure output pins */
    // gpio_pin_configure(gpioPtr, LED3_PIN,GPIO_OUTPUT | GPIO_ACTIVE_HIGH | GPIO_PULL_UP);
    gpio_pin_configure(gpioPtr, LED3_PIN,GPIO_OUTPUT );

    /* configure input pins */
    gpio_pin_configure(gpioPtr, HALL_SENSOR_PIN,GPIO_INPUT | GPIO_ACTIVE_LOW );

    /* configure interrupt callbacks */
    gpio_init_callback(&gpio_hall_sensor_cb, (gpio_callback_handler_t)hallSensorCallback, BIT(HALL_SENSOR_PIN));
    gpio_add_callback(gpioPtr, &gpio_hall_sensor_cb);
    }

Related