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

PWM with a piezo buzzer

I'm trying to get some sound out of a piezo buzzer using the PWM library here:

github.com/.../nrf51-pwm-library

My buzzer has a resonant frequency of 2,730Hz. The buzzer doesn't have its own driver, I need to generate the wave for it. What changes do I need to make to main_sin.c to get that frequency?

Here's what I've tried so far.

int main(void)
{
    uint32_t counter = 0;
    
    nrf_pwm_config_t pwm_config = PWM_DEFAULT_CONFIG;
    
    pwm_config.mode             = PWM_MODE_BUZZER_64; // Was PWM_MODE_LED_100
    pwm_config.num_channels     = 1; // Was 3

    // One channel only, on pin 14
    pwm_config.gpio_num[0]      = 14; // Was 8
    // pwm_config.gpio_num[1]      = 8;
    // pwm_config.gpio_num[2]      = 10;
    
    // Initialize the PWM library
    nrf_pwm_init(&pwm_config);

    while (true)
    {
        // Update the 3 outputs with out of phase sine waves
        nrf_pwm_set_value(0, sin_table[counter]);
        // nrf_pwm_set_value(1, sin_table[(counter + 33) % 100]);
        // nrf_pwm_set_value(2, sin_table[(counter + 66) % 100]);
        counter = (counter + 1) % 100;
        
        // Add a delay to control the speed of the sine wave
        // 125 kHz is one wave every 0.000008s or 0.008ms or 8us, so why is this 8000us?
        // nrf_delay_us(8000);

        // If 8000us gets us 125kHz, then 366,300 should get us 2730Hz.
        nrf_delay_us(366300);
    }
}

As the comments above show, I'm confused about how this delay relates to the PWM frequency.

I'd also like to be executing other code while the buzzer is sounding and thought that PPI made this possible. So why the while() loop here at all?

  • Eliot,

    By duty cycle of 50% he means the following ...

    nrf_pwm_set_value(0, sin_table[counter]); where sin_table[counter] value what be 50% of the pwm max value. If pwm max = 2930 then half of that (50%) would give 1465.

    Hope that helps.

  • I see the confusion: my buzzer requires 2,730Hz, not 2,930Hz. Half of that is 1,365. Do you mean I need to scale up the values in the sine table so that they peak at 1,365, like this?

    	uint32_t value = (float)sin_table[counter]/255.0f * 1365.0f;
        nrf_pwm_set_value(0, value);
    

    Running that produces no sound yet. I'm sure my pwm_config is wrong. Currently using this:

    nrf_pwm_config_t pwm_config =
    	{.num_channels  = 1,             // Was 3
    	.gpio_num       = {14},          // Was 8,9,10
    	.ppi_channel    = {0,1,2,3,4,5},
    	.gpiote_channel = {2,3,0},
    	.mode           = PWM_MODE_BUZZER_2730HZ};
    
  • Your frequency was taken into account in the formula TORBJØRN provided above ...

    pwm_max_value = 16000000/ (2 * 2^0* 2730) = 2930 2930 is not in hertz. it is the max pwm value, the max counter value for the timer compare.

    So between 0-2930 with a prescaler of 0 the pwm frequency will be 2730 and a variable duty cycle depending of the value to set with the nrf_pwm_set_value function.

    nrf_pwm_set_value(0,1465) gives a 2730 Hz signal with 50% duty nrf_pwm_set_value(0,500) gives a 2730 Hz signal with ~6% duty

    If you added the code given by TORBJØRN you should be generating the correct frequency.

    have you attempted to manually set the duty cycle? nrf_pwm_set_value(0, 1465); Try to manually set it instead of using the sin table.

    This will help you debug.

    Do you have any means off verifying the frequency being generated on the pin? oscope? dmm? Make sure you are getting a signal first.

    If you aren't using the softdevice make sure USE_WITH_SOFTDEVICE is set to 0. By default in the pwm.h I believe it is 1. This will definitely cause an app failure.

    Good Luck.

  • Thanks. USE_WITH_SOFTDEVICE is definitely 0 and I've tested with the nrf_pwm_set_value(0, 1465) hard coded. No joy.

    Don't yet have a scope but will see what I can see with a multimeter.

  • Are you able to update your source code? Then I can run it and let you know my results.

    If not I understand.

Related