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.

Parents
  • Which Timer are you using? RTC? if so which instance? make sure that the instance you are using is not used by anything else in your system. Preferably use RTC1 or 2 if available.

  • I have used a generic GPIO and timer on other examples in the past. I am not using it now for this application. I wanted to use the capture capability of the PWM. I see there is a ...\v3.02\zephyr\tests\drivers\pwm\pwm_loopback example. this looks like it uses a PWM output connected to a PWM input that does use capture capabilities. I tired to understand and build this but was unsuccessful. there is not an overlay for nRF9160 so I could not get it to compile. Is this what I need to understand to do PWM measure frequency and period. The example is not very clear is there some description of the PWM loopback example?

  • can the nRF9160 SICA B1A use a PWM input to capture the input frequency? if so how o I do that?

  • 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);
    }
    

Reply
  • 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);
    }
    

Children
No Data
Related