Arduino Modulino Buzzer Tutorial

What is an Arduino Modulino Buzzer?

The Arduino Modulino Buzzer is a maker-friendly module that allows a user to quickly play a melody or sound alarms. The Buzzer module (Arduino Part number ABX00108) was originally offered as part of the Arduino Plug and Make kit. Like all Modulino modules, it features a Qwiic connector for breadboard-free connection with similarly equipped modules. Also, like its Modulino Pixels counterpart, the Modulino Buzzer features a 32-bit STMicroelectronics ARM microcontroller. The low-cost ARM Cortex M0 microcontroller handles the I2C communication and drives the Murata Electronics Piezioelectric buzzer.

This engineering brief serves as a bridge extending the easy-to-use module to the underlying hardware and communication protocols. While the Arduino Modulinos were built for simplicity, there is a need for advanced students to understand and integrate the design into their own custom designed Printed Circuit Boards (PCBs).

Figure 1: Image of the Arduino Modulino Buzzer module. The large, surface-mount Murata buzzer is in the center of the board. The tiny 32-bit STM ARM microcontroller is visible in the lower left corner.

Getting started with Arduino Modulino Buzzer

In many respects, the buzzer operates similarly to the Arduino tone( ) function, in that it accepts a frequency and a duration parameter:

  • The frequency is an integer value for the desired tone in Hz.
  • Duration is the desired time, in milliseconds for the tone to sound.

For example, this code will sound a 1 kHz tone for a duration of 250 ms:

buzzer.tone(1000, 250);

Tech Tip: Arduino makes it very easy to get started with the Modulino boards. Provided you have properly installed the modulino library, you can find example code by following File > Examples > Modulino > Modulino_Buzzer. This is the same IDE location for classic programs such as File > Examples > 01 Basic > Blink.

Object-oriented programming

The Modulino API (Application Programming Interface) is designed using a high-level C++ object-oriented language. We can see the components in the code below including a constructor to create a buzzer object. We also see several methods that operate on the object including begin( ) and tone( ). Note that dot notation is used to associate a method with an object. The first part is the object, and the second part is the operation performed on the object.

#include <Modulino.h>

ModulinoBuzzer buzzer;   // Constructor

void setup() {
  Modulino.begin( );
  buzzer.begin( );      // Initialize the buzzer object
  pinMode(2, OUTPUT);
}

void loop() {
  uint16_t duration = random(100, 500);
  uint16_t note = random(200, 4000);
  digitalWrite(2, HIGH);           // Flag used by the logic analyzer
  buzzer.tone(note, duration);
  digitalWrite(2, LOW);
  delay(duration);                 // ***YOU MUST WAIT*** for the specified duration before sending the next tone. 
}

Blocking code

You may already grok (deeply understand) blocking code as you likely encounter the Arduino delay( ) function. We call this a blocking function as program execution is halted when delay( ) is counting down. It’s as if the microcontroller has blinders on; it will ignore all other activities during the delay( ) operation. For example, the program will not respond to a pushbutton while the delay( ) is in effect.

Tech Tip: Blocking is an oversimplification as most microcontrollers operate using Interrupt Service Routines (ISR) to handle time-critical background tasks. These behind-the-scenes operations are not blocked by delay( ). For example, the pushbutton we mentioned earlier could leverage the interrupt( ) library. Please leave a comment below if you would like to explore this essential topic.

Now that we better understand blocking, we can state that the Modulino Buzzer’s tone( ) command is non-blocking. When called, this function sends a message to the Modulino Buzzer. The Arduino then continues with other tasks in loop( ). For the note to play its full duration, we must include a blocking mechanism. This is highlighted in the previous code listing with the YOU MUST WAIT comment. Observe that the tone( ) method is called with the same duration. In this case, the Modulino’s STM microcontroller and the Arduino UNO R4 microcontroller are both counting down time.

Tech Tip: The “YOU MUST WAIT” delay is not coordinated between the Arduino proper and the Modulino. It is up to you to command a similar wait time for each device. Remember that the Arduino sends the Modulino a single packet of information. There is no handshake or “I’m done” message when the Modulino Buzzer is complete. Best practice is to keep the duration the same between the tone( ) method and the delay( ) function.

