Pages

Wednesday, December 3, 2014

Faking it with Music

Jill thinks I know a lot more than I do about making my lights blink to music.

I'm not musical enough to add music to code  from sheet music. I can't read music, but I know people who can. 

 So when I created my first arduino code to music when I took Caleb's class, I wanted Jeopardy music to play during my 'game buzzer' so I did what anybody who can't read music would do -I reached out to my musical children. Hey kiddos.. can anyone write out the notes to Jeopardy for me. When I tried it it sucked. I then reached out again and got a quick lesson on how to read the charts that convert notes to frequencies.   Here is the chat I saved from that remote lesson for future reference.

And below is the code I came up with that project. 

It basically played Jeopardy music  after the user presses start while the game participants think of the answer until one of them presses a buzzer




---------------------------------------------
/*
SparkFun Inventor's Kit
Lucie's Game Buzzer

This is a game buzzer that could be used for a classroom quiz game between two players.
In this case the MC (teacher) would ask a question, then start the Game Buzzer.
The Game Buzzer
The Game Buzzer plays a short tune  and displays on the LCD a message to start guessing. 
As soon as one player has a guess, they press their assigned button. 
The display shows which player "pressed the button" and turns on his/her assigned LED. 
The MC can now entertain that guess for the player who pressed the button first.

In the code example below I color coded the code to match the components
green is for main program code
orange is for code impacting the LCD
blue is for code impacting the buzzer
brown is for code impacting the pushbutton and LED of player 1 with yellow LED
red is for code impacting the pushbutton and LED of player 2 with Red LED
*/

// Load the LiquidCrystal library, 
#include <LiquidCrystal.h>

// Initialize the library with the pins we're using.
LiquidCrystal lcd(12,11,5,4,3,2);

// Assign the buzzer Pin
const int buzzerPin = 9;

// set up an array with the notes we want to play

// Length must equal the total number of notes and spaces 
const int songLength = 20;
const int jsongLength = 64;

// Notes is an array of text characters corresponding to the notes
// in your song. A space represents a rest (no tone)
char notes[] = "Bac bac bbbb cccc bac"; 
char jnotes[] = "gCgcgCggCgCE  DCbaGgCgefgCgC ag f e d c"; 



/* the new pitches Adam figured out for me were g, HC, g, LC, g, HC, g, g, HC, g, HC, HE, (double rest), HD, HC, b, a, g#, g, HC, g, LE, f, g, HC, g, HC, rest, a, g, rest, f, rest, LE, rest, LD, rest, LC 
with the following beats
2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 1,1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4


  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D','E','G' };
  int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 415};

*/

// Beats is an array of values for each note and rest.
// A "1" represents a quarter-note, 2 a half-note, etc.
// Don't forget that the rests (spaces) need a length as well.

int beats[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4};
int jbeats[] = {2, 2, 2, 2, 2, 2, 4, 2, 2, 2, 2, 1,1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4};


// The tempo is how fast to play the song.
// To make the song play faster, decrease this value.

int tempo = 150;
int jtempo = 200;


// Set up the buttons for Player 1 and 2 

const int button1Pin = 6;  // pushbutton 1 pin
const int button2Pin = 8; // pushbutton 2 pin
const int ledPinY =  13;    //  yellow LED pin
const int ledPinR = 1; // red pin 

// variables will change:
//int buttonPressed = 0;         // variable for reading if a button has been pushed 
//I was going to use this then decided this part was going to be for version 2.0 

void setup()
{

// Set up the buzzer pins to be an outpus:
pinMode(buzzerPin, OUTPUT);

// Set up the pushbutton pins to be an input:
 pinMode(button1Pin, INPUT);
 pinMode(button2Pin, INPUT);

 // Set up the LED pin to be an output:

 pinMode(ledPinY, OUTPUT);
 pinMode(ledPinR, OUTPUT); 
  
  // The LiquidCrystal library can be used with many different
  // LCD sizes. We're using one that's 2 lines of 16 characters,
  // so we'll inform the library of that:
   lcd.begin(16, 2);

  // clear any old data on the LCD
   lcd.clear();

  // Now we'll display a message on the LCD!  
  lcd.print("Ready To Guess?");

  // Adjusting the contrast with the Pentionmeter if necessary
     
}  //end setup

//Now for the main program

