/*Star Spangled Banner with LEDs
Created by Ryan Aebi June 2018
Code Structure
-Basic Loop to refernce other functions
-Push buttons do either Star Spangled Banner or Charge sounds with lights
Star Spangled Banner Notes
-Funtion has note assigned by integer for Frequncy(Hz), & duration(time in n)
-LED is choosen by myself semi-randomly when writing function
-Function is built to increase in pitch with each play (resets to normal pitch on startup/hardware reset)
-Pitch calculated is 1/12 of a whole or .06
 
Button Design/wiring
-3 LED sets of Red, Blue & Green on each channel including 2 of each in parallel.
-External reset button
-start button for song
-interrupt song for charge
*/
//**************************************************************Declared Integers
  const int ChargeButton=3; //(Nano D3) uno pin 2 should be an interupt pin
  const int StartButton=5; //(Nano D5) uno pin 4
  const int BuzzerPin=9; //(Nano D9) uno pin 9
  const int RedLED=6; //(Nano D6) uno pin 6
  const int WhiteLED=7; //(Nano D7) uno pin 7
  const int BlueLED=8; //(Nano D8) uno pin 8 
  
  int n=1000; //declaring the integer this value will change with each song
  int DurationOn=n; //declaing integer for later on will be used in stacatto calculations
  int DurationRest=n; //declaing integer for later on will be used in stacatto calculations
  
  //sum of x & y should be 1 I have more notes on this later on
  float x=.66; //declaring float for time on
  float y=.34; //declaring float for time off
  
  //rate at which lights randomly flash while waiting button input
  int Twinkle_Rate=250; //note that if increased drastically buttons may not respond 100% of the time
  //lower twinkle rate improves button press response
  
  //sets integers for button states
  int StartButtonState;
  int ChargeButtonState;
  
  //note middle C is 4C (B flats & E flats)
  int Note1=233; //3Bb   233Hz
  int Note2=294; //4D    294Hz
  int Note3=330; //4E    330Hz
  int Note4=349; //4F    349Hz
  int Note5=392; //4G    392Hz
  int Note6=440; //4A    440Hz
  int Note7=466; //4Bb   466Hz
  int Note8=523; //5C    523Hz
  int Note9=587; //5D    587Hz
  int Note10=622; //5Eb  622Hz
  int Note11=698; //5F   698Hz
 
