Authors: Halanna Yuh, Spencer Bowman

12/6/2019

Abstract

Our project was a 2-player competitive boxing game where each user controls the 2 arms of a wooden “boxer” and attempts to strike their opponent’s “boxer” in the center with the arms. Users control the arms by pressing 2 buttons that correspond to each of the arms. A sound is played when a user successfully strikes their opponent.

Objectives

  • Create a 2 player competitive game where each player manipulates the two arms of a wooden boxer by pressing the corresponding buttons with the intent of striking their opponent’s boxer with the arm
  • Each press of the button should correspond to only one strike of the arm to encourage continuous user engagement. That is, they cannot “cheat” the game by just leaving their finger on the buttons and letting their boxer strike continuously.
  • The device should have strong feedback to the user when they achieve the goal of landing a strike. This is achieved by having a sound play when a user lands a successful strike.
  • Encourage strategic coordination from users in executing and blocking strikes.

Implementation

Square force sensors were used to detect a successful strike. These sensors were chosen for this purpose because they were sensitive enough to detect the slightest touch and had enough surface area for the arm to land on when it is struck. Once the output of the force sensors decrease below a certain threshold, this indicates that the sensor is being touched, and a speaker is used to play a sound.

For the arms, we used a servo to winch in a string which was attached to both members. The members were spring loaded to naturally rest in the extended position. As the servo unwound, the slack in the string would allow the arm to return to its extended position, causing the arm to “punch”. We looked into different methods of decoupling the string from the servo so that the punch was more violent, though none of our designs were able to produce the necessary rope travel in the limited space. The punching system also allowed the arms to be stopped, or hit other punching arms without any damage to the arms or the servo. All that would happen is that the string would go into slack, and the servo will still be allowed to freely go to its desired location. The arms were put at an angle inward, so that a punch could be blocked by another punch if the used timed it right. However, if the opposing arm was not extended, your punch would land cleanly without interference. To add to the distance that we pulled in the string, we added standoffs around the outer holes of the star shaped servo horn to build a drum. We originally struggled with using glued plastic spacers as they would fall off during use. We switched to lathed down metal standoffs as we could physically attach them to the horn with a bolt through the holes in the servo horn.

Outcomes

Successes

  • Children were mostly engaged because of the game’s competitive nature. 
  • Required some coordination on the children’s behalf to block their opponent’s strike. This prompted them to become really focused on the game when engaging with it.
  • The playing of the sound gave the user a notion of success and enhanced experience.

Failures

  • Technical errors during the demo mostly involved the string snapping.
  • Sometimes the arms would become misaligned rendering the user unable to strike their opponent at all.
  • Speed of the strikes were slow due to limitations of the servo motors used.

Future Work

For future implementations, we hope to revise the fundamental experience by adding more degrees of freedom for the user to move their boxer. What could be particularly useful is providing the user with the option to move their boxer linearly along a horizontal axis so they can avoid a strike or arrange their boxer in a better position to land a strike. We could also modify the way the user executes a strike to make the experience more interesting. Instead of having the arm extend and retract with one press of the button, the user can press down onto the button to have the arm slowly retract, and then release the button to have the arm extend and strike.

Contribution

Spencer: Designed the boxer and punching mechanism. Designed and built the moving punching bag that was used for the first demo. Helped with the wiring and the code.

Halanna – Designed the button box. Assembled the wires (cutting, crimping, soldering wires to components, fitting the wires into housings). Worked on code and electronic schematic. Helped with assembly of the boxers. For the first iteration, I also worked on a linear motion system for the punching bag, although this was never incorporated in any final demos. For more information on our first iteration, refer to our Intermediate Progress Report here .

Linear motion system for the punching bag component for 1st iteration.

Video

Children interacting with the device.
A closer look at the arms.

Photo Documentation

First iteration with a “punching bag” linearly and the user attempting to strike the bag.
Final iteration at museum.

Code

#include <Servo.h&gt;
Servo arm1; 
Servo arm2;
Servo arm3;
Servo arm4;

const int SERVO_ARM1 = 8;
const int SERVO_ARM2 = 7;
const int SERVO_ARM3 = 4;
const int SERVO_ARM4 = 2;

const int SWITCH_ARM1=A2;
const int SWITCH_ARM2=A3;
const int SWITCH_ARM3=A4;
const int SWITCH_ARM4=A5;

