6. Chapter Buzzer
In this chapter, we will learn about buzzers and the sounds they make. And in our next project, we will use an active buzzer to make a doorbell and a passive buzzer to make an alarm.
6.1. Project Doorbell
We will make a doorbell with this functionality: when the Push Button Switch is pressed the buzzer sounds and when the button is released, the buzzer stops. This is a momentary switch function.
Raspberry Pi (with 40 GPIO) x1 GPIO Extension Board & Ribbon Cable x1 Breadboard x1 |
|||
NPN transistorx1 (S8050) |
|
||
Push Button Switch x1 |
Resistor 1kΩ x1 |
Resistor 10kΩ x2 |
|
Jumper Wire |
|||
6.1.1. Component knowledge
6.1.1.1. Buzzer
A buzzer is an audio component. They are widely used in electronic devices such as calculators, electronic alarm clocks, automobile fault indicators, etc. There are both active and passive types of buzzers. Active buzzers have oscillator inside, these will sound as long as power is supplied. Passive buzzers require an external oscillator signal (generally using PWM with different frequencies) to make a sound.
Active buzzer
Passive buzzer
Active buzzers are easier to use. Generally, they only make a specific sound frequency. Passive buzzers require an external circuit to make sounds, but passive buzzers can be controlled to make sounds of various frequencies. The resonant frequency of the passive buzzer in this Kit is 2kHz, which means the passive buzzer is the loudest when its resonant frequency is 2kHz.
How to identify active and passive buzzer?
As a rule, there is a label on an active buzzer covering the hole where sound is emitted, but there are exceptions to this rule.
Active buzzers are more complex than passive buzzers in their manufacture. There are many circuits and crystal oscillator elements inside active buzzers; all of this is usually protected with a waterproof coating (and a housing) exposing only its pins from the underside. On the other hand, passive buzzers do not have protective coatings on their underside. From the pin holes, view of a passive buzzer, you can see the circuit board, coils, and a permanent magnet (all or any combination of these components depending on the model.
Passive buzzer
Passive buzzer
6.1.1.2. Transistors
A transistor is required in this project due to the buzzer’s current being so great that GPIO of RPi’s output capability cannot meet the power requirement necessary for operation. A NPN transistor is needed here to amplify the current.
Transistors, full name: semiconductor transistor, is a semiconductor device that controls current think of a transistor as an electronic “amplifying or switching device”. Transistors can be used to amplify weak signals, or to work as a switch. Transistors have three electrodes (PINs): base (b), collector (c) and emitter (e). When there is current passing between “be” then “ce” will have a several-fold current increase (transistor magnification), in this configuration the transistor acts as an amplifier. When current produced by “be” exceeds a certain value, “ce” will limit the current output. at this point the transistor is working in its saturation region and acts like a switch. Transistors are available as two types as shown below: PNP and NPN,
PNP transistor
NPN transistor
Note
In our kit, the PNP transistor is marked with 8550, and the NPN transistor is marked with 8050.
Thanks to the transistor’s characteristics, they are often used as switches in digital circuits. As micro-controllers output current capacity is very weak, we will use a transistor to amplify its current in order to drive components requiring higher current.
When we use a NPN transistor to drive a buzzer, we often use the following method. If GPIO outputs high level, current will flow through R1 (Resistor 1), the transistor conducts current and the buzzer will make sounds. If GPIO outputs low level, no current will flow through R1, the transistor will not conduct currentand buzzer will remain silent (no sounds).
When we use a PNP transistor to drive a buzzer, we often use the following method. If GPIO outputs low level, current will flow through R1. The transistor conducts current and the buzzer will make sounds. If GPIO outputs high level, no current flows through R1, the transistor will not conduct current and buzzer will remain silent (no sounds). Below are the circuit schematics for both a NPN and PNP transistor to power a buzzer.
NPN transistor to drive buzzer |
PNP transistor to drive buzzer |
|
|
6.1.2. Circuit
Schematic diagram with RPi GPIO Extension Shield |
Hardware connection. If you need any support,please feel free to contact us via:
|
Note
In this circuit, the power supply for the buzzer is 5V, and pull-up resistor of the push button switch is connected to the 3.3V power feed. Actually, the buzzer can work when connected to the 3.3V power feed but this will produce a weak sound from the buzzer (not very loud).
6.1.3. Sketch
In this chapter, we use a button to control the active buzzer. The code is similar to that in Chapter 3.
6.1.3.1. Sketch_06_1_Doorbell
First, enter where the project is located:
$ cd ~/Freenove_Kit/Pi4j/Sketches/Sketch_06_1_Doorbell
Enter the command to run the code.
$ jbang Doorbell.java
During the code running, press the button to sound the buzzer and release the button to stop it.
You can see messages printed on the terminal.
Press Ctrl+C to exit the code.
You can open the code with Geany to view and edit it, with the following command.
$ geany Doorbell.java
Click the icon to run the code.
If the code fails to run, please check Geany Configuration.
The following is program code:
1///usr/bin/env jbang "$0" "$@" ; exit $?
2
3//DEPS org.slf4j:slf4j-api:2.0.12
4//DEPS org.slf4j:slf4j-simple:2.0.12
5//DEPS com.pi4j:pi4j-core:2.6.0
6//DEPS com.pi4j:pi4j-plugin-raspberrypi:2.6.0
7//DEPS com.pi4j:pi4j-plugin-gpiod:2.6.0
8
9import com.pi4j.Pi4J;
10import com.pi4j.io.gpio.digital.DigitalState;
11import com.pi4j.util.Console;
12
13public class Doorbell{
14 private static final int PIN_BUTTON = 18;
15 private static final int PIN_BUZZER = 17;
16
17 public static void myPrintln(String tempText) {
18 Console console = new Console();
19 console.println("\u001B[32m" + tempText + "\u001B[0m");
20 }
21
22 public static void main(String[] args) throws Exception {
23 var pi4j = Pi4J.newAutoContext();
24 var buzzer = pi4j.dout().create(PIN_BUZZER);
25 var button = pi4j.din().create(PIN_BUTTON);
26
27 button.addListener(e -> {
28 if (e.state() == DigitalState.LOW) {
29 myPrintln("buzzer turned on. >>>");
30 buzzer.high();
31 }
32 else if(e.state() == DigitalState.HIGH){
33 myPrintln("buzzer turned off. >>>");
34 buzzer.low();
35 }
36 });
37
38 try{
39 while (true) {
40 Thread.sleep(500);
41 }
42 }
43 finally{
44 pi4j.shutdown();
45 }
46 }
47}
Please note that as the code is similar to that in chapter 3, here we do not explain it again.
In order to make the prompt messages printed by the terminal more conspicuous, we wrote the myprintln function to wrap the console.println function.
1 public static void myPrintln(String tempText) {
2 Console console = new Console();
3 console.println("\u001B[32m" + tempText + "\u001B[0m");
4 }
6.2. Project Alertor
Next, we will use a passive buzzer to make an alarm.
The list of components and the circuit is similar to the doorbell project. We only need to take the Doorbell circuit and replace the active buzzer with a passive buzzer.
6.2.1. Sketch
In this chapter, we use button to control the passive buzzer to make sound.
6.2.1.1. Sketch_Alertor
First, enter where the project is located:
$ cd ~/Freenove_Kit/Pi4j/Sketches/Sketch_06_2_Alertor
Enter the command to run the code.
$ jbang Alertor.java
When the code is running, press the button to sound the buzzer and release to stop it.
You can see messages printed on the terminal.
Press ctrl+C to exit the code.
You can open the code with Geany to view and edit it, with the following command.
$ geany Alertor.java
Click the icon to run the code.
If the code fails to run, please check Geany Configuration.
The following is program code:
1///usr/bin/env jbang "$0" "$@" ; exit $?
2
3//DEPS org.slf4j:slf4j-api:2.0.12
4//DEPS org.slf4j:slf4j-simple:2.0.12
5//DEPS com.pi4j:pi4j-core:2.6.0
6//DEPS com.pi4j:pi4j-plugin-raspberrypi:2.6.0
7//DEPS com.pi4j:pi4j-plugin-gpiod:2.6.0
8
9import com.pi4j.Pi4J;
10import com.pi4j.context.Context;
11import com.pi4j.io.gpio.digital.DigitalState;
12import com.pi4j.io.gpio.digital.DigitalInput;
13import com.pi4j.io.gpio.digital.DigitalOutput;
14import com.pi4j.util.Console;
15import java.util.HashMap;
16import java.util.Map;
17import java.util.Random;
18
19class PWMController implements Runnable {
20 private DigitalOutput pwm;
21 private int pwmFrequency;
22 private double pwmDutyCycle;
23 private boolean running = true;
24 private long period;
25 private long highTime;
26 private long lowTime;
27
28 public PWMController(DigitalOutput pwm) {
29 this.pwm = pwm;
30 this.pwmFrequency = 1000;
31 this.pwmDutyCycle = 0.5;
32 this.period = (int) (1000000 / pwmFrequency);
33 this.highTime = (int) (period * pwmDutyCycle);
34 this.lowTime = (int) (period - highTime);
35 }
36
37 @Override
38 public void run() {
39 while (running) {
40 if (highTime != 0) {
41 pwm.high();
42 delayUs(highTime);
43 }
44 if (lowTime != 0) {
45 pwm.low();
46 delayUs(lowTime);
47 }
48 }
49 }
50
51 public void setPwmFrequency(int frequency) {
52 if (frequency != 0) {
53 this.pwmFrequency = frequency;
54 this.period = (int) (1000000 / pwmFrequency);
55 this.highTime = (int) (period * pwmDutyCycle);
56 this.lowTime = (int) (period - highTime);
57 } else {
58 this.pwmFrequency = 0;
59 this.period = (int) (1000);
60 this.highTime = (int) (0);
61 this.lowTime = (int) (period - highTime);
62 }
63 }
64
65 public void setPwmDutyCycle(double dutyCycle) {
66 this.pwmDutyCycle = dutyCycle;
67 this.highTime = (int) (period * pwmDutyCycle);
68 this.lowTime = (int) (period - highTime);
69 }
70
71 private void delayUs(long us) {
72 long startTime = System.nanoTime();
73 long endTime = startTime + (us * 1000);
74 while (System.nanoTime() < endTime) {
75 }
76 }
77
78 public void requestStop() {
79 running = false;
80 }
81}
82
83public class Alertor {
84 private static final Context pi4j = Pi4J.newAutoContext();
85 private static final Map<Integer, PWMController> pwmControllers = new HashMap<>();
86 private static volatile int buttonState = 0;
87 private static int PIN_BUTTON = 18;
88 private static int PIN_BUZZER = 17;
89
90 public static void setPwmConfig(int pin) throws Exception {
91 DigitalOutput pwm = pi4j.dout().create(pin);
92 PWMController pwmController = new PWMController(pwm);
93 Thread pwmThread = new Thread(pwmController, "PWM Controller " + pin);
94 pwmControllers.put(pin, pwmController);
95 pwmThread.start();
96 Runtime.getRuntime().addShutdownHook(new Thread(() -> {
97 pwmController.requestStop();
98 try {
99 pwmThread.join();
100 } catch (InterruptedException e) {
101 Thread.currentThread().interrupt();
102 }
103 }));
104 }
105
106 public static void myPrintln(String tempText) {
107 Console console = new Console();
108 console.println("\u001B[32m" + tempText + "\u001B[0m");
109 }
110
111 public static void main(String[] args) throws Exception {
112
113 DigitalInput button = pi4j.din().create(PIN_BUTTON);
114 button.addListener(e -> {
115 buttonState = e.state() == DigitalState.LOW ? 1 : 0;
116 });
117
118 setPwmConfig(PIN_BUZZER);
119 PWMController buzzer = pwmControllers.get(PIN_BUZZER);
120 buzzer.setPwmFrequency(0);
121 buzzer.setPwmDutyCycle(0.5);
122
123 try {
124 while (true) {
125 if (buttonState == 1) {
126 myPrintln("buzzer turned on. >>>");
127 buzzer.setPwmFrequency(1000);
128 } else {
129 myPrintln("buzzer turned off. >>>");
130 buzzer.setPwmFrequency(0);
131 }
132 Thread.sleep(100);
133 }
134 }
135 finally {
136 for (PWMController controller : pwmControllers.values()) {
137 controller.requestStop();
138 }
139 pi4j.shutdown();
140 }
141 }
142}
Create a pi4j context for manipulating the GPIOs, and define the GPIO numbers that control the keys and buzzer.
1private static final Context pi4j = Pi4J.newAutoContext();
2private static final Map<Integer, PWMController> pwmControllers = new HashMap<>();
3private static volatile int buttonState = 0;
4private static int PIN_BUTTON = 18;
5private static int PIN_BUZZER = 17;
Initialize the button input pin, create a monitoring event, and assign the key value to buttonState when the button state changes.
1DigitalInput button = pi4j.din().create(PIN_BUTTON);
2button.addListener(e -> {
3 buttonState = e.state() == DigitalState.LOW ? 1 : 0;
4});
Initialize the PWM pin that controls the passive buzzer.
1setPwmConfig(PIN_BUZZER);
2PWMController buzzer = pwmControllers.get(PIN_BUZZER);
3buzzer.setPwmFrequency(0);
4buzzer.setPwmDutyCycle(0.5);
When buttonState is 1, the passive buzzer sounds, and when buttonState is 0, the buzzer sound is turned off. Print the information in the console.
1if (buttonState == 1) {
2 myPrintln("buzzer turned on. >>>");
3 buzzer.setPwmFrequency(1000);
4} else {
5 myPrintln("buzzer turned off. >>>");
6 buzzer.setPwmFrequency(0);
7}