Communication protocol

The Modulino Buzzer is connected to the main Arduino controller using a Qwicc connector. This is a convenient feature for a large variety of microcontroller expansion board are available.

I2C vs SPI

Recall that the iic in Qwiic stands for “Inter-Integrated Circuit” commonly spoken as “eye-squared-see.” It’s an old protocol dating back 40 years. Its primary purpose is on-board connection of microcontrollers and sensors. It is especially useful when multiple low-speed devices are required as opposed to the Serial Peripheral Interface (SPI) which is preferred for high-speed connection of single devices. Note that the I2C protocol takes the time to address each component using a 2-wire bus (SDA and SCL) while SPI uses a 3 or 4-wire bus (MOSI, MISO, SCK, and sometimes SS) to talks to a single component.

Tech Tip: DigiKey offers thousands of sensors, analog to digital converters, digital to analog converters, and a host of specialized devices. Many are available with I2C SPI or sometimes both connections. Remember SPI for high-speed, singular device connections and I2C for slower application that require multiple devices to share a common on-board network.

Modulino Buzzer protocol

The I2C communication protocol is addressed-based. Communication begins when the primary microcontroller sends the unique address to the device of interest. In the Figure 3 example, the communication begins with the Arduino UNO R4 sending the hex 0x3C value. The Modulino Buzzer acknowledges the “wake-up call.” The R4 then sends 8 bytes of information.

Observation with the Digilent Analog Discovery Pro 2230 suggests that the data are sent 4-bytes for frequency and 4-bytes for duration. The total time required for the frame is approximately 1 ms. The test setup is shown in Figure 2. Figure 3 presents the results.

I will leave it to you to reverse engineer the frame. It shouldn’t be too difficult as you can program a specific tone and duration and then observe the result. Hint: This appears to be a little-Endian protocol.

Figure 2: Setup used to observe the communication protocol between the Arduino UNO R4 WiFi and the Modulino Buzzer module. The Digilent Analog Discovery Pro is visible in the background.

Figure 3: Data is transferred as a frame starting with the default 0x3C address followed by 4 byes for frequency and 4 bytes for duration.

Tech Tip: It is often useful to use a microcontroller pin as a trigger to synchronize the logic analyzer or oscilloscope. In Figure 3 we see that Digital input 0 (DI0) is used as the trigger. The software method is included in the previous code snippet. The use of the random tone and random duration allows the user to hear the tone and see the pattern on the logic analyzer.

Tech Tip: The random( ) function is not as random as you might initially think. You can convince yourself of this by pressing the Arduino reset button. The same pseudorandom notes will be played each time the unit is reset. This is a fascinating topic that leads to cryptography and national security. Please visit this NIST page for additional information. Also see the Arduino randomSeed( ) function and its relationship to an unconnected A1 input pin.

Parting thoughts

The Arduino Modulino Buzzer allows a user to quickly set up and program classic microcontroller routines. With fine control over tone and duration, you could play a song, provide auditory feedback for a switch press, or provide a multitude of tone specific alarms.

As a challenge, I encourage you to locate and then adapt Arduino code to play the Super Mario theme Song. As another challenge, use the Modulino Knob along with the Buzzer to construct a metronome.

Please leave your comments below if you have any questions about this product. Finally, we would love to see how it was used in your projects.

Best wishes,

APDahlen

Related Information

Please follow these links to related and useful information:

About this author

Aaron Dahlen, LCDR USCG (Ret.), serves as an application engineer at DigiKey. He has a unique electronics and automation foundation built over a 27-year military career as a technician and engineer which was further enhanced by 12 years of teaching (interwoven). With an MSEE degree from Minnesota State University, Mankato, Dahlen has taught in an ABET-accredited EE program, served as the program coordinator for an EET program, and taught component-level repair to military electronics technicians. Dahlen has returned to his Northern Minnesota home and thoroughly enjoys researching and writing articles such as this.