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

Changing connection interval cause issue with PWM

Edit 2: Files need to reproduce the issue described in this questions:

pwm_conn_itvl_bug_files.zip

To reproduce the issue please just replace the main.c and nrf_drv_config.h into a ble_app_uart example in SDK v10.0.0, and put the project files into /s110/arm5_no_packs.


Further inspection shows that sd_ble_gap_ppcp_set() (at line 127 of attachment's main.c) returns error code 7, which should be NRF_ERROR_INVALID_PARAM? This is strange because I believe that 2000ms is still well below the 4s limit.


Edit 1:

I am using the PWM library to generate a PWM of period about 27us. After I tried changing the connection interval a little bit, I have noticed that any max_conn_interval greater than or equal to MSEC_TO_UNITS(1999, UNIT_1_25_MS) cause the PWM signal to become completely wrong.

For example,

  • With MSEC_TO_UNITS(2000, UNIT_1_25_MS) I am looking at a PWM signal with 3700ms period with 2600ms high.
  • Meanwhile, with MSEC_TO_UNITS(1999, UNIT_1_25_MS), I got a PWM signal with 26.80~27.20us period with 13.60us high, very close to my intended 27us period with 50% duty cycle.

Is there any reason for this? I don't think I see anything mentioned in the PWM library documentation.

For reference, I am using SDK v10.0.0, with SoftDevice S110 v8.0.0 on nRF51 DK. I started with ble_app_uart example, strip off all NUS code, add a Device Information Service in with just Serial Number field and now just started working with PWM.

Below is all of my code that I think is relevant.

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(1999, UNIT_1_25_MS)             /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(1999, UNIT_1_25_MS)             /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */

...

APP_PWM_INSTANCE(PWM, 2);

...

/**@brief Function for initializing the Connection Parameters module.
 */
static void conn_params_init(void)
{
    uint32_t               err_code;
    ble_conn_params_init_t cp_init;
    
    memset(&cp_init, 0, sizeof(cp_init));

    cp_init.p_conn_params                  = NULL;
    cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
    cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
    cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
    cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
    cp_init.disconnect_on_fail             = false;
    cp_init.evt_handler                    = on_conn_params_evt;
    cp_init.error_handler                  = conn_params_error_handler;
    
    err_code = ble_conn_params_init(&cp_init);
    APP_ERROR_CHECK(err_code);
}

...

/** @brief  Initialize PWM signal
  */
static void pwm_init(void)
{
    uint32_t err_code;
    app_pwm_config_t pwm_config = APP_PWM_DEFAULT_CONFIG_1CH(27, 29);
    err_code = app_pwm_init(&PWM, &pwm_config, NULL);
    DEBUG_MAIN_PRINTF(("app_pwm_init returns %d\n", err_code));
    DEBUG_MAIN_PRINTF(("period = %d\n", app_pwm_cycle_ticks_get(&PWM)));
    APP_ERROR_CHECK(err_code);
    app_pwm_enable(&PWM);
    
    while (app_pwm_channel_duty_set(&PWM, 0, 100) == NRF_ERROR_BUSY);
}


/**@brief Application main function.
 */
int main(void)
{
    uint32_t err_code;
    bool erase_bonds;
    uint8_t  start_string[] = START_STRING;
    
    // Initialization starts -----------------------------------------------------------------------
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
    uart_init();
    buttons_leds_init(&erase_bonds);
    
    pwm_init();
    
    ble_stack_init();
    gap_params_init();
    services_init();
    advertising_init();
    conn_params_init();
    // Initialization ends -------------------------------------------------------------------------
    
    printf("%s",start_string);
    
  
    while (app_pwm_channel_duty_set(&PWM, 0, 50) == NRF_ERROR_BUSY);

    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
    
    
    
    // Enter main loop.
    for (;;)
    {
        power_manage();
    }
}
Related