Finally, Compy is up and working! Here are some photos of his guts, and his code is below!
Compy's frontI added googly eyes and a pipe cleaner bow-tie to give him a little craft charm.
Compy's Back
His battery pack is attached on the back.
Compy with his Battery Pack removed
The battery pack is attached with velcro. The chip clip which holds Compy onto a laptop is hot glued.
Compy's Guts
I used an Arduino Mini, and had to put that in a little acrylic box from the Container Store separate from another acrylic box containing the speaker and the IR sensor. Code is below!
/*
* ----------- Taken in part from Play Melody, also with help from Matt's averaging code, and trouble shooting from Rich. Thanks!
*/
// TONES ==========================================
// Start by defining the relationship between
// note, period, & frequency.
#define c 3830 // 261 Hz
#define d 3400 // 294 Hz
#define e 3038 // 329 Hz
#define f 2864 // 349 Hz
#define g 2550 // 392 Hz
#define a 2272 // 440 Hz
#define b 2028 // 493 Hz
#define C 1912 // 523 Hz
#define D 1700
#define E 1519
#define F 1432
#define G 1275
#define A 1136
#define B 1014
#define CC 956
#define DD 850
#define EE 759
#define FF 716
#define GG 637
#define AA 568
#define BB 507
#define CCC 478
#define DDD 425
#define DDDS 441
#define EEE 379
// Define a special note, 'R', to represent a rest
#define R 0
#define NUMREADINGS 50
// SETUP ============================================
int readings[NUMREADINGS]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
int closeValue = 0;
int speakerOut = 9; // Set up speaker on a PWM pin
int irSensor = 3;
int DEBUG = 1; // Do we want debugging on serial out? 1 for yes, 0 for no
int redLED = 8;
int otherLED = 13;
int SECONDS_TILL_BEEP = 150;
int numFrames = 0;
void setup() {
pinMode(speakerOut, OUTPUT);
pinMode(irSensor, INPUT);
if (DEBUG) {
Serial.begin(9600); // Set serial out if we want debugging
for (int i = 0; i < NUMREADINGS; i++)
readings[i] = 0; // initialize all the readings to 0
}
int frameRate = 10;
}
// MELODY and TIMING =======================================
// melody[] is an array of notes, accompanied by beats[],
// which sets each note's relative length (higher #, longer note)
int melody[]= {G, D, B, G, D, B, G, D, B, G };
int beats[] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 32};
int MAX_COUNT = sizeof(melody) / 2; // Melody length, for looping.
long tempo = 10000; // Set overall tempo
int pause = 1000; // Set length of pause between notes
int rest_count = 100; //// Loop variable to increase Rest length <-BLETCHEROUS HACK; See NOTES
// Initialize core variables
//int tone = 0;
//int beat = 0;
//long duration = 0;
// PLAY TONE ==============================================
// Pulse the speaker to play a tone for a particular duration
void playTone(int tone, long duration) {
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);
}
}
}
// LET THE WILD RUMPUS BEGIN =============================
void loop() {
//int milliSeconds = millis() % (SECONDS_TILL_BEEP * 1000);//milliseconds will count over after the desired time
analogWrite(redLED, 0);
analogWrite(otherLED, 255);
//averaging code taken from M Bethancourt's divine 3 LED IR code
total -= readings[index]; // subtract the last reading
readings[index] = analogRead(irSensor); // read from the sensor
total += readings[index]; // add the reading to the total
index = (index + 1); // advance to the next index
if (index >= NUMREADINGS) // if we're at the end of the array...
index = 0; // ...wrap around to the beginning
average = total / NUMREADINGS; // calculate the average
Serial.println(average); // send it to the computer (as ASCII digits)
closeValue = average;
// Set up a counter to pull from melody[] and beats[]
if(closeValue >100 && closeValue < 200){
analogWrite(otherLED, 0);
analogWrite(redLED, 255);
//we loop 10x per second
numFrames++;//this loop, they've been sitting here. this essentially counts 1/10th of a second
//numframes / 10 = how many seconds they've been there
if (numFrames / 10 > SECONDS_TILL_BEEP){
for (int i=0; i < MAX_COUNT ; i++) {
int tone = melody[i];
int beat = beats[i];
long duration = beat * tempo; // Set up timing
playTone(tone, duration);
// A pause between notes...
//delayMicroseconds(pause);
}
numFrames = 0;//we have beeped, start all over again.
}
}
else {
analogWrite(otherLED, 255);
analogWrite(redLED, 0);
}
if (DEBUG) {
Serial.print("IR: ");
Serial.println(analogRead(irSensor));
Serial.print("Milli: ");
//Serial.println(milliSeconds);
}
}
Comments
You can follow this conversation by subscribing to the comment feed for this post.