void loop()
{

//let's initialize our buttons 

   int button1State, button2State;  // variables to hold the pushbutton states
   button1State = digitalRead(button1Pin);
   button2State = digitalRead(button2Pin);
  
//checking to see if the buttons have been pressed 

while((digitalRead(button1Pin) == HIGH) && (digitalRead(button2Pin) == HIGH)) 

{
// if no buttons have been pressed play song

   int i, duration;
  
  for (i = 0; i < songLength; i++) // step through the song arrays
  {
    duration = beats[i] * tempo;  // length of note/rest in ms
    
    if (notes[i] == ' ')          // is this a rest? 
    {
      delay(duration);            // then pause for a moment
    }
    else                          // otherwise, play the note
    {
      tone(buzzerPin, frequency(notes[i]), duration);
      delay(duration);            // wait for tone to finish
    }
    delay(tempo/10);              // brief pause between notes

   //read the button state  
   button1State = digitalRead(button1Pin);
   button2State = digitalRead(button2Pin);

  } // end of song playing loop
  
  
 //  Check to see if button one is pressed and if it is turn on yellow light and change display
    
   if (button1State == LOW) 
   
                                                        // then...
  {
    digitalWrite(ledPinY, HIGH);  // turn the LED on then display message to LCD below

     lcd.begin(16, 2);
      lcd.clear();
     lcd.print(" Yellow Player can Guess ");


      int i, duration;
  
  for (i = 0; i < jsongLength; i++) // step through the song arrays
  {
    duration = jbeats[i] * jtempo;  // length of note/rest in ms
    
    if (jnotes[i] == ' ')          // is this a rest? 
    {
      delay(duration);            // then pause for a moment
    }
    else                          // otherwise, play the note
    {
      tone(buzzerPin, frequency(jnotes[i]), duration);
      delay(duration);            // wait for tone to finish
    }
    delay(jtempo/10);              // brief pause between notes
    
    
     
  }  
    lcd.clear();
     lcd.print(" Times Up ");   
  

    
  }
  else

//check to see if button 2 is pressed and if it is turn on red light and change display
  
   if (button2State == LOW) 
                                                        // then...
  {
    digitalWrite(ledPinR, HIGH);  // turn the LED on
     lcd.begin(16, 2);
      lcd.clear();
     lcd.print("Red Player Can Guess");
  
     int i, duration;
  
  for (i = 0; i < jsongLength; i++) // step through the song arrays
  {
    duration = jbeats[i] * jtempo;  // length of note/rest in ms
    
    if (jnotes[i] == ' ')          // is this a rest? 
    {
      delay(duration);            // then pause for a moment
    }
    else                          // otherwise, play the note
    {
      tone(buzzerPin, frequency(jnotes[i]), duration);
      delay(duration);            // wait for tone to finish
    }
    delay(jtempo/10);              // brief pause between notes
    
    
     
  }  
    lcd.clear();
     lcd.print(" Times Up ");   
  


  
  }
  else
  {
    digitalWrite(ledPinR, LOW);  // turn the LED off
  } //end of nested loop
    
  {
    digitalWrite(ledPinY, LOW);  // turn the LED off
  } // end of outer next If statement

}    // end the void loop program
  
  
  
  
  
  
  

  
  //  set the invisible cursor of the LCD  to the first column
  // (column 0) of the second line (line 1):

  lcd.setCursor(0,1);

  // Now we'll print the number of seconds (millis() / 1000)
  // since the Arduino last reset:

  lcd.print(millis()/1000);
  
}  // end of main program


//This is the function that gets called to play the tune


int frequency(char note) 
{
  // This function takes a note character (a-g), and returns the
  // corresponding frequency in Hz for the tone() function.
//Added some new frequencies to move across a second octave and include a G#
//uppercase G is really G# in this case 
  

  int i;
  const int numNotes = 11;  // number of notes we're storing
  
  // The following arrays hold the note characters and their
  // corresponding frequencies. The last "C" note is uppercase
  // to separate it from the first lowercase "c". If you want to
  // add more notes, you'll need to use unique characters.

  // For the "char" (character) type, we put single characters
  // in single quotes.
//added more notes to reach into a second octave and include a G#
//used the upper case G to represent G# so I didn't have to deal with strings


//  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D','E','G' };
//  int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 415};

 char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C','D','E','G' };
  
 int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 415};



  
  // Now we'll search through the letters in the array, and if
  // we find it, we'll return the frequency for that note.
  
  for (i = 0; i < numNotes; i++)  // Step through the notes
  {
    if (names[i] == note)         // Is this the one?
    {
      return(frequencies[i]);     // Yes! Return the frequency
    }
  }
  return(0);  // We looked through everything and didn't find it,
              // but we still need to return a value, so return 0.
}
----------------------------------------------------------------

BTW.. going through the Spark Inventor Kit was very helpful in filling in some major gaps my understanding of so many different things about science, coding, and more.  There are still gaps left, but I'm so glad I went through those lessons. 
Back to my musical hat.  
 So for my musical hat, I used the sketch that came with the Sweater you posted. The LED's just flash back and forth at different beats for the 3 songs. I going to trust that others who know more about music than I coded knew the right beat and coded it correctly. 

I started with the musical sweater code

And realized the Switch song part did not work. But it has some code it in that I understood.. so with LOTS of trial and error I pulled out ONE song and added it segment by segment to a simple sketch of BASIC Switch.


Here is where my sketch stands now.  I want to play more with it,  but can't get back to it for a day or two. 

