Buzzer and PWM

This tutorial explains how to implement a Grove buzzer using a pulse width modulated (PWM) signal, a technology that we will present on this occasion.

Prerequisites

  1. A Grove Base Expansion Card
  2. NUCLEO-WB55 Board
  3. A buzzer Grove

Grove buzzer:

Plug the buzzer into the Grove Base Shield D3 connector. It vibrates and produces a sound when a voltage is transmitted to it. You can change the sound frequency by generating a PWM signal on the buzzer control pin.


Grove buzzer


Image credit : Seeed Studio

What’s a PWM ?

Pulse Width Modulation (PWM) is a method used for simulating an analog signal using a digital source. We generate a square signal, of given frequency, which is at +3.3V (high) for a configurable proportion of the period and at 0V (low) the rest of the time. It’s a way to modulate the energy sent to a device. Applications: to control motors, to vary the intensity of an LED, to vary the frequency of a buzzer… The proportion of the duration of a period during which the voltage is in the “high” state is called the “Duty Cycle”. The figure below shows three PWM signals with duty cycles of 25%, 50% and 75% (from bottom to top).


Grove buzzer


Program PWM on a NUCLEO-WB55 board

In practice, the generation of PWM signals is one of the functions provided by the timers, components integrated in the microcontroller that behave like programmable meters. The STM32WB55 contains several timers, and each of them controls several channels. Some channels of some timers are connected to Microcontroller output pins (GPIO). These pins can be used to generate PWM control signals.

MicroPython allows you to easily program pins in PWM output mode, but you will need to know:

  1. Which pins of the NUCLEO-WB55 are possible PWM outputs;
  2. Which timers and channels are connected to these pins in the STM32WB55.

The figure and table below provide these two information:


PWM WB55 PWM WB55


MicroPython code

The following scripts are available in the download area.

The code consists in having the buzzer read “in loop” an array frequency encoding a range of musical notes. The channel and timer of the PWM D3 pin used are identified from the mapping plan in the figure above.

# Objet of the script : Play a jingle on a buzzer (Grove or other).
# This example demonstrates the use of PWM for pin D3 on which the
# buzzer is plugged in.

from pyb import Pin, Timer

# List of notes that will be played by the buzzer
frequency = [262, 294, 330, 349, 370, 392, 440, 494]

# D3 generates a PWM with TIM1, CH3
BUZZER = Pin('D3')

while True :
	# Iteration between 0 and 7
	for i in range (0,7) :
		# Adjust frequency during iteration
		tim1 = Timer(1, freq=frequency[i])
		ch3 = tim1.channel(3, Timer.PWM, pin=BUZZER)
		# Duty cycle set to 5% (the buzzer is powered 5% of the time of a period)
		ch3.pulse_width_percent(5)