Introduction to Speakers

Piezoelectric speaker

What you see in the picture above is a piezoelectric speaker – a tiny, electrically controlled diaphragm. On the back is a small crystal. When there is power flowing through the crystal, the size changes, bending the diaphragm. The change in the diaphragm is what causes sound and music as we know it. Today, let’s go through how we can make music with a piezo and Arduino.

Basic sketch

Piezo is greek for “press” or “Squeeze”.

Take a look at your piezo – as a general type of thing, it should remind you of an LED. No, it doesn’t blink and it’s not going to light up, but it’s got two legs, one long and one short. Long story short – long leg goes to pin 6, short leg goes to GND. Let’s copy the following code and see what happens:

#define PIEZO_PIN (6)

void setup() {
  pinMode(PIEZO_PIN,OUTPUT);
}

void loop() {
  digitalWrite(PIEZO_PIN,HIGH);
  delay(100);
  digitalWrite(PIEZO_PIN,LOW);
  delay(100);
}

Hear anything? What’s actually happening is a tiny “pop” sound ten times per second. Let’s try changing the delay and see what happens.

Just like your vocal chords, piezos cause air vibrations. If you go fast enough on your piezos and it’s going to start sounding like musical notes.

Middle “C” (C4)

The standard piano has 88 keys; the term middle C refers to the “C” key closest to the center. Hitting up google gives us a frequency of 262.62 Hz give or take. That means approximately 261 times on and off every second, and 1/261 seconds of a pause between each. Check it out in our code:

#define PIEZO_PIN (6)
                             // The 4th C on the keyboard
#define C4 (261.625565)

void setup() {
  pinMode(PIEZO_PIN,OUTPUT);
}

void loop() {
  play_one_note(C4);
}

void play_one_note(float frequency) {
                              // 1000000 microseconds (us) in a second
  float duration = 1000000;
                              // the time to stay on or off
  float hold_time = 1000000 / frequency;
                              // how long have we been playing this note?
  float t=0;
  while( t<duration ) {
    digitalWrite(PIEZO_PIN,HIGH);
                              // half the time on
    delayMicroseconds( hold_time );
    digitalWrite(PIEZO_PIN,LOW);
                              // half the time off
    delayMicroseconds( hold_time );
    t += frequency;
  }
}

Think about this one for a second – what happens if you try and play a bunch of notes?

Note length

Alright. We’ve figured out how to play notes – let’s play around with changing the length of each note. What do we have to do to make play_one_note() last a different amount of time?

#define NONE (0)
#define C4 (261.625565)
#define D4 (293.7)
#define E4 (329.6)
#define F4 (349.2)
                               // beats per minute
#define BPM (120.0)

void play_one_note(float frequency,float duration) {
  duration *= 1000000 * (60.0/BPM);

  if(frequency>0) {
    float t=0;

    int hold_time = 1000000.0/frequency;
    while(t<duration) {
      digitalWrite(PIEZO_PIN,HIGH);
                               // half the time on
      delayMicroseconds( hold_time );
      digitalWrite(PIEZO_PIN,LOW);
                               // half the time off
      delayMicroseconds( hold_time );
      t += hold_time;
    }
  } else {
    // silence
    delayMicroseconds(duration);
  }
}

void loop() {
  play_one_note(C4,1.00);     // almost a whole note
  play_one_note(D4,0.50);     // half note
  play_one_note(E4,0.50);     // half note
  play_one_note(F4,0.25);     // quarter note
  play_one_note(NONE,0.01);   // the tiniest pause
}

Whole songs

Okay. We can play notes that we want and we can hold it for different lengths. The next step is obvious – an orchestra. Well, maybe not yet. Let’s try playing a song! My approach is to make two arrays – the first will hold notes, and the second will hold lengths.

float notes[] = { C4,D4,E4,F4,NONE };
float times[] = { 1,0.5,0.5,0.25,0.01 };

void loop() {
  int note_count = sizeof(notes) / sizeof(float);

  for(int i=0;i<note_count;++i) {
    play_one_note(notes[i],times[i]);
  }
}

Alright, now we’re getting somewhere! Let’s find some sheet music and convert it to notes and lengths.

So, if we switch between two notes at the right speed you can make one speaker sound like it has two voices singing in harmony – keep in mind that this only makes them sound like it, and they’re technically not together. However, it sounds pretty close to the real thing. What we’ll need is one voice singing a bass line and the other voice being the melody, or the lead.

Questions

  • Can you make the Arduino work with more than one voice? How about 3, or even 4? Try converting the Tetris music score. If you want more of a challenge, try converting one of Bach’s concertos!

Special thanks to VHS member Bruce for pointing out that in the original article I described a magnet-coil speaker, not a piezoelectric speaker. My brain loaded the wrong schematic when I was trying to describe the inner workings. He also points out that you can build your own piezoelectric speaker. Cool!