/ / Introduction
diagram:
Inside the Piezo Buzzer
Piezo
A Piezo is an electronic device that can be used to play tones and to detect tones. The normal piezoelectric effect is generating electricity from squeezing a crystal. The piezo speaker consists of two metal plates and when electricity is applied to the piezo speaker it will make the metal plates attract and repel generating quick vibration which in turn will generate sound.Piezos have polarity. Commercial devices usually have a red and a black wire indicating how to plug it to the board. Connect the black one to ground and the red one to the input. You also have to connect a resistor in the range of the Megaohms in parallel to the Piezo element;
Sometimes it is possible to acquire Piezo elements without a plastic housing. These devices look like a metallic disc and are easier to use as input sensors.
To read a piezo you can
just hook it into an
analog input, but you need to drain off
any voltage with a
resistor, or it just builds
up.
When the Piezo element is used to detect sound, it is a knock sensor. Knock sensors read a voltage value and transform it into a value encoded digitally. When using an Arduino, you transform the voltage into a value in the range 0..1024. 0 represents 0 volts, while 1024 represents 5 volts at the input of one of the six analog pins.
The code example will capture the knock and if it is stronger than a certain threshold, it will send the string "Knock!" back to the computer over the serial port. In order to see this text you could either use a terminal program, which will read data from the serial port and show it in a window, or make your own program in e.g. Processing.

