Lab 5 - Genie in a Bottle

Submitted by fchasen on Wed, 03/06/2013 - 11:40

Description

The Genie in the bottle begs you to let it out every few seconds. When you open the lid of the jar it celebrates its release and then plays a little melody. Putting the lid back on makes play a sad melody and resume begging to be let out again.

Based on the Melody example for K3, the code for the different states quickly got very complex and pausing the music, but still sensing light changes was also a challenge. I hope to clean it up (maybe splitting into classes) at somepoint.

Components Used

• Arduino Uno
• 10 ohm resistor
• Glass opaque jar
• Light sensor
• Piezo speaker

Code

/* Play Melody
* -----------
*
*
* (cleft) 2005 D. Cuartielles for K3
* Refactoring and comments 2006 clay.shirky@nyu.edu
* See NOTES in comments at end for possible improvements
*/

// TONES  ==========================================
// Start by defining the relationship between
//       note, period, &  frequency.
#define  cc     3830    // 261 Hz
#define  dd     3400    // 294 Hz
#define  ee     3038    // 329 Hz
#define  ff     2864    // 349 Hz
#define  gg     2550    // 392 Hz
#define  aa     2272    // 440 Hz
#define  bb     2028    // 493 Hz
#define  CC     1912    // 523 Hz
// Define a special note, 'R', to represent a rest
#define  RR     0

// SETUP ============================================
// Set up speaker on a PWM pin (digital 9, 10 or 11)
int speakerOut = 9;

int lightPin = 0;
int lightVal = 0;
int minLight = 170;

// States  =======================================

boolean closed = true;
boolean letout = false;
boolean shutin = false;
boolean firstRun = true;

int maxWait = 1500;
int wait = maxWait;

// MELODY and TIMING  =======================================

int state = 0;

int* melodies[4];
int* beats[4];

//-- Hello - Let me out!
int melodyA[] = { RR, gg, ee,  RR, bb, RR, bb, aa };
int beatsA[]  = { 1024, 32, 16, 1024, 32,  64, 8, 64 };

//-- Lid back on
int melodyB[] = {  aa, gg, aa, gg, aa, gg, aa, gg, ee };
int beatsB[]  = {  32, 16, 32, 16, 32, 16, 32, 16, 64 };

//-- Released
int melodyC[] = {  ee, ff, gg, aa, bb, CC  };
int beatsC[]  = {  8, 8, 8, 8, 16, 32 };

//-- Out
int melodyD[] = {  aa, bb, aa, bb, aa, bb, aa, bb, CC, bb, cc };
int beatsD[]  = {  32, 16, 32, 16, 32, 16, 32, 16, 64, 16, 32 };

int MAX_COUNT; // Melody length, for looping.

// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 100;
// Loop variable to increase Rest length
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES

int between = 64;

// Initialize core variables
int tone_ = 0;
int beat = 0;
long duration  = 0;

void setup() {
pinMode(speakerOut, OUTPUT);
Serial.begin(9600); // Set serial out if we want debugging

melodies[0] = melodyA;
melodies[1] = melodyB;
melodies[2] = melodyC;
melodies[3] = melodyD;

beats[0] = beatsA;
beats[1] = beatsB;
beats[2] = beatsC;
beats[3] = beatsD;

}

// PLAY TONE  ==============================================
// Pulse the speaker to play a tone for a particular duration
void playTone() {
long elapsed_time = 0;
if (tone_ > 0) { // if this isn't a Rest beat, while the tone has
//  played less long than 'duration', pulse speaker HIGH and LOW
while (elapsed_time < duration) {

digitalWrite(speakerOut, HIGH);
delayMicroseconds(tone_ / 2);

// DOWN
digitalWrite(speakerOut, LOW);
delayMicroseconds(tone_ / 2);

// Keep track of how long we pulsed
elapsed_time += (tone_);
}
}
else { // Rest beat; loop times delay
for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
delayMicroseconds(duration);
}
}
}

void checkLight() {

if(firstRun == true){
firstRun = false;
if(lightVal < minLight){
closed = true;
}else{
closed = false;
}

}

if(lightVal < minLight){
//Serial.println(closed);
if(closed == false){
shutin = true;
closed = true;
wait = 0;
Serial.println("Put In");
}
}else{
if(closed == true){
letout = true;
closed = false;
Serial.println("Let Out");
}
}

// 0. A closed
// 1. B shutin
// 2. C released
// 3. D free

if(letout){
state = 2;
MAX_COUNT = sizeof(melodyC) / 2;
pause = 64;
letout = false;
between = 64;
} else if(shutin){
state = 1;
MAX_COUNT = sizeof(melodyB) / 2;
pause = 32;
between = 64;
shutin = false;

} else if(closed){
state = 0;
MAX_COUNT = sizeof(melodyA) / 2;
pause = 64;
between = 4000;
} else {
state = 3;
MAX_COUNT = sizeof(melodyD) / 2;
pause = 64;
between = 64;
}
}

// LET THE WILD RUMPUS BEGIN =============================
void loop() {

Serial.println(lightVal);

checkLight();

//delay(between);

if(closed == false || wait > maxWait) {
wait = 0;
// Set up a counter to pull from melody[] and beats[]
for (int i=0; i< MAX_COUNT; i++) {
tone_ = melodies[state][i];
beat = beats[state][i];

duration = beat * tempo; // Set up timing

playTone();
// A pause between notes...
delay(pause);

}

}else{
wait++;

}

}
Drupal theme by Kiwi Themes.