Compy: A peek inside

Finally, Compy is up and working! Here are some photos of his guts, and his code is below!

Compy’s front
Img_5691
I added googly eyes and a pipe cleaner bow-tie to give him a little craft charm.

Compy’s Back
Img_5692
His battery pack is attached on the back.

Compy with his Battery Pack removed
Img_5694
The battery pack is attached with velcro. The chip clip which holds Compy onto a laptop is hot glued.

Compy’s Guts
Img_5697
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);
    }

  }