int ledPin = 13;
int piezoPin = 2;
int THRESHOLD = 100; // set minimum value that indicates a knock
int val = 0; // variable to store the value coming from the sensor
int t = 0; // the "time" measured for how long the knock lasts
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(19200);
Serial.println("ready"); // indicate we're waiting
}
void loop() {
digitalWrite(ledPin,LOW); // indicate we're waiting
val = analogRead(piezoPin); // read piezo
if( val >THRESHOLD ) { // is it bigger than our minimum?
digitalWrite(ledPin, HIGH); // tell the world
t = 0;
while(analogRead(piezoPin) > THRESHOLD) {
t++;
} // wait for it to go LOW (with a little hysteresis)
if(t>100) { // cut off the low values because they're noise
Serial.print("knock! ");
Serial.println(t);
}
}
delay(100); // make a delay to avoid overloading the serial port
}
/ / Piezo Read Revisited
Whack the piezo to generate a number based on force of whack
int piezo=0;
int led=13;
int THRESHOLD=100;
void setup(){
Serial.begin(9600);
}
void loop(){
digitalWrite(led,LOW);
val=analogRead(____);
if(val>=THRESHOLD){
digitalWrite(_____,_____);
t=0;
while(analogRead(___)>=(THRESHOLD/2)){
t++;
}
if(t!=0){
Serial.println(t);
}
}
}
/ /Motor Pulse
Wire up a Piezo and a motor
int ledPin = 13;
int knockSensor = 0;
byte val = 0;
int statePin = LOW;
int motor=___;
int THRESHOLD = 100;
int t;
void setup() {
pinMode(ledPin, OUTPUT);
beginSerial(9600);
}
void loop() {
val = analogRead(knockSensor);
if (val >= THRESHOLD) {
//reverse the state of the pins
___________________
//turn the led on
___________________
t=0;
while(analogRead(knockSensor)>THRESHOLD){
t++;
}
if (t!=0){
Serial.print("Knock!");
Serial.print(t);
analogWrite(motor,100);
delay(1000);
analogWrite(motor,0);
}
}
}
/ /Getting Creative
You can mount the element on anything
(under rugs, floor mat, door, your body, etc.)This one is glued to a larger brass disc for a drum trigger.
Hook a piezo up to something, connect with Processing. Every time someone knocks on your object, play a sound!
Playing Sounds in Processing
import ddf.minim.*; import processing.serial.*; String portname = "________________"; // get portame Serial port; // Create object from Serial class AudioSample sounds[]; //list your sounds and import them into processing String sound_names[] = { ________, ________, ________, ________, ________, ________ }; void setup(){ size(___, ____); background(______________); stroke(255); // always start Minim before you do anything with it Minim.start(this); Minim.debugOn(); sounds = new AudioSample[sound_names.length]; for( int i=0; i< sound_names.length; i++ ) { sounds[i] = Minim.loadSample(sound_names[i], 512); } // Open the port that the board is connected to and use the same speed (19200 bps) port = new Serial(this, portname, 19200); } void draw(){ // do the drawing on events } void soundball() { int r = int(random(sounds.length)); println("picked sound #"+r); sounds[r].trigger(); // play a random sound int x = int(random(0,300)); int y = int(random(0,300)); fill(240,0,0); ellipse(x,y, 40,40); fill(30,0,0); ellipse(x,y, 8,8); } void serialEvent(Serial p) { char inByte = port.readChar(); println("received char: "+ inByte); if( inByte == '!' ) { // '!' is end of "knock!" soundball(); } } void keyPressed() { if(key == ' ') { background(40,40,40); // erase screen } soundball(); } void stop(){ // always close Minim audio classes when you are done with them for( int i=0; i<sounds.length; i++ ) { sounds[i].close(); } super.stop(); }
/ / Cheesy Hallmark Card
/* Play Melody
* -----------
*This example uses a piezo speaker to play melodies.
*It sends a square wave of the appropriate frequency
* to the piezo to generate the corresponding tone.
* Program to play melodies stored in an array, it requires to know
* about timing issues and about how to play tones.
*
* The calculation of the tones is made following the mathematical
* operation:
*
* timeHigh = 1/(2 * toneFrequency) = period / 2
*
* where the different tones are described as in the table:
*
* note frequency period PW (timeHigh)
* c 261 Hz 3830 1915
* d 294 Hz 3400 1700
* e 329 Hz 3038 1519
* f 349 Hz 2864 1432
* g 392 Hz 2550 1275
* a 440 Hz 2272 1136
* b 493 Hz 2028 1014
* C 523 Hz 1912 956
*
* (cleft) 2005 D. Cuartielles for K3
*/
int ledPin = 13;
int speakerOut = 9;
// the number of notes
int length = ____;
char names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
int beats[]={1,1,1,1,1,1,2,1,1,1,1,1,1,2,4};
char notes[]=ccggaagffeeddc "; //space at end represents a rest
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
int tempo=300;
void setup(){
//set the piezo and the led to outputs
}
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
//set the piezo to 5V
_______________________
//create the tone by setting the amount of time to delay
delayMicroseconds(______);
//set the piezo to 0V
_____________________
//create the tone by setting the amount of time to delay
delayMicroseconds(______);
}
}
void playNote(char note, int duration) {
// play the tone corresponding to the note name
//create a for loop that iterates over the 8 notes in your array
________________________________________
//test if the current name equals the note passed into the function
_____________________
//if condition met, then call the function playTone and pass it the current tone and
//the duration passed into this function
_________________
}
}
}
void loop() {
//create a for loop to iterate over the length of your tune
_________________________
//test if the note is a rest
___________________________
//if condition is met, then call delay and pass it the
//current beat multiplied by your tempo variable
___________________
//otherwise, call playNot and pass it the current note, and the current beat
//multiplied by your tempo
________________________
}
// pause between notes by calling delay and passing it half the tempo
________________
}
}
The timing for each note is calculated based on variables, as such you can tweak the sound of each note or the timing. To change the speed of the melody all you need to do is change the value of tempo. Change it to a larger number to slow the melody down, or a smaller number to speed it up.
If you are worried about the notes being a little out of tune this can be fixed as well. The notes have been calculated based on a formula in the comment block at the top of the program. But to tune individual notes just adjust their values in the tones[] array up or down until they sound right. (each note is matched by its name in the names[] (array ie. c = 1915 )
char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
Composing your own melodies:
The program is programmed to play Twinkle Twinkle Little Star however the way it is programmed makes changing the song easy. Each song is defined in one int and two arrays, the int length defines the number of notes, the first array notes[] defines each note, and the second beats[] defines how long each note is played.An example: Twinkle Twinkle Little Star
int length = 15;
char notes[] = "ccggaagffeeddc ";
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
1, 1, 2, 4 };
int length = 13;
char notes[] = "ccdcfeccdcgf ";
int beats[] = {1,1,1,1,1,2,1,1,1,1,1,2,4};
Play your own Melody with Serial
/* Sound Serial (aka Keyboard Serial)
* ------------
*
* Program to play tones depending on the data coming from the serial port.
*
* The calculation of the tones is made following the mathematical
* operation:
*
* timeHigh = 1/(2 * toneFrequency) = period / 2
*
* where the different tones are described as in the table:
*
* note frequency period PW (timeHigh)
* c 261 Hz 3830 1915
* d 294 Hz 3400 1700
* e 329 Hz 3038 1519
* f 349 Hz 2864 1432
* g 392 Hz 2550 1275
* a 440 Hz 2272 1136
* b 493 Hz 2028 1014
* C 523 Hz 1912 956
*
* (cleft) 2005 D. Cuartielles for K3
*
* Updated by Tod E. Kurt <tod@todbot.com> to use new Serial. commands
* and have a longer cycle time.
*
*/
int ledPin = 13;
int speakerPin = 9;
// note names and their corresponding half-periods
byte names[] ={ 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
int serByte = -1;
int ledState = LOW;
int count = 0;
void setup() {
//set the led and piezo to OUTPUT
//initialize serial
}
void loop() {
//set the piezo to LOW
_______________________
//read in Serial
serByte = Serial.read();
//test if serByte does not equal -1
____________________
//print the serByte as a BYTE to Serial Monitor
__________(______,BYTE);
//flip the state of the led
______________________
//write the state of the led to the led pin
___________________
}
//create a for loop to iterate over the notes
______________________
//test if the current name equals the byte that came in through Serial
______________________
// play it for 50 cycles by creating a for loop that iterates 50 times
____________________
//turn the piezo high, wait the right amount of
//microseconds, turn it off, wait again
}
}
}
}
/ /Build an instrument
How to play a trumpet:c..........0pen d..........1-3 e..........1-2 f ..........1 g..........0pen / 1-3 a..........1-2 / 3 b..........2 C..........0pen / 2-3
Simplified for Arduino:
c..........1-2-3 d..........1-3 e..........1-2 f ..........1 g..........0pen a..........3 b..........2 C..........2-3
#define piezo 9 // Hook up speaker to digital pin 9
#define sw1 2 // Switch hooked to analog pin 1
#define sw2 3 // Switch hooked to analog pin 2
#define sw3 4 // Switch hooked to analog pin 3
int val1;
int val2;
int val3;
char names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
int tonesStart[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
int tonesEnd[] = { 1905, 1690, 1509, 1422, 1265, 1126, 1004, 946 };
int note;
void setup() {
//set the piezo to be an output
//set your switches to be inputs
//initialize Serial communication
}
void loop() {
//set each valve to read the state of the corresponding button valve1 and sw1
//using the arduino guide above construct your if statements
// If all buttons are pressed, then note is c
if (val1 && val2 && val3) {
note=0;
}
// If the first and third buttons are pressed, then note is d
else if (val1 && !val2 && val3) {
note=1;
}
//continue for all combinations
__________
...
}
//print the note in the serial monitor
_____________
//turn the speaker on, delay the appropriate amount of microseconds
//turn the speaker off and delay the appropriate amount of microseconds
}
An example:
/ /Build a theremin
A therimin is a musical instrument created by Leon Theremin. It works by responding to the body's electric field.
Make a circuit for a Theremin by adding a photocell
/* Theremin
* --------
*
*
* Created 24 October 2006
* copyleft 2006 Tod E. Kurt <tod@todbot.com
* http://todbot.com/
*/
int photoCell = 0; // select the input pin for the potentiometer
int speakerPin = 7;
int val = 0;
void setup() {
pinMode(speakerPin, OUTPUT);
beginSerial(9600);
Serial.println("ready");
}
void loop() {
digitalWrite(speakerPin, LOW);
val = analogRead(photoCell); // read value from the sensor
val = val*2; // process the value a little
//val = val/2; // process the value a little
for( int i=0; i<500; i++ ) { // play it for 50 cycles
digitalWrite(speakerPin, HIGH);
delayMicroseconds(val);
digitalWrite(speakerPin, LOW);
delayMicroseconds(val);
}
}/ /Soft Circuit
- Attach two wires 1/3 of the way on each side of the fabric. Stitch
the end of the wire without the covering plastic with conductive
thread and then attach the remaining part of wire to the fabric with
normal thread. Do not use conductive thread when you stitch the
rest of the wire to the fabric since this will create a short circuit
when you put the piezo speaker membrane in place.
The stitchings with normal thread are only meant to hold the wires in place. - Place
the piezo element over one side and fold the other side over it and stitch
everything together with normal thread. It’s good to stitch around
the membrane since it needs to be quite snug for the wires to connect
on both sides of the membrane.