//**************************************************************Charge Function/Song
void Charge(){
  n=600; //rate at which song progresses
  
  //Format: write pin(s) on, tone at specific frequency (this way its not subject to 
  //changes at end of National Anthem, more on this later on), delay for same time as tone to sync up music, 
  //write pin(s) off that were on and delay for a rest 
  digitalWrite(RedLED, HIGH);
  tone(BuzzerPin, 392, n/3);
  delay(n/3);
  digitalWrite(RedLED, LOW);
  delay(70);
  
  digitalWrite(WhiteLED, HIGH);
  tone(BuzzerPin, 523, n/3);
  delay(n/3);
  digitalWrite(WhiteLED, LOW);
  delay(70);
  
  digitalWrite(BlueLED, HIGH);
  tone(BuzzerPin, 659, n/3);
  delay(n/3);
  digitalWrite(BlueLED, LOW);
  delay(70);
  
  digitalWrite(RedLED, HIGH);
  digitalWrite(WhiteLED, HIGH);
  digitalWrite(BlueLED, HIGH);
  tone(BuzzerPin, 784, n*3/4);
  delay(n*3/4);
  digitalWrite(BlueLED, LOW);
  digitalWrite(RedLED, LOW);
  digitalWrite(WhiteLED, LOW);
  delay(70);
  
  digitalWrite(BlueLED, HIGH);
  tone(BuzzerPin, 659, n/4);
  delay(n/4);
  digitalWrite(BlueLED, LOW);
  delay(70);
  
  digitalWrite(RedLED, HIGH);
  digitalWrite(WhiteLED, HIGH);
  digitalWrite(BlueLED, HIGH);
  tone(BuzzerPin, 784, n*2);
  delay(n*2);
  digitalWrite(BlueLED, LOW);
  digitalWrite(RedLED, LOW);
  digitalWrite(WhiteLED, LOW);
  delay(70);
}
//**************************************************************SingleDW function
void SingleDWwithNote(int HZ, int TurnOn, int Duration, int Staccato){ 
  //Hertz at which note is (references Note#)
  //turn on= pin (red/white/blue LED) that will be tuned on
  //duration is for how long
  //Staccato 1=yes, 0=no results in slightly shortened note, or a high int x value as just a brief pause
 
 
 
  if (Staccato==1){DurationOn=Duration*x;} //how long tone & lights are on is DurationShort
  else if (Staccato==0){DurationOn=Duration;}
  
    digitalWrite(TurnOn, HIGH);
    
    tone(BuzzerPin, HZ, DurationOn);
    delay(DurationOn);
    
    digitalWrite(TurnOn, LOW);
 
  if (Staccato==1) {
    DurationRest=Duration*y; 
    delay(DurationRest);
    }
}
//**************************************************************USA National Anthem Function/Song
void USNationalAnthem(){
  n=577; //rate at which sound plays calulated from: 60,000 (ms/BPM factor) / 104 BPM = 577 ms
  /*
    quarter note value is n
    half note value in n*2
    eighth notes it n/2
    dotted eights note is n*3/4
  */
  
  //x & y integers are for staccato/adding rest after a note
  //note that x+y must =1 or the int. n rate will be thrown off
  //decrease x and increase y though to make the notes more pronouced and jumpy/upbeat
  x=.92; //true stacatio is about 1/2 or 2/3 value so x value around .5 to .7 for a true staccato
  y=.08; //1.00-.92(x value) =.08
  
  //bars 1-5, lines 1
  SingleDWwithNote(Note4, RedLED, n*3/4, 1);
  SingleDWwithNote(Note2, WhiteLED, n/4, 1);
  SingleDWwithNote(Note1, RedLED, n, 1);
  SingleDWwithNote(Note2, WhiteLED, n, 1);
  SingleDWwithNote(Note4, RedLED, n, 1);
  SingleDWwithNote(Note7, WhiteLED, n*2, 1);
  SingleDWwithNote(Note9, BlueLED, n*3/4, 1);
  SingleDWwithNote(Note8, WhiteLED, n/4, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note2, WhiteLED, n, 1);
  SingleDWwithNote(Note3, BlueLED, n, 1);
  SingleDWwithNote(Note4, RedLED, n*2, 1);
  SingleDWwithNote(Note4, RedLED, n/2, 1);
  SingleDWwithNote(Note4, RedLED, n/2, 1);
 
  //bar6-9 line 2
  SingleDWwithNote(Note9, BlueLED, n*3/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n/2, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note6, BlueLED, n*2, 1);
  SingleDWwithNote(Note5, WhiteLED, n/2, 1);
  SingleDWwithNote(Note6, BlueLED, n/2, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note4, BlueLED, n, 1);
  SingleDWwithNote(Note2, WhiteLED, n, 1);
  SingleDWwithNote(Note1, BlueLED, n, 1);
  SingleDWwithNote(Note4, RedLED, n*3/4, 1);
  SingleDWwithNote(Note2, WhiteLED, n/4, 1);
  
  //bars 10-13 line 3
  SingleDWwithNote(Note1, RedLED, n, 1);
  SingleDWwithNote(Note2, WhiteLED, n, 1);
  SingleDWwithNote(Note4, RedLED, n, 1);
  SingleDWwithNote(Note7, WhiteLED, n*2, 1);
  SingleDWwithNote(Note9, BlueLED, n*3/4, 1);
  SingleDWwithNote(Note8, WhiteLED, n/4, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note2, WhiteLED, n, 1);
  SingleDWwithNote(Note3, BlueLED, n, 1);
  SingleDWwithNote(Note4, RedLED, n*2, 1);
  SingleDWwithNote(Note4, RedLED, n/2, 1);
  SingleDWwithNote(Note4, RedLED, n/2, 1);
   
  //bar 14-17, line 4, end of page 1 
  SingleDWwithNote(Note9, BlueLED, n*3/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n/2, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note6, BlueLED, n*2, 1);
  SingleDWwithNote(Note5, WhiteLED, n/2, 1);
  SingleDWwithNote(Note6, BlueLED, n/2, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note4, BlueLED, n, 1);
  SingleDWwithNote(Note2, WhiteLED, n, 1);
  SingleDWwithNote(Note1, RedLED, n, 1);
  SingleDWwithNote(Note9, BlueLED, n/2, 1);
  SingleDWwithNote(Note9, BlueLED, n/2, 1);
  //bars 18-21, line 5, start of page 2
  SingleDWwithNote(Note9, BlueLED, n, 1);
  SingleDWwithNote(Note10, RedLED, n, 1);
  SingleDWwithNote(Note11, WhiteLED, n, 1);
  SingleDWwithNote(Note11, WhiteLED, n*2, 1);
  SingleDWwithNote(Note10, RedLED, n/2, 1);
  SingleDWwithNote(Note9, BlueLED, n/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n, 1);
  SingleDWwithNote(Note9, BlueLED, n, 1);
  SingleDWwithNote(Note10, RedLED, n, 1);
  SingleDWwithNote(Note10, RedLED, n*2, 1);
  SingleDWwithNote(Note10, RedLED, n, 1);
  //bars 22-25, line 6
  SingleDWwithNote(Note9, WhiteLED, n*3/2, 1);
  SingleDWwithNote(Note8, BlueLED, n/2, 1);
  SingleDWwithNote(Note7, WhiteLED, n, 1);
  SingleDWwithNote(Note6, RedLED, n*2, 1);
  SingleDWwithNote(Note5, BlueLED, n/2, 1);
  SingleDWwithNote(Note6, RedLED, n/2, 1);
  SingleDWwithNote(Note7, WhiteLED, n, 1);
  SingleDWwithNote(Note2, BlueLED, n, 1);
  SingleDWwithNote(Note3, RedLED, n, 1);
  SingleDWwithNote(Note4, WhiteLED, n*2, 1);
  SingleDWwithNote(Note4, RedLED, n, 1);
  n=n*1.08; //60,000 / 96 bpm= 625 ms; just a slight retard
  
  //bars 26-28, line 7
  SingleDWwithNote(Note7, WhiteLED, n, 1);
  SingleDWwithNote(Note7, WhiteLED, n, 1);
  SingleDWwithNote(Note7, WhiteLED, n/2, 1);
  SingleDWwithNote(Note6, BlueLED, n/2, 1);
  SingleDWwithNote(Note5, RedLED, n, 1);
  SingleDWwithNote(Note5, RedLED, n, 1);
  SingleDWwithNote(Note5, RedLED, n, 1);
  SingleDWwithNote(Note8, WhiteLED, n, 1);
  SingleDWwithNote(Note10, RedLED, n/2, 1);
  SingleDWwithNote(Note9, BlueLED, n/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n/2, 1);
  SingleDWwithNote(Note7, RedLED, n/2, 1);
  
  //bars 29-30
  SingleDWwithNote(Note7, RedLED, n, 1);
  SingleDWwithNote(Note6, BlueLED, n*2, 1); //2x for holding
  SingleDWwithNote(Note4, RedLED, n/2, 1);
  SingleDWwithNote(Note4, RedLED, n/2, 1);
  SingleDWwithNote(Note7, BlueLED, n*3/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n/2, 1);
  SingleDWwithNote(Note9, BlueLED, n/2, 1);
  SingleDWwithNote(Note10, RedLED, n/2, 1);
  
  n=n*1.2; //large retard
  
  //bars 31-34 end of song
  SingleDWwithNote(Note11, WhiteLED, n*2, 1); //extra hold on free
  SingleDWwithNote(Note7, RedLED, n/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n/2, 1);
  SingleDWwithNote(Note9, BlueLED, n*3/2, 1);
  SingleDWwithNote(Note10, RedLED, n/2, 1);
  SingleDWwithNote(Note8, WhiteLED, n, 1);
  SingleDWwithNote(Note7, RedLED, n*3, 1); //only holding for 3 values
  
  //rasie all notes by 3 steps
  //1.06 derived from music theory. Take a note in hertz and then divide by the 
  //note below it (sharps and flats count as a note) all round to 1.06
  //You can delete this next paragraph to avoid frequency changes or change it up if you want
  Note1=Note1*1.06*1.06*1.06;
  Note2=Note2*1.06*1.06*1.06;
  Note3=Note3*1.06*1.06*1.06;
  Note4=Note4*1.06*1.06*1.06;
  Note5=Note5*1.06*1.06*1.06;
  Note6=Note6*1.06*1.06*1.06;
  Note7=Note7*1.06*1.06*1.06;
  Note8=Note8*1.06*1.06*1.06;
  Note9=Note9*1.06*1.06*1.06;
  Note10=Note10*1.06*1.06*1.06;
  Note11=Note11*1.06*1.06*1.06;
}
//**************************************************************Twinkle 
void Twinkle(int Twinkle_Time) //Place a number in () shows how long the twinkle occurs
{
  //built this function for another use so it has a bizarre starting unnesseary calculation 
  
  //changes time&rate into a smaller number integer, note it front end rounds
  Twinkle_Time=Twinkle_Time/Twinkle_Rate; // in this case Tiwkle Time is = to Twinkle Rate so value is 1
  for(Twinkle_Time;Twinkle_Time>0;Twinkle_Time--) //since value is 1 only processes once
  
  {
  int B= random(1,4); //random integer of 1, 2 or 3
  int C= random(1,4); //random integer of 1, 2 or 3
  //no issues if both integers are the same, just one LED comes on, adds to randomness
  //evaluates each integer to run on a specific color LED
  if(B==1){digitalWrite(RedLED, HIGH);}
  if(B==2){digitalWrite(WhiteLED, HIGH);}
  if(B==3){digitalWrite(BlueLED, HIGH);}
 
  if(C==1){digitalWrite(RedLED, HIGH);}
  if(C==2){digitalWrite(WhiteLED, HIGH);}
  if(C==3){digitalWrite(BlueLED, HIGH);}
 
  delay(Twinkle_Rate);// keeps LED on for a set period of time
  
  //and then we write corresponding LEDs low. cold possibly simlify and just write all 3 low may speed up timing
  if(B==1){digitalWrite(RedLED, LOW);}
  if(B==2){digitalWrite(WhiteLED, LOW);}
  if(B==3){digitalWrite(BlueLED, LOW);}
  
  if(C==1){digitalWrite(RedLED, LOW);}
  if(C==2){digitalWrite(WhiteLED, LOW);}
  if(C==3){digitalWrite(BlueLED, LOW);}
  }}
