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

PWM driver issue

Hello guys,

I have nRF52840-based BL654 SoC module on my custom board and I develop the firmware in SDK 15.0.0 environment with s140 SoftDevice.

Among other things, I need to drive the buzzer with BL654 module through the following driving circuit:

                                                  

Using PWM drivers from Nordic was a natural choise for me. Here is the part of my code reponsible for PWM initialization and playing the pwm pattern that drives the buzzer with 988Hz frequency and 50% duty cycle:

static nrf_drv_pwm_t m_pwm_beeper    = NRF_DRV_PWM_INSTANCE(0);

...

static uint32_t beeper_init(uint16_t frequency) {
    uint32_t err_code;

    nrf_drv_pwm_config_t const pwm_config_beeper = {
        .output_pins =
            {
                BEEPER,                   // channel 0
                NRF_DRV_PWM_PIN_NOT_USED, // channel 1
                NRF_DRV_PWM_PIN_NOT_USED, // channel 2
                NRF_DRV_PWM_PIN_NOT_USED  // channel 3
            },
        .irq_priority = PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
        .base_clock   = NRF_PWM_CLK_1MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 1000000 / frequency, // default frequency = 988Hz
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO};
    err_code = nrf_drv_pwm_init(&m_pwm_beeper, &pwm_config_beeper, NULL);
    APP_ERROR_CHECK_NON_FATAL(err_code);

    return err_code;
}

...

void turn_beeper_on(void) {
    m_beeper_seq_values.channel_0 = 50; // 50% duty cycle on channel 0
    if (get_beeper_volume() == 0) {
        NRF_LOG_INFO("Beeper is muted");
        return;
    }
    NRF_LOG_INFO("Turning on beeper: %d", m_beeper_seq_values.channel_0);

    nrf_drv_pwm_simple_playback(&m_pwm_beeper, &m_beeper_seq, 1,
                                NRF_DRV_PWM_FLAG_LOOP);
}

When I drive the buzzer with turn_beeper_on(void) function, I can clearly hear some sporadic and infrequent "wobbling" of the beeper sound. According to this thread, unwanted "wobbling" effect comes from the glitch error in PWM driver. It looks like the problem is related to the HFCLK switching from RC to XTAL, which happens every time the SoftDevice uses the radio (I use the BLE stack in my code).

According to this thread, PWM is shifting the phase when radio is active (due to switching between the 32khz & 16Mhz crystals - BLE-event requesting a clock change from RC to XTAL). Suggestion from the thread to start the crystal with sd_clock_hfclk_request() function before calling ble_advertising_start() function did not resolve the issue for me - some kind of PWM glitch still exists causing "wobbling" in beeper sound. 

 uint32_t p_is_running = 0;
	sd_clock_hfclk_request();
	while(! p_is_running) {  							//wait for the hfclk to be available
		sd_clock_hfclk_is_running((&p_is_running));
	}

    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);

Is there something I am missing here, some kind of prevention from PWM glitch issue?

Thanks in advance for your time and effort!

Sincerely,

Bojan.

Related