Our easy to play game is designed to help improve anyone’s ball in cup throwing skills. To start a game, a participant flips a switch which simultaneously starts a high pitched sound and a stopwatch. They then pick up a ball or another object and attempts to throw it in a cup. As soon as the shot is made, the game ends, the sound stops, an LED blinks three times, and the amount of time elapsed from the start of the game is displayed on a computer screen.

Detail view of sound emitter and sensor

Discussion

At the beginning of our project, we very quickly agreed that creating some sort of game which required human interaction to trigger our transducers would be interesting because it extended both the complexity and range over which we could design the product. Having further become very interested in incorporating IR, light, and sound into our project we set about merging our broader project interests with these components in what became the ball in cup game. The process was wrought with several challenging aspects, and yet other surprisingly simple features. Below we discuss highlights from each, broken down into two parts: hardware-wise, and code-wise.

In our initial brainstorming, integrating several components into two coupled transistors via circuits seemed like a daunting task: each transduction piece was unknown to us and required unique circuit logic to parse and reason over on the arduino. For instance, our sound detector consisted of five ports, including three for sound reading: ‘audio’, ‘envelop’, and ‘gate’. Each port captured a different element of a sound, while only a single one contained the information we needed. However, with help from online sources and material covered in lecture, we surprisingly found that wiring up each component was surprisingly straightforward.

Testing the IR Proximity Sensor
Testing the buzzer component
Testing the sound sensor with the buzzer

Furthermore, we realized that to integrate each component to form our transducers, it was sufficient to set them all in parallel with one another. This observation greatly simplified our final circuit architecture, and proved to be easier to debug than a more complicated circuit.

In conjunction with putting together our hardware project components, we faced several challenges with designing our code structure. Because our goal was to design a game based off of a double transducer, we had to not only tie in each transduction component together to form the transducers and dependencies, but also had to seamlessly integrate other game parts to work in concert with the transducers. One challenging aspect of this was incorporating game state design into our project. Our vision was to have three game states: start, active, and terminal, each which was responsible for different aspects of the game. The role of the start state was to initialize all required components for the game, the active state served to perform all actions required while the game is ongoing, and the terminal state was meant to perform game ending functions. In terms of our code, the start state should initialize the stopwatch, and flags which dictate whether the game was active. The active state in turn should play the sound infinitely and detect if the IR sensor had been tripped, turning off the sound if true (first transducer). Meanwhile, the terminal state should be triggered by the absence of sound which causes the LED blinking series (second transducer) and terminates the game. This required a complete restructuring of our code because up until this point, both transducers were captured in a single if statement which detected whether the IR sensor had been detected. Thus, meeting our vision required breaking apart the transducers into the active and terminal game states, as well adding a new start state as well.

One aspect of our project we might have changed if we had more time was the type of sound emanating from an active game. Instead of playing a single monotone sound continuously, we think it would be interesting to instead change the sound based on elapsed time. This change would provide a unique form of participant feedback as it would give an indication of how long the game has been going on for.

Detail View of Proximity Sensor in Cup
Detail view of electrical components

Video of Ball in Cup Game in action:

Schematic for ball in cup game

Code

 

/* Ball In Cup Game
 *  
 *  This code integrates several components (an IR sensor, speaker,
 *  sound detector, LED, switch, and display) into a double transducer
 *  ball in cup game. Specifically, the double transducer is created in
 *  our code according to the following; IR sensor --> sound (first 
 *  transducer), sound detector --> light (second transducer). The switch 
 *  and display are then used to start the game, and show a participant's 
 *  end game score respectively. 
 *  
 *  Inputs: an IR sensor, switch, and sound detector
 *  Outputs: a speaker, LED, and text display (via serial port)
 *  
 */


// Initialize and Assign Global Variables
const int BUZZER_PIN = 4;    // sound pin 
const int SWITCH_PIN = 3;    // switch pin
const int SOUND_PIN = A0;    // sound detector pin
const int LED_PIN = 5;       // LED pin
const int IR_PIN = A1;       // IR sensor pin
// initialize flags
bool DID_PRINT = false;      // Has current game time elapsed been printed
bool IS_END_GAME = false;    // Dictate game state
int OLD_SWITCH_STATE;        // initialize switch state variable
unsigned long time;          // initialize time variable

void setup(){
  // Set up arduino inputs & outputs
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(SWITCH_PIN, INPUT);
  pinMode(SOUND_PIN, INPUT);
  pinMode(IR_PIN, INPUT);
  // read initial state of switch
  OLD_SWITCH_STATE = digitalRead(SWITCH_PIN);
  // set serial port
  Serial.begin(9600);
}

void loop(){
  // initialize function variables
  int start_time;            // game start timestamp
  int end_time;              // game end timestamp
  int ir_threshold = 180;    // Used to detect when IR sensor is tripped
  int sound_threshold = 40;  // Used to detect absence of sound
  int current_switch_state = digitalRead(SWITCH_PIN);
  // switch state is different from past switch state
  // trigger game start
  if (current_switch_state != OLD_SWITCH_STATE) {
    // assign active game flags
    IS_END_GAME = false;
    DID_PRINT = false;
    // start sound
    tone(BUZZER_PIN, 1000);
    // begin stopwatch (record current timestamp)
    start_time = millis();
    }
  // game is active
  if (IS_END_GAME == false) {
    // ball has landed in cup
    if (analogRead(IR_PIN) > ir_threshold) {
      // terminate game
      IS_END_GAME = true;
      // IR sensor --> sound transducer
      noTone(BUZZER_PIN);
    }
  
  }
  else { // game has ended
    // Time taken to complete game has not been printed on screen
    if (DID_PRINT == false) {
      // stop stopwatch (record game end timestamp)
      end_time = millis();
      // print time elapsed in seconds
      Serial.print("Congratulations! It took you: ");
      int time_elapsed = (end_time - start_time) / 1000;
      Serial.print(time_elapsed);
      Serial.println(" seconds.");
      }
    // sound sensor --> sound detector. LEDs have not blinked yet
    // DID_PRINT ensures LED's are only blinked once
    if ((analogRead(SOUND_PIN) < sound_threshold) && (DID_PRINT == false)) {
      // sound detection --> light transducer
      // begin light show
      digitalWrite(LED_PIN, HIGH);
      delay(500);
      digitalWrite(LED_PIN, LOW);
      delay(200);
      digitalWrite(LED_PIN, HIGH);
      delay(500);
      digitalWrite(LED_PIN, LOW);
      delay(200);
      digitalWrite(LED_PIN, HIGH);
      delay(500);
      digitalWrite(LED_PIN, LOW);
      // LED flash and text print has been performed
      // Set to so that it does not happen again (only once)
      DID_PRINT = true;
      }  
    }
  // update switch state for next step
  OLD_SWITCH_STATE = current_switch_state;
}