const int FORCE_SENSOR1 = A0;
const int FORCE_SENSOR2 = A1;

const int speakerPin = 11;
bool arm1_strike = false;
bool arm2_strike= false; 

int arm1State = 0; //0 is retracted, 1 is extending, 2 is retracting
int arm2State = 0; 
int arm3State = 0; //0 is retracted, 1 is extending, 2 is retracting
int arm4State = 0; 

unsigned long int arm1Timer = 0;
unsigned long int arm2Timer = 0;
unsigned long int arm3Timer = 0;
unsigned long int arm4Timer = 0;

unsigned long int toneTimer = 0;
int toneState = 0; //0 is not playing tone, 1 is playing tone
int bagState = 0;
unsigned long int bagTimer = 0;
void setup() {
  // put your setup code here, to run once:
  arm1.attach( SERVO_ARM1);
  arm2.attach(SERVO_ARM2);
  arm3.attach( SERVO_ARM3);
  arm4.attach(SERVO_ARM4);
  //bag.attach(8);
  //bag.write(0);
  arm1.write(0);
  arm2.write(180);
  arm3.write(0);
  arm4.write(180);
  Serial.begin(9600);

}


void loop() 
{
 
  
  if(digitalRead(SWITCH_ARM1) == 0 and arm1State == 0){ //arm is retractred and button is pressed 
    arm1State = 1;
    arm1Timer = millis();
    arm1.write(180);
  }
  if (arm1State == 1 and millis() - arm1Timer &gt; 1000){
    arm1State = 2;
    arm1Timer = millis();
    arm1.write(0);
  }
  if (arm1State == 2 and millis() - arm1Timer &gt; 1000){
    arm1State = 0;
  }

  
  if(digitalRead(SWITCH_ARM2) == 0 and arm2State == 0){ //arm is retractred and button is pressed 
    arm2State = 1;
    arm2Timer = millis();
    arm2.write(0);
  }
  if (arm2State == 1 and millis() - arm2Timer &gt; 1000){
    arm2State = 2;
    arm2Timer = millis();
    arm2.write(180);
  }
  if (arm2State == 2 and millis() - arm2Timer &gt; 1000){
    arm2State = 0;
  }

  if(digitalRead(SWITCH_ARM3) == 0 and arm3State == 0){ //arm is retractred and button is pressed 
    arm3State = 1;
    arm3Timer = millis();
    arm3.write(180);
  }
  if (arm3State == 1 and millis() - arm3Timer &gt; 1000){
    arm3State = 2;
    arm3Timer = millis();
    arm3.write(0);
  }
  if (arm3State == 2 and millis() - arm3Timer &gt; 1000){
    arm3State = 0;
  }

  if(digitalRead(SWITCH_ARM4) == 0 and arm4State == 0){ //arm is retractred and button is pressed 
    arm4State = 1;
    arm4Timer = millis();
    arm4.write(0);
  }
  if (arm4State == 1 and millis() - arm4Timer &gt; 1000){
    arm4State = 2;
    arm4Timer = millis();
    arm4.write(180);
  }
  if (arm4State == 2 and millis() - arm4Timer &gt; 1000){
    arm4State = 0;
  }

  if(analogRead(FORCE_SENSOR1)< 800 and toneState == 0)
  {
    tone(speakerPin, 440);
    toneTimer = millis();
    toneState = 1;
  }
  if (toneState == 1 &amp;&amp; millis() - toneTimer &gt; 500){
    noTone(speakerPin);
    toneState = 2;
  }
  if (toneState ==2  &amp;&amp; analogRead(FORCE_SENSOR1) &gt; 1000){
    toneState = 0;
  }  

  if(analogRead(FORCE_SENSOR2)< 800 and toneState == 0)
  {
    Serial.println("tone started");
    tone(speakerPin, 440);
    toneTimer = millis();
    toneState = 1;
  }
  if (toneState == 1 &amp;&amp; millis() - toneTimer &gt; 500){
    Serial.println("tone over");
    noTone(speakerPin);
    toneState = 2;
  }
  if (toneState ==2  &amp;&amp; analogRead(FORCE_SENSOR2) &gt; 1000){
    toneState = 0;
  }  
  
 
  
}

CAD Files

https://drive.google.com/file/d/1yoQK0GaDquHBUVBWBBmlwIlKNzZ9M8Lc/view?usp=sharing

Electronic Schematic