Wednesday 9/28 – Lab 5: Output: Piezo speakers

Before the Lab

You should have experiments with the force sensitive resistor and photosensor to control your LEDs. You should have also used the force sensitive resistor and photosensor to control a Processing program on your computer. Congratulations!

In Lab Exercise

Special Note

If you finish early, please use the extra time to solder some wires onto your motor, which we will be using in the near future.

Objective

Using the piezo to make sound.

Activities

Part 1 – The Piezo Buzzer

1. Connect the Arduino to the Piezo Buzzer.

2. There are two sample programs on the course website. Give them a shot:

This sample code plays a song on your speaker:


/* Play Melody
 * -----------
 *
 * 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 = 7;               
byte names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};  
int tones[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
byte melody[] = "2d2a1f2c2d2a2d2c2f2d2a2c2d2a1f2c2d2a2a2g2p8p8p8p";
// count length: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
//                                10                  20                  30
int count = 0;
int count2 = 0;
int count3 = 0;
int MAX_COUNT = 24;
int statePin = LOW;

void setup() {
 pinMode(ledPin, OUTPUT); 
 pinMode(speakerOut, OUTPUT);
}

void loop() {
  digitalWrite(speakerOut, LOW);     
  for (count = 0; count < MAX_COUNT; count++) {
    statePin = !statePin;
    digitalWrite(ledPin, statePin);
    for (count3 = 0; count3 <= (melody[count*2] - 48) * 30; count3++) {
      for (count2=0;count2<8;count2++) {
        if (names[count2] == melody[count*2 + 1]) {       
          digitalWrite(speakerOut,HIGH);
          delayMicroseconds(tones[count2]);
          digitalWrite(speakerOut, LOW);
          delayMicroseconds(tones[count2]);
        } 
        if (melody[count*2 + 1] == 'p') {
          // make a pause of a certain size
          digitalWrite(speakerOut, 0);
          delayMicroseconds(500);
        }
      }
    }
  }
}

This sample code lets you control the note using Serial input:



/* 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 = 7;

// note names and their corresponding half-periods  
byte names[] ={ 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};  
unsigned int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
  
int ledState = LOW;
int count = 0;

// what we read in from serial
char serInString[100];  // array that will hold the different bytes of the string. 100=100characters;
                        // -> you must state how long the array will be else it won't work properly
char serNote;

void setup() {
  pinMode(ledPin, OUTPUT); 
  pinMode(speakerPin, OUTPUT); 
  Serial.begin(9600);
  Serial.println("ready");
}

void loop() {
  // Read data from Serial /////////////////
  // clear the string
  memset(serInString, 0, 100);
  //read the serial port and create a string out of what you read
  readSerialString(serInString);
  
  // Reset speaker to not play anything
  digitalWrite(speakerPin, LOW);
  
  // if your note plays forever, uncomment this section
  // by deleting the "/*" and "*/"
  /*
  // if there is no new input over Serial, then just skip the rest of the 
  // loop() and check again
  if (serInString[0] == 0) {
    return; 
  } 
  */
  
  // if we get any new input over the Serial port
  if (serInString[0] != 0) {
    ledState = !ledState;           // flip the LED state
    digitalWrite(ledPin, ledState); // write to LED
    // remember what the note is we should be playing
    serNote = serInString[0];
    Serial.println(serNote);
  }
  
  for (count=0;count<=8;count++) {  // look for the note
    if (names[count] == serNote) {  // ahh, found it
      Serial.print(serNote);
      Serial.print(" is a note we can play. tones[count] = ");
      Serial.print(tones[count]);
      Serial.println();
      for( int i=0; i<50; i++ ) {   // play it for 50 cycles
        //Serial.print(i); Serial.print(" ");
        digitalWrite(speakerPin, HIGH);
        delayMicroseconds(tones[count]);
        digitalWrite(speakerPin, LOW);
        delayMicroseconds(tones[count]);
      }
    }
  }
}

//read a string from the serial and store it in an array
//you must supply the array variable
void readSerialString (char *strArray) {
  int i = 0;
  if(!Serial.available()) {
    return;
  }
  while (Serial.available()) {
    strArray[i] = Serial.read();
    i++;
  }
}

3. If you want to reduce the volume of the piezo speaker, you can add a resistor in series with the speaker:

Part 2 –Make a Theremin

A Theremin is an instrument designed to be played without being touched. You will make one here using your piezo buzzer and the photosensor.

1. Build the Theremin circuit. Note that this is just the photocell circuit and the piezo circuit combined.

2. The software to control the Theremin is here:



/* Theremin
 * --------
 *
 *
 * Created 24 October 2006
 * copyleft 2006 Tod E. Kurt &lt;tod@todbot.com
 * http://todbot.com/
 */

int potPin = 0;    // select the input pin for the potentiometer
int speakerPin = 7;

int val = 0;

void setup() {
  pinMode(speakerPin, OUTPUT); 
  Serial.begin(9600);
  Serial.println("ready");
}

void loop() {
  digitalWrite(speakerPin, LOW);
  
  val = analogRead(potPin);    // 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&lt;500; i++ ) {  // play it for 50 cycles
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(val);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(val);
  }
}

Homework

Input output coincidence exercise. Design an artifact where both input and output occur at the same place. Use any combination of your input transducers and output transducers (pot, photocell, FSR, LEDs, piezo, screen). E.g., a ball that changes colors and/or plays different sound/melody depending on the pressure being applied. A stick you can twist to color or sound differently… These are just examples to spark your imagination. Be creative!