- To
make the vibrations that generate sound pulse the piezo
with power. To make these pulses fast enough to generate vibrations
you can't use the normal delay() as this pause isn’t quick enough.
Instead use delayMicroseconds(). This code generates a vibration that creates the tone A:
The pause is what determines the tone generated. A 1911 microsecond delay would generate a C.
#define piezoPin 9 void setup() { /* declare the piezo pin as an output */ _________________ } void loop() { //set the pin HIGH ________________________ /* the time here will determine the tone */ delayMicroseconds(1136); //set the pin LOW ________________________ delayMicroseconds(1136); }
Oscillation with a Zipper
The analog zipper can give you a range of values in between 0V and 5V. To make a analog zipper you need:- a normal zipper
- some conductive thread
- 10kΩ resistor
-
Sew the resistor in place.
- Sew another color wire to the other end of the resistor

- Make a connection with conductive
thread from the other side of the resistor and all the way from the
bottom of the same side of the zipper all the way to the top. Make
sure you stitch in between all of the teeth’s of the zipper

- On the
other side sew a line from a black wire at the end
to the metal teeth of the zipper and make a few stitches between
the teeth, upwards, on the zipper.

- Plug the red wire into 5V
- Attach the black wire to GND ports
- Attach the last wire to
analog pin 2.
- To be able to show what kind of values
the zipper gives us, you will need to use serial communication so
that the Arduino can report back to the computer and show you the
values in the serial monitor:
/* declare that you want to use analog pin 2 and call it analogPin */ _______________ /*declare an integer that will act as a temporary variable so you can store the values that the zipper will give you */ __________________ void setup(){ Serial.begin(9600); } void loop(){ /*Do an analog reading on analogPin and save the value in the zipper varible */ _____________________ /*print the value to the monitor*/ ________________ delay(200); } - If you
can’t see any numbers in your monitor, make sure the communication
speed set in the Arduino IDE is the same as in your program
(9600 baud in this example). Each zipper will give you different
values since making an analog zipper isn’t an exact science yet, the
slightest difference will affect the result. This form of home made
analog sensor is still good enough to be used for most prototypes
that need a hidden input device.
- Wire up your Piezo on pin 10.
- Here is new code:
/* declare the pin the piezo speaker is attached to*/ ______________ /* declare the pin the zipper is attached to */ ___________ /* declares a temporary storage variable (type int)*/ _____________ /* declare a variable for the remapped value */ ________________ void setup(){ /*declare your output pin*/ ________________ } void loop(){ /* read and store the value from the zipper */ ______________________ /* remapp the value from the zipper to fit within the range of 0 through 2000 */ = map(____,100,300,0,2000); /*send 5V to the piezo speaker */ __________________ /* pause with the remapped value */ delayMicroseconds(_______); /* send 0V to the piezo speaker */ ________________ /* pause with the remapped value */ delayMicroseconds(_______); }
You needed to use the map function because your zipper might give values good enough to set some tones directly, but they will have much lower range than wanted since an analog sensor never gives a value above 1023.
Test your oscillator.
The Soft Synth
- Create an interface like the one pictured below