It's a basic switch with 4 LED's  
When you turn on the switch the music plays and the LED's blink with the notes (alternate LED) 
It looks like the function runs INSIDE the loop that is part of PARSE TUNE function  and that some type of 'beat' is passed to that function  .  When I looked at the original code it looks like the beat sent with the notes changes with each of the four songs, but I have not analyzed it enough to see how closely the beats and LED blinking are in sync. 

As you can see I'm not expert... but building on bits of knowledge gained here and there
-------------------------------------------------------------------------

int speakerPin = 7;

int ledPin = 6; // LED is connected to digital pin 13
int switchPin = 2; // switch connected to digital pin 2
int switchValue; // a variable to keep track of when switch is pressed


int led1 = A2;                          
int led2 = A3;

int led3 = A4;

int led4 = 6;

int songChoice; 

int ledPattern = true;
 const int beatLength = 50;

//Play music functions
void playTone(int tone, int duration) {

for (long i = 0; i < duration * 1000L; i += tone * 2) {

digitalWrite(speakerPin, HIGH);

delayMicroseconds(tone);

digitalWrite(speakerPin, LOW);

delayMicroseconds(tone);

}

}
//teach Lilypad what the notes and play that note when you are told to

void playNote(char note, int duration, boolean sharp) {

char names[] ={'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D', 'E', 'F', 'G', 'A', 'B' };

int tones[]  = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 851, 758, 716, 636, 568, 506 };

char names_sharp[] = { 'c', 'd', 'f', 'g', 'a', 'C', 'D', 'F', 'G', 'A' };

int tones_sharp[] = { 1804, 1607, 1351, 1204, 1073, 902, 804, 676, 602, 536 };

if (sharp == false) {

for (int i = 0; i < 14; i++) {

if (names[i] == note) {

playTone(tones[i], duration);

}

}

} else {

for (int i = 0; i < 10; i++) {

if (names_sharp[i] == note) {playTone(tones_sharp[i], duration);

}

}

}

}
//--- stop music

void playTune () {

 // Jingle Bells

char notes[]="b4b4b8b4b4b8b4D4g6a2b12,4C4C4C6C2C4b4b4b2b2b4a4a4b4a8D8b4b4b8b4b4b8b4D4g6a2b12,4,C4C4C6C2C4b4b4b2b2D4D4C4a4g12,8.";

parseTune(notes, beatLength, false);

}

//parse tune


void parseTune(char notes[], int beatLength, boolean loopSong) {boolean play = true;

for (int i = 0; notes[i] != '.' && play == true; i++) {

 alternateLeds();

//updateSwitchState();

//if (switchState == LOW) {

//play = false;

//} else {

if (notes[i] == ',') {

char len[3];

int count = 0;

while (notes[i+1] >= '0' && notes[i+1] <= '9' && count < 2) {

len[count] = notes[i+1];

count++;

i++;

}

len[count] = '\0';

int duration = atoi(len);

delay(duration * beatLength);

} else {

//alternateLeds();

char note = notes[i];

boolean sharp;

if (notes[i+1] == '#') {

i++;

sharp = true;

} else {

sharp = false;

}

char len[3];

int count = 0;

while (notes[i+1] >= '0' && notes[i+1] <= '9' && count < 2) {

len[count] = notes[i+1];

count++;

i++;

}len[count] = '\0';

int duration = atoi(len);

playNote(note, duration * beatLength, sharp);

}

delay(beatLength / 2);

}

}

//if (loopSong == true) {

//switchState = LOW;

//}

// make your LED blinsk

void alternateLeds() 
{

if (ledPattern == true) {

digitalWrite(led1, LOW);

digitalWrite(led2, HIGH);

digitalWrite(led3, LOW);

digitalWrite(led4, HIGH);

ledPattern = false;

} else {

digitalWrite(led1, HIGH);

digitalWrite(led2, LOW);

digitalWrite(led3, HIGH);

digitalWrite(led4, LOW);

ledPattern = true;

}
}

// stop alternate pattern


//------------

   
void setup()  
{  
      pinMode(ledPin, OUTPUT); // sets the ledPin to be an output
      pinMode(switchPin, INPUT); // sets the switchPin to be an input
      digitalWrite(switchPin, HIGH); // sets the default (unpressed) state of switchPin to HIGH

pinMode(speakerPin, OUTPUT);

pinMode(led1, OUTPUT);

pinMode(led2, OUTPUT);

pinMode(led3, OUTPUT);

pinMode(led4, OUTPUT);


//pinMode(buttonPin, INPUT);

}  
   
void loop() // run over and over again
{  
      switchValue = digitalRead(switchPin); // check to see if the switch is pressed
      if (switchValue == LOW) { // if the switch is pressed then,
          digitalWrite(ledPin, HIGH); // turn the LED on
          
          
playTune();

      }  
      else { // otherwise,
          digitalWrite(ledPin, LOW); // turn the LED off
      }  
}


-

No comments:

Post a Comment