5. Using the Buzzer

In this quick tutorial I will demonstrate how to make Mono buzz, using the simple API in the SDK

Mono has a built-in buzz speaker. The speaker is directly connected to a GPIO on Mono’s MCU. We have configured the MCU such that the GPIO pin is used by a hardware PWM. This means the speaker is driven by a square pulse signal generated by the MCU hardware. The software only has to turn the PWM on and off.

Simple Example

Let us begin with a code snippet that beeps for 0.5 sec:

void AppController::monoWakeFromReset() {
    
    // Get a pointer to the buzzer object
    mono::sensor::IBuzzer *buzzer = mono::IApplicationContext::Instance->Buzzer;

    // make a beep for 0.5 sec
    buzzer->buzzAsync(500);
}

First we get a pointer to the current buzzer object that has been created by the global ApplicationContext object. All buzz-speaker objects must implement the IBuzzer interface, that defines methods to emit buzzing sounds.

Then we use the method buzzAsync that turns on the speaker. The important thing here is to note that the buzzing is asynchronous. The signal sent to the speaker is hardware generated, so the software does not need to do anything. When buzzAsync returns, the buzzing is still going on - and will it do so for the next 0.5 sec.

Multiple Beeps

If you what to make, say 3 beeps in a row, you need to use callbacks. This is due to the asynchonous behaviour of the IBuzzer interface. Luckily there is a similar method called: buzzAsync(void (*callback)(void)). This method takes a callback function, that gets called when the buzzing has ended. We can use this function to chain the buzzing, thereby making multiple beeps.

To do this, we use the built-in Timer class to control the delay between beeps.

Note

This is the best practice approach. The lazy ones might choose to use several wait_ms() calls. But this approach will stall the CPU, making it unresponsive.

In our AppController we declare an integer count variable. We also add a callback function for the buzz (buzzEnded()) and one for the delay (pauseEnded()).

wakeFromReset:

void AppController::monoWakeFromReset() {

    // init the count to 0
    count = 0;
    
    mono::sensor:IBuzzer *buzzer = mono::IApplicationContext::Instance->Buzzer;
    
    // begin the buzzing (for 0.5 sec)
    buzzer->buzzAsync<AppController>(500, this, &AppController::buzzEnded);
}

buzzEnded:

void AppController::buzzEnded() {

    // increment the buzz beep count
    count++;

    // If we have buzzed less the 3 times, start a delay timer
    if (count < 3)
        mono::Timer::callOnce<AppController>(500, this, &AppController::buzzEnded);
}

pauseEnded:

void AppController::buzzEnded() {

    //the delay timed out - begin buzzing again

    // get the buzzer pointer
    mono::sensor:IBuzzer *buzzer = mono::IApplicationContext::Instance->Buzzer;
    
    // begin buzzing again (for 0.5 sec)
    buzzer->buzzAsync<AppController>(500, this, &AppController::buzzEnded);
}

Now, since we use Timers and async buzzing, Mono will stay responsive during both the buzzing and the pauses in between. This means it will keep sampling the touch input, updating display and running other timers in the background.

Killing a buzz

Say you might have called buzzAsync(60000), which is a one minute long buzz tone. After some seconds you regret the decision and wish cancel the buzzing. To do that you use the buzzKill() method! Calling this method will immediate stop any buzzing started earlier.

Note

If you have installed a callback at the end of your buzz - the callback will still get called.