Lab 5 - Genie in a Bottle
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
- Breadboard
- 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){
Serial.println("ready");
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() {
lightVal = analogRead(lightPin); // read value from the sensor
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++;
}
}
- Login to post comments
Drupal theme by Kiwi Themes.