The blue wires should be connected to Arduino digital 2-6.
The black wire should be attached to GND - Wire up your piezo
- This program check all the buttons as soon as one of them is pushed
it will start to play the tone of that key. In this example we are going
to use the tones C, D, E, F and G.
C 1911 D 1703 E 1517 F 1432 G 1276 A 1136 B 1012 C 0956
Here is the program:/* declare the pin which the piezo speaker is attached to */ ________________ /* declare the first soft button */ ________________ /* declare the second soft button */ ________________ /* declare the third soft button */ ________________ /* declare the fourth soft button */ ________________ /* declare the fifth soft button */ ________________ void setup(){ /* declare the piezopin as output */ ________________ /* declare the first soft button as input */ ________________ /* declare the second soft button as input */ ________________ /* declare the third soft button as input */ ________________ /* declare the fourth soft button as input */ ________________ /* declare the fifth soft button as input */ ________________ /* send 5V to the first soft button */ ________________ /* send 5V to the second soft button */ ________________ /* send 5V to the third soft button */ ________________ /* send 5V to the fourth soft button */ ________________ /* send 5V to the fifth soft button */ } void loop(){ /* test if the first soft button is pushed */ ________________ /* sends 5V to the piezo speaker */ ________________ /* wait for 1911 microseconds (creates a C) */ ________________ /* stop sending 5V to the piezo speaker */ ________________ /* wait for another 1911 microseconds */ ________________ } //complete the code for the other 4 buttons }