using pwm input to measure frequency

I have an NRF9160 system running and I see mention of "The nRF9160 PWM peripheral can capture the period and pulse width of an external PWM signal" but  was a little confused as to how to implement it. I have used and I am using PWM as an output so that I understand. I have used a generic GPIO as input and used interrupts to start and stop a timer to measure time between edges. This uses two items a generic GPIO and a timer. as I understand the capture capability it just used a single PWM to do the measurement.

can you point me to any examples how to implement this if I am correct in assuming all I need is a single PWM pin.

  • can you please tell me if PWM capture is possible for the nRF9160 SICA BIA..

  • I set up the timers as described in https://docs.nordicsemi.com/bundle/ncs-latest/page/zephyr/kernel/services/timing/timers.html. but I could not get an accurate timer at settings lower than 500 usec. my example code is shown below. At the timer expiry I toggle an output pin so I can see the timer frequency with a scope on the output pin. 1 msec and 500 usec seem to work fine but when I set it to 100 usec I see ~150 usec. below that 50 usec is ~ 170 usec, 10 usec is ~300 usec. below 500 usec the counts are very inaccurate. they do not represent the time between interrupts.

    what am I doing wrong. how do I get the timer to count at 1 usec?

       k_timer_init(&gpio_timer, gpio_timer_handler, NULL);
        k_timer_start(&gpio_timer, K_USEC(100), K_USEC(100));
    void gpio_handler(struct k_work *work)
    {
        gpioCounter++;
        gpio_pin_toggle(sw2ctrl_dev, SW2CTRL_DEV_PIN);
    }
  • Susheel

    can you please  try to answer these questions.

    1. is PWM capture possible for my device?

    2. how can I get a timer to time at 1 usec?

  • Sorry for delayed response Timothy, 

    Timothy said:
    1. is PWM capture possible for my device?

    The PWM peripheral in itself is output so it cannot do a input capture. But you can use a TIMER-GPIOTE in event mode + PPI to make a capture like configuration, 

    Timothy said:
    2. how can I get a timer to time at 1 usec?

    In nrf connect SDK, you cannot get RTOS timer to have a better resolution than 1ms using RTOS timer API. So you would have to use nrfx_timer HAL API directly for measuring time with 1us resolution, you can do something like this in your code (use as template)

    // top of src/jfet_init.c
    #include <zephyr.h>
    #include <nrfx_timer.h>
    
    
    #define TIMER_ID 1
    static const nrfx_timer_t timer = NRFX_TIMER_INSTANCE(TIMER_ID);
    
    
    void jfet_init(void)
    {
        /* Configure the timer for 1 MHz (1 µs ticks) */
        nrfx_timer_config_t cfg = NRFX_TIMER_DEFAULT_CONFIG;
        cfg.frequency = NRF_TIMER_FREQ_1MHz;
        cfg.mode      = NRF_TIMER_MODE_TIMER;
        cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    
        /* Init & start */
        nrfx_timer_init(&timer, &cfg, NULL);
        nrfx_timer_enable(&timer);
    
        /* …rest of your JFET setup… */
    }
    
    
    uint32_t read_now_us(void)
    {
        nrfx_timer_capture(&timer, NRF_TIMER_CC_CHANNEL0);
        return nrfx_timer_capture_get(&timer, NRF_TIMER_CC_CHANNEL0);
    }
    

  • Susheel
    when I try to add just the first few lines it does not build. I am using SDK toolchain 3.0.2.
    what am I missing in order to get this to build. I tried to build the lines shown below.
    *************************************
    #include <nrfx_timer.h>
    
    #define TIMER_ID 1
    static const nrfx_timer_t timer = NRFX_TIMER_INSTANCE(TIMER_ID);
    
    ******************** errors  *******************
                   from C:/Nordic4/test_n9160/agr_ind_new_9160/src/jfet_files/jfet_init.c:1982:
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h: In function 'jfet_init':
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:472:24: error: invalid storage class for function 'nrf_timer_prescaler_set'
      472 | NRF_STATIC_INLINE void nrf_timer_prescaler_set(NRF_TIMER_Type * p_reg, uint32_t prescaler_factor);
          |                        ^~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:481:28: error: invalid storage class for function 'nrf_timer_prescaler_get'
      481 | NRF_STATIC_INLINE uint32_t nrf_timer_prescaler_get(NRF_TIMER_Type const * p_reg);
          |                            ^~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:489:24: error: invalid storage class for function 'nrf_timer_task_trigger'
      489 | NRF_STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_reg,
          |                        ^~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:500:28: error: invalid storage class for function 'nrf_timer_task_address_get'
      500 | NRF_STATIC_INLINE uint32_t nrf_timer_task_address_get(NRF_TIMER_Type const * p_reg,
          |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:509:24: error: invalid storage class for function 'nrf_timer_event_clear'
      509 | NRF_STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type *  p_reg,
          |                        ^~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:521:24: error: invalid storage class for function 'nrf_timer_event_check'
      521 | NRF_STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type const * p_reg,
          |                        ^~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:532:28: error: invalid storage class for function 'nrf_timer_event_address_get'
      532 | NRF_STATIC_INLINE uint32_t nrf_timer_event_address_get(NRF_TIMER_Type const * p_reg,
          |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:541:24: error: invalid storage class for function 'nrf_timer_shorts_enable'
      541 | NRF_STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_reg,
          |                        ^~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:550:24: error: invalid storage class for function 'nrf_timer_shorts_disable'
      550 | NRF_STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_reg,
          |                        ^~~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:559:24: error: invalid storage class for function 'nrf_timer_shorts_set'
      559 | NRF_STATIC_INLINE void nrf_timer_shorts_set(NRF_TIMER_Type * p_reg,
          |                        ^~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:569:42: error: invalid storage class for function 'nrf_timer_short_compare_clear_get'
      569 | NRF_STATIC_INLINE nrf_timer_short_mask_t nrf_timer_short_compare_clear_get(uint8_t channel);
          |                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    C:/Nordic4/v2.9.0/modules/hal/nordic/nrfx/hal/nrf_timer.h:578:42: error: invalid storage class for function 'nrf_timer_short_compare_stop_get'
      578 | NRF_STATIC_INLINE nrf_timer_short_mask_t nrf_timer_short_compare_stop_get(uint8_t channel);
       
Related