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

BLE Nano/Nordic SDK: making a quick buzz from a piezo speaker

I am working on a project using a ble nano (nrf51822) using the Nordic SDK 8.1. I started building off the ble-app-hrs in the examples of the documentation so my code is pretty similar to the example.
What I am trying to do is to have a piezo speaker make a quick couple of buzzes when a bond is made. To do this I went into the bsp_led_indication() method in bsp.c and added the following code for the BSP_INDICATE_CONNECTED case:

 case BSP_INDICATE_CONNECTED: // This case is used when a connection is made
        printf("BSP_INDICATE_CONNECTED\n");

        COMPONENTS_OFF(COMPONENTS_MASK & ~BSP_LED_0_MASK & ~ALERT_LED_MASK);
        COMPONENTS_ON(BSP_LED_0_MASK);

        beepCount++;
        if (beepCount <= 6) {
            COMPONENTS_INVERT(BSP_BUZZER_MASK);
            app_timer_start(m_leds_timer_id, BSP_MS_TO_TICK(500), NULL);
        }

        m_stable_state = indicate;
        break;

please not that I updated the boards.h file to add the following methods:

` #define COMPONENTS_ON(components_mask) do { NRF_GPIO->OUTSET = (components_mask) & (COMPONENTS_MASK & COMPONENTS_INV_MASK);
NRF_GPIO->OUTCLR = (components_mask) & (COMPONENTS_MASK & ~COMPONENTS_INV_MASK); } while (0)

#define COMPONENTS_OFF(components_mask) do { NRF_GPIO->OUTCLR = (components_mask) & (COMPONENTS_MASK & COMPONENTS_INV_MASK);
NRF_GPIO->OUTSET = (components_mask) & (COMPONENTS_MASK & ~COMPONENTS_INV_MASK); } while (0)

#define COMPONENTS_IS_ON(components_mask) ((components_mask) & (NRF_GPIO->OUT ^ COMPONENTS_INV_MASK) )

#define COMPONENTS_INVERT(components_mask) do { uint32_t gpio_state = NRF_GPIO->OUT;
NRF_GPIO->OUTSET = ((components_mask) & ~gpio_state);
NRF_GPIO->OUTCLR = ((components_mask) & gpio_state); } while (0)`

The problem I have now is that the buzzer will buzz for inconsistent times. for example, some times when a bond is made the buzzer will ring for 2 or 3 seconds before turning off and back on again (even though the delay is set to 500 ms). Is there a better way I can create a buzzing sound than adding a timer that recalls the bsp_led_indication() method? Also is there an easy way I can change the tone or pitch of the buzzer to improve the sound quality (currently the buzzer just makes an awful screeching sound when it is activated... This may just be due to the quality of the piezo speaker I purchased (I got it from radio shack). Is there a better component to make a beep sound?)

  • I would strongly recommend to use the PWM. I see that you have tried this earlier in this post, what is the reason you are not using PWM anymore?

  • @sigurd What is the advantage to using PWM? I tried using it but was unable to get it to work. What was happening was I would change the variables for the PWM and the tone wouldn't be effected at all. Since the behavior was the same as just using a normal write to the gpio and just setting the gpio to high or low was easier I removed the pwm. Do you have a good guide or explanation for how I can get PWM working?

  • The advantage of using the PWM library is that you get more precise timing on the period the signal is high/low, and therefore get a more stable frequency. The PWM library takes care of all the timing in order to produce a stable frequency. I suspected that this is the reason you get that “awful screeching sound” when not using PWM, and that you are using a frequency that is not resonating well with your buzzer. If you take a look in the buzzer datasheet, the resonance frequency should be listed. If you change the PWM frequency, the tone will change. There is a PWM example in the SDK, have you looked at that?: SDK_folder\examples\peripheral\pwm

  • @sigurd Yes I was looking at the example in \examples\peripheral\pwm. It doesn't do a good job of explaining what each variable does though. Like it doesn't have a variable set for the duty cycle or frequency which I need to know how to set. ..... The peripheral\pwm is actually the example I was previously using when I was having problems..... I think I may have used a pin without PWM but I'm not sure (how do I check if the pin has PWM ability). All I know is that I went in and changed the 'value' variable and the tone and volume of the buzzer was not impacted. How can I go about fixing this?

  • You can set the duty cycle with the app_pwm_channel_duty_set() function, and the period/frequency with the APP_PWM_DEFAULT_CONFIG_1CH()/APP_PWM_DEFAULT_CONFIG_2CH() function. You can vary the volume of the sound by modifying the duty cycle. 0% will produce no sounds, 50% will be the max volume. Between 50% and 100% is the same as between 0% and 50%. Different frequencies will give you different tones.

Related