Learn Arduino with Olympia Circuits
Learn Arduino
  • Home
    • Get Started
    • How to Use This Site
  • Electronics
    • The Basics
    • Electricity Flows like Water
    • Electronic Components
    • The Arno Board
  • Programming
    • The Basics
    • setup and loop Blocks
    • Variables and Arrays
    • Connecting with the Pins
    • Flow Control >
      • if Statement
      • Loops
      • Delays
    • Functions
    • Serial Communication
    • USB
    • Some Thoughts
  • Projects
    • Projects 1 >
      • 1.01: Blink
      • 1.02 Blink x2
      • 1.03 Blink Faster
      • 1.04 LED Chase!
      • 1.05 Wait To Blink
      • 1.06 Blink a Little Faster Now
      • 1.07 LED Fade
      • 1.08 RGB Blink
      • 1.09 Change RGB Color with SW1
      • 1.10 Fade RGB Colors
      • 1.11 Reaction Time Game
    • Projects 2 >
      • 2.01 Hello World
      • 2.02 Talk Back
      • 2.03 ASCII Values
      • 2.04 Ski Game
      • 2.05 Demonstration of the String Object
    • Projects 3 >
      • 3.01 Read the Potentiometer
      • 3.02 ASCIIbet Soup
      • 3.03 Potentiometer sets LED Brightness
      • 3.04 Potentiometer Sets Blink Rate
      • 3.05 LED Chase, Part II
    • Projects 4 >
      • 4.01 Bringing the Piezo to Life
      • 4.02 Controlling the Piezo with a Function
      • 4.03 Piezo C Major
      • 4.04 Piezo Greensleaves
      • 4.05 Piezo Metronome
      • 4.06 Piezo as an Input
      • 4.07 Piezo as an Input 2
      • 4.08 Metronome II
      • 4.09 Piezo Playback
      • 4.10 Piezo Fireworks
      • 4.11 Piezo Mosquito
    • Projects 5 >
      • 5.01 The Phototransistor
      • 5.02 Light and Sound
      • 5.03 Light and Sound II
    • Projects 6 >
      • 6.01 EEPROM
      • 6.02 I2C Address Scan
      • 6.03 Read the I2C Temperature Sensor
      • 6.04 High Temperature Alarm
    • Projects 7 >
      • 7.01 Arno Phone Home
      • 7.02 Keyboard Alphabet
      • 7.03 Move Mouse
      • 7.04 Draw Squares
    • Special Projects >
      • Bike Light Demo
  • References
    • Arno Pin Key
    • Arno Schematic
    • Project Index

Project 4.09 Piezo Playback

 In the previous project, we measured the average time between four strikes on the piezo and played back the tempo.  In this project, we record eight taps and playback the rhythm.  In other words, we play back the same patterns of taps instead of just the average rate.  Upload this sketch and tap on the peizo eight times to get it going.  Press SW1 to reset the sketch and prepare it to record another set of taps.

Concepts:  analogRead, arrays, boolean variable type, functions, switching pinMode

Circuits:
  • Circuit 2
  • Circuit 3
  • Circuit 4


  • Select Sketch

    ///////////////////////////////////////////////////
    //Project 6.08 Piezo Playback
    int piezo = A11;
    int knock = 0;
    int redLED = 9;
    int SW1 = 1;
    long periods[7];
    long times[8];
    int count = 0;
    int playback = 0;
    void setup(){
    pinMode(redLED,OUTPUT);
    pinMode(SW1,INPUT);
    void clearPiezo();
    }
    void loop(){
    knock = analogRead(piezo);
    if(knock > 40){
    times[count] = millis();
    digitalWrite(redLED,HIGH);
    delay(50);
    digitalWrite(redLED,LOW);
    count ++;
    while(knock > 20){
    clearPiezo();
    knock = analogRead(piezo);
    }
    }
    if(count==8){
    pinMode(piezo,OUTPUT);
    count = 0; //reset for next time
    //calculate period
    for(int j = 0; j<7; j++){
    periods[j] = times[j+1] - times[j];
    //make delays at least 50 milliseconds
    if(periods[j] < 51) periods[j] = 51;
    }
    //now play back until SW1 pressed
    playback = 0;
    while(digitalRead(SW1)==HIGH){
    //create tone
    digitalWrite(redLED,HIGH);
    piezoTone(2500,50);
    digitalWrite(redLED,LOW);
    if(playback<7){
    delay(periods[playback] - 50);
    }
    else{
    delay(periods[6]);
    }
    playback ++;
    if(playback==8) playback=0;
    } //end while for SW1
    while(digitalRead(SW1)==LOW){
    clearPiezo();
    }
    } //end if for count = 7
    }
    void clearPiezo(){
    pinMode(piezo,OUTPUT);
    digitalWrite(piezo,LOW);
    delay(1);
    pinMode(piezo,INPUT);
    }
    void piezoTone(long freq, long duration){
    long aSecond = 1000000;
    long period = aSecond/freq;
    duration = duration*1000;
    duration = duration/period;
    for(long k = 0; k < duration; k++){
    digitalWrite(piezo,HIGH);
    delayMicroseconds(period/2);
    digitalWrite(piezo,LOW);
    delayMicroseconds(period/2);
    }
    }
    ///////////////////////////////////////////////////

    Much of this sketch is the same as the previous one. On difference is that we need to record the time between strikes on the piezo.  We store the values in the array periods:

    long periods[7];

    Look back at the previous project to see how we record the timing of each strike.  We’re going to skip forward to the point where we test to see if eight strikes have been recorded:

    if(count==8){

    First, we switch piezo to an output to prepare it to playback the rhythm.  We also reset the variable count that was used to determine when eight strikes had been recorded:

        pinMode(piezo,OUTPUT);

        count = 0; //reset for next time

        //calculate period

    Next, we calculate the time between strikes and load the results in the array periods.  We also make sure that each period is at least 50 milliseconds:

        for(int j = 0; j<7; j++){

          periods[j] = times[j+1] - times[j];

          //make delays at least 50 milliseconds

          if(periods[j] < 51) periods[j] = 51;

        }

    Now we prepare to playback the rhythm until SW1 is pressed and goes to LOW:

    //now play back until SW1 pressed

        playback = 0;

        while(digitalRead(SW1)==HIGH){  

    We begin by playing a tone and flashing redLED:

          //create tone

          digitalWrite(redLED,HIGH);

          piezoTone(2500,50);

          digitalWrite(redLED,LOW);

    We have 7 periods between tones.  They start at 0 (the first element of all arrays) and go up to 6.  We use the variable playback to keep track of which element of periods to use:

          if(playback<7){

            delay(periods[playback] - 50);

          }

    What do we do after the last tone is played?  If we start over again right away, it would just merge with the previous tone.  So when we get to the seventh period (the sixth element of the array) we replay it.  In other words, we repeat the last period between tones before we start the sequence over again:

          else{

            delay(periods[6]);

          }   

    Now we increment playback and reset it once it reaches 8.  Then we go back to the top of the while loop: 

          playback ++;

          if(playback==8) playback=0;

        } //end while for SW1

    If we break out of the while loop by pressing SW1, we reset piezo to an input to prepare it for the next set of strikes:

        pinMode(piezo,INPUT);

      } //end if for count = 7

    }

    Back to Projects 4

    Copyright Olympia Circuits LLC 2014. All Rights Reserved.