nRF51822 : Timer capture and PWM generation with softdevice

Hello,

I have been developing some products over the nRF51822 BLE. Got my introduction with nRF about 2 months back and despite the steep learning curve I was able to integrate the softdevice with LESC passkey and some GPIO peripheral control for a BLE Lock product. NRF team has been a GREAT HELP.

Now I want to add one more peripheral that is a 125KHz RFID card reader. I have figured out the hardware for the same. It basically fires a 125KHz to the coil and depending on the load from RFID card, a data stream of one and zero is received from a comparator. 

Refer this link https://www.serasidis.gr/circuits/RFID_reader/125kHz_RFID_reader.htm

I basically want to integrate this using the nordic mcu.

I figured out the PWM output using the app__pwm example. I am a bit stuck on capturing the waveform. I get that I have to start the timer in counter mode triggered by one GPIO but I am not able to do this along with the softdevice running in parellel.

Please let me know of any literature available or any example for the same.

What I had done so far : 

1. BLE stack along with peer manager is working perfectly

2. A couple of notify and write characteristics are available to take care of the peripherals.

3. I have used two timers so far, one for the SD and one 100ms to do all my control related tasks.

4. I was able to generate a 125KHz PWM on one GPIO.

What I need to do : 

To capture the pulses on one GPIO (pin P0.07 in my case). How I perceive this is that I can make an array to store the capture values and then process it any time. Let me know if I am looking at this in a wrong way.

Peripherals used so far : 

/*****/control task timmer
APP_TIMER_INIT(0, 4, false);
    err_code = app_timer_create(&m_control_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                control_timeout_handler);
    err_code = app_timer_start(m_control_timer_id, APP_TIMER_TICKS(100, 0), NULL);

/*****/peer manager timer
    uint32_t err_code = app_timer_create(&m_sec_req_timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
    err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL);
                            sec_req_timeout_handler);

/*****/pwm output
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(8L, MCU1); // 125KHz on MCU1 pin
    err_code = app_pwm_init(&PWM1,&pwm1_cfg,NULL);
    APP_ERROR_CHECK(err_code);
    app_pwm_enable(&PWM1);
    app_pwm_channel_duty_set(&PWM1, 0, 50); //set initial duty as zero (instanct, channel, !duty)

/*****/general GPIOs on about 6 pins that are handled accross the code.

I also got to know about the PPI+timer+gpiote method but I was not able to get it running.

Also for me power consumption is very critical since it is a battery operated device. Any extra hardware uses a lot of power as I observed so I want to make it very minimal.(< 0.5mA total during idle operation).

Thanks & Regards

Parents
  • Hi,

    Please let me know of any literature available or any example for the same.

    You can find some examples in this post: devzone.nordicsemi.com/.../ppi-configuration-to-count-pulses

  • Hello,

    Thanks for the reply.

    So I tried to use the examples provided, but when i integrate it in my code, the BLE part does not work. I think this is some issue related to timer conflicts because as soon as i comment the timer init part everything works.

    I was able to use the GPIOTE and get the interupt counts from the pulses but pulse width count is creating problem.

    As I mentioned I am already using one PWM channel, one timer for control part and softdevice must be using one. So I am not sure how to proceed here.

    Thanks

  • shwetank vishnu said:
    I think this is some issue related to timer conflicts because as soon as i comment the timer init part everything works.

    What timer init part are you referring to here?

  • The timer init that is in the code that you shared. Below is the code.

    void timer_init()
    {
        ret_code_t err_code;
        // Configure TIMER1 for counting of low to high events on GPIO
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        timer_cfg.mode = NRF_TIMER_MODE_COUNTER;
        err_code = nrf_drv_timer_init(&m_timer_count, &timer_cfg, timer_handler_count);
        APP_ERROR_CHECK(err_code);
    
        // Configure TIMER2 for reading the counter timer at a given interval COUNT_READ_INTERVAL
        timer_cfg.mode = NRF_TIMER_MODE_TIMER;
        err_code = nrf_drv_timer_init(&m_timer_read, &timer_cfg, timer_handler_read);
        APP_ERROR_CHECK(err_code);
        
        uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer_read, COUNT_READ_INTERVAL);
        nrf_drv_timer_extended_compare(&m_timer_read,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       true);
        nrf_drv_timer_enable(&m_timer_read);
    }

    It is used along with the GPIOTE and PPI initialization. 

  • shwetank vishnu said:
    So I tried to use the examples provided, but when i integrate it in my code, the BLE part does not work.

    The SoftDevice uses TIMER0, but this timer_init functions uses TIMER1 and TIMER2, so it should not be a conflict here. Do you know if you use e.g. TIMER1 for something else in your application?

  • So as I said, I am using one timer for control purpose i.e. a 100ms generic timer interrupt and one APP_PWM to generate the 125KHz pulse.

    void pwm_init()
    {
    uint32_t err_code;
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(8L, MCU1); // 125KHz on MCU1 pin
    err_code = app_pwm_init(&PWM1,&pwm1_cfg,NULL);
    APP_ERROR_CHECK(err_code);
    app_pwm_enable(&PWM1);
    app_pwm_channel_duty_set(&PWM1, 0, 100); //set initial duty as zero (instanct, channel, !duty)
    }
    
    void control_timer_init()
    {
    APP_TIMER_INIT(0, 4, false);
    err_code = app_timer_create(&m_control_timer_id,
    APP_TIMER_MODE_REPEATED,
    control_timeout_handler);
    err_code = app_timer_start(m_control_timer_id, TIMER_INTERVAL, NULL);
    }

    Now I am not sure what timer do either of these use since APP_PWM and APP_TIMER are handled internally.

    To re-iterate what I want to do : 

    1. Use the softdevice and peer manager for BLE.

    2. One 125KHz pulse.

    3. One generic timer for control part (50 - 100msec).

    4. A method to measure incoming pulse width.

  • Hi,

    app_timer uses RTC. But app_pwm will use a TIMER instance.

    There are 3 TIMER instances on the nRF51.

    Softdevice uses TIMER0, so 2 timers left for the application.

    app_pwm uses 1, and timer_init() code uses 2(m_timer_count and m_timer_read).

    Maybe you can try to remove m_timer_read, and use e.g an app_timer to trigger the reading of m_timer_count instead.

Reply Children
Related