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.

Parents
  • Hi Bojan,

    Thank you for a great explanation of the problem. Sorry for the confusion in the last reply, I've edited the last reply. Starting the HFCLK immediately in the start of main will prevent the switching between HFINT  and the HFXO, Could you provide a trace from the oscilloscope of the glitch? Also, could you share your main file?

    regards

    Jared 

  • Hello ,

    Sorry for a late reply, we were waiting for the Logic Analyzer to arrive. I finally recorded the PWM signal sequences and here is what we get:

    I was recording our PWM signal for about 20 seconds. Our PWM clock (.base_clock) was set to 1MHz. We drive the buzzer with the 988Hz frequency (1.012ms period) so we get about 20K PWM sequencies. For each sequence, we measure and display frequency of the PWM driver signal. SoftDevice is present in our code but we stoped BLE advertising during the moments we drive the buzzer with PWM driver. Here are the results:

     What I can say is that there is no PWM glitch but that the frequencies/periods of PWM signal varies from sample to sample (in a range from desired 988Hz to almost 993Hz). There are also moments in time when the frequencies dip down and this is probably when we can feel the wobbling of the sound.

    We tried to use 16MHz clock for our PWM driver and this is what we get:

    Variations between the frequencies are less pronounced but the wobbling of the sound still remains.

    The main question here is: if we set the period of the PWM signal to 1.012ms/988Hz with 

    .top_value    = 1000000 / frequency, // default frequency = 988Hz
     

    for 1MHz PWM clock or with

     

    .top_value    = 16000000 / frequency, // default frequency = 988Hz
     

    for 16MHz PWM clock, why the frequencies of  PWM signal slightly vary from sample to sample? Is there any internal conflict inside nRF52840 SoC?

    Thanks once again for your time and effort. It is really appreciated!

    Sincerely,

    Bojan.

  • Hi,

    The variation that you're experiencing isn't really that much and is within what we would expect of the PWM peripheral. The variation is due to the inaccuracy of the HFXO. I'm not really sure if the woobling is due to the small drops in frequency because i've seen several applications that has used the PWM peripheral with a buzzer without the woobling sound. Are you able to drive the buzzer directly from the development kit and see if the issue persists?

    Jared

Reply
  • Hi,

    The variation that you're experiencing isn't really that much and is within what we would expect of the PWM peripheral. The variation is due to the inaccuracy of the HFXO. I'm not really sure if the woobling is due to the small drops in frequency because i've seen several applications that has used the PWM peripheral with a buzzer without the woobling sound. Are you able to drive the buzzer directly from the development kit and see if the issue persists?

    Jared

Children
Related