//**************************************************************Setup
void setup(){ 
  pinMode(ChargeButton, INPUT_PULLUP); //puts as input and enables internal pull up resistor for button
  pinMode(StartButton, INPUT_PULLUP); //puts as input and enables internal pull up resistor for button
  
  pinMode(RedLED, OUTPUT); //LED configured as output
  pinMode(WhiteLED, OUTPUT); //LED configured as output
  pinMode(BlueLED, OUTPUT); //LED configured as output
  
  pinMode(BuzzerPin, OUTPUT); //Buzzer configured as output
  
  //digitalWrite(ChargeButton, HIGH); not necessary since it is enabled as pullup, its just redundant
  //digitalWrite(StartButton, HIGH); not necessary since it is enabled as pullup, its just redundant
  
  //sets all LEDs to LOW to avoid any errors. For my deisgn HIGH=ON, LOW=OFF
  digitalWrite(RedLED, LOW);
  digitalWrite(WhiteLED, LOW);
  digitalWrite(BlueLED, LOW);
  
} 
//**************************************************************Main Loop
void loop(){
 
  //reads button states, pins were hooked to internal resistor configured as high
  //pins will be low when pressed
  StartButtonState = digitalRead(StartButton); //low=pressed
  ChargeButtonState = digitalRead(ChargeButton); //low=pressed
  
  //evalues against integers to do the 1st function pin that was resistered as low
  //sampling rate for reading buttons is the int twinkle_rate (.25 seconds)
  if (StartButtonState==LOW){USNationalAnthem();}
  else if (ChargeButtonState==LOW){Charge();}
  
  else{Twinkle(Twinkle_Rate);} // if no pins pressed then twinkle on! again... and again... and again...
  
}
Comments