Lab 5 - Playing darts with a laser

Assignment: Input / Output Coincidence Lab Assignment

Collaborators:

Throwing sharp-pointed darts is dangerous in a small apartment, so why not throw photons from a laser* instead. Plus with light, you'll never have to dig for lost darts again.

Take a laser pointer and aim it at the center of the bullseye ring. If the beam hits the center, one of the two photocells will detect a high luminescence reading and trigger Arduino to input a victory song. The victory song is taken from the Arduino code "Play Melody". Since a laser have a collimated beam (the beam of light doesn't grow bigger further away from the source), I have used two photocells to measure differences in luminescence across them. The assumption is that a laser beam from a pointer won't have a wider diameter than the surface of a photocell.

* It's slightly less dangerous...

 

Attached is a photo of the dart board with the two photocells peeking out from the center. Below is a short video of the photon dart triggering off the song:

 

 

Below is my code. The commented out portions are my attempt at making my code more versatile and adaptative to different ambient lighting. It didn't work well, producing many false positive readings of bullseyes. I set a definite threshold value of 600 instead.

 

/*
* Playing darts with light - aim a laser pointer at the bullseye
*   If you hit the bullseye, a song plays
*   Two adjacent photocells detect light
*   If their difference is great, then a song plays
*  Song code from Play Melody 2005 D. Cuartielles for K3
*/

int photo1 = 4;   // select the input pin for the photocell 1
int photo2 = 5;   // select the input pin for the photocell 2
int val1 = 0;     // variable to store the value coming from photocell 1
int val2 = 0;     // variable to store the value coming from photocell 2
int oldavgval1 = 0;  // track previous average luminescence reading on photocell 1
int oldavgval2 = 0;  // track previous average luminescence reading on photocell 2
int avgval1 = 0;  // track average luminescence reading on photocell 1
int avgval2 = 0;  // track average luminescence reading on photocell 2
float oldstdev1 = 10; // previous standard deviation in ambient luminescence
float oldstdev2 = 10; // previous standard deviation in ambient luminescence
float stdev1 = 10; // standard deviation in ambient luminescence
float stdev2 = 10; // standard deviation in ambient luminescence
int i;
boolean laseron1 = 0;   // track if the laser spot is in the bullseye, on photocell1
boolean laseron2 = 0;   // track if the laser spot is in the bullseye, on photocell2

int ledPin = 13;
int speakerOut = 7;  // pin to output sound from speaker
byte names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'}; 
int tones[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
byte melody[] = "2d2a1f2c2d2a2d2c2f2d2a2c2d2a1f2c2d2a2a2g2p8p8p8p";
int count = 0;
int count2 = 0;
int count3 = 0;
int MAX_COUNT = 24;
int statePin = LOW;

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(speakerOut, OUTPUT);  
Serial.begin(9600);
}

void loop() {

/* 
avgval1 = 0;
avgval2 = 0;
for (i=0; i < 8; i++)
{
avgval1 += analogRead(photo1);    // read the input of photocell 1
avgval2 += analogRead(photo2);    // read the input of photocell 2
}
avgval1 = avgval1/i;
avgval2 = avgval2/i;
*/
val1 = analogRead(photo1); // read the value from the photocell, 0-1023
val2 = analogRead(photo2); // read the value from the photocell, 0-1023

/*
oldavgval1 = avgval1;
oldavgval2 = avgval2;
avgval1 = avgval1*99.0/100.0 + (float)val1/100.0;
avgval2 = avgval2*99.0/100.0 + (float)val2/100.0;
oldstdev1 = stdev1;
oldstdev2 = stdev2;
stdev1 = sqrt ((stdev1*99.0/100.0)*(stdev1*99.0/100.0) + ((float)val1-avgval1)*((float)val1-avgval1)/100);
stdev2 = sqrt ((stdev2*99.0/100.0)*(stdev2*99.0/100.0) + ((float)val2-avgval2)*((float)val2-avgval2)/100); 

laseron1 = val1 > oldavgval1 + 2*oldstdev1;
laseron2 = val2 > oldavgval2 + 2*oldstdev2;
*/

laseron1 = val1 > 600;
laseron2 = val2 > 600;

Serial.print(val1);
Serial.print(" ");
Serial.print(val2);
Serial.print("\n");

if (laseron1 ^ laseron2)  // XOR
{
Serial.print("Play music!");

/*
// Don't update averages and stdevs with outlier values!
avgval1 = oldavgval1;
avgval2 = oldavgval2;
stdev1 = oldstdev1;
stdev2 = oldstdev2;
*/

// Play melody
digitalWrite(speakerOut, LOW);    
for (count = 0; count < MAX_COUNT; count++) {
statePin = !statePin;
digitalWrite(ledPin, statePin);
for (count3 = 0; count3 <= (melody[count*2] - 48) * 30; count3++) {
for (count2=0;count2<8;count2++) {
if (names[count2] == melody[count*2 + 1]) {      
digitalWrite(speakerOut,HIGH);
delayMicroseconds(tones[count2]);
digitalWrite(speakerOut, LOW);
delayMicroseconds(tones[count2]);
}
if (melody[count*2 + 1] == 'p') {
// make a pause of a certain size
digitalWrite(speakerOut, 0);
delayMicroseconds(500);
}
}
}
}

} // end of XOR loop

delay(100);                   // rest a little...
}