Rubber Band Launcher Mark I

 

Here's a fun project that we put together using stuff that we could find in our office. It's the Rubber Band Launcher Mark I! (Yes, we're calling it Mark I because we intend to further improve this model!)

It's made using pieces of plywood, a cardboard box, cable ties, and screws!

What's cool about it is that you can use your smartphone to control the launcher from a distance!

It's very easy to make! If you have two servos lying around, you can construct this too!

Here's a video of the Rubber Band Launcher in action!

The Setup

C360 2013-11-02-20-02-19-376.jpg


Here's what you'll need to make your own Arduino x Andee Launcher (feel free to improvise!):

  • 1x Arduino
  • 1x Annikken Andee
  • 1x Plywood Board (or some other hard material that won't bend easily by the rubber band's tension)
  • 1x Cardboard Box (or anything else to raise your launcher)
  • 2x Servo
  • 2x Cable ties
  • 5x Screws
  • 3x Nuts
  • Lots of rubber bands!


The Launching Board

I've cut the plywood board to about 40cm x 8cm. On one end of the board, I inserted a screw in the middle. That's to hold one end of the rubber band. On the other end of the board, I fastened a small servo using a cable tie.

Be sure to properly align the servo arm and the screw! Here's what I mean:

C360 2013-11-02-20-04-53-445.jpg


This will ensure that your rubber band will fire in the intended direction.


The Firing Mechanism

I should say a little about the firing mechanism. We're using a half-arm for the small servo. When the servo arm is up (about 100 degrees), it'll hold the rubber band in place.

C360 2013-11-02-20-05-32-466.jpg

From (painful) experience, setting the servo arm perpendicular to the board isn't a good idea when you need to reload. The rubber band tends to misfire. 100 degrees will do a better job.


Vertical Motion

For better stability, I've mounted the second servo horizontally down to another board, and attached a small board (using screws) to the servo arm. Next, I mounted the launching board to the top of the small board using two more screws to hold it in place. Here's how it looks:

C360 2013-11-02-20-05-47-521.jpg


Wiring It Up!

Wiring up the servos is very easy! The red wires of the servos go to +5V, while the black wires of the servos go to GND. As for the white and yellow wires, you just have to hook them up to one of the Arduino pins.

C360 2013-11-02-20-02-49-777.jpg


For this project, the firing servo is connected to Pin 2, while the vertical turning servo is connected to Pin 3.

Lastly, the Arduino is connected to the Annikken Andee so that we can use our smartphone to control it.

The Code

As we're using the Annikken Andee, the smartphone user interface is programmed in the Arduino source code itself.

The interface objects are declared at the top of the code, while their individual on-screen appearance is defined in the function setInitialData(). Button actions are coded in the loop() function below.

Here's a screenshot of the user interface:

Screenshot 2013-11-05-10-40-01.png


// Insert necessary libraries
#include <SPI.h>
#include <Andee.h>
#include <Servo.h>

#define TURN 5 // Each turn is set at 5 degrees

AndeeHelper btnFire;
AndeeHelper btnUp;
AndeeHelper btnDown;
AndeeHelper btnCustomFire; 
AndeeHelper displayStatus; // Display current angle
Servo servoVERT; // Servo for moving launcher up/down
Servo servoFire; // Servo for firing rubber band
int posVERT = 0;
int pos;
char input[3];
int pinFIRE = 2; // Firing servo connected to pin 2
int pinservoVERT = 3; // Up/down servo connected to pin 3


void setup()
{
  Andee.begin();
  Andee.clear();
  setInitialData();
  servoFire.attach(pinFIRE);
  servoVERT.attach(pinservoVERT);
  
  // Initialise launcher to 45 degrees
  for(posVERT = 90; posVERT > 45; posVERT--) 
  {                                  
    servoVERT.write(posVERT);
    delay(50);
  }
  
  // Initialise firing servo to reload position
  for(pos = 0; pos < 180; pos++) 
  {                              
    servoFire.write(pos);
    delay(20);
  }
}

void setInitialData()
{
  displayStatus.setId(0);
  displayStatus.setType(DATA_OUT);
  displayStatus.setTitle("Rubber Band Launcher Mark I");
  displayStatus.setLocation(0,0,FULL);    
  displayStatus.setUnit("degrees");

  btnUp.setId(1);
  btnUp.setType(BUTTON_IN);
  btnUp.setTitle("UP");
  btnUp.setLocation(1,0,FULL); 
 
  btnDown.setId(2);
  btnDown.setType(BUTTON_IN);
  btnDown.setTitle("DOWN");
  btnDown.setLocation(2,0,FULL);
  
  btnFire.setId(3);
  btnFire.setType(BUTTON_IN);
  btnFire.setTitle("FIRE");
  btnFire.setLocation(3,0,HALF);
  btnFire.setColor(RED);
  
  btnCustomFire.setId(4);
  btnCustomFire.setType(KEYBOARD_IN);
  btnCustomFire.setKeyboardType(ANDROID_NUMERIC);
  btnCustomFire.setTitle("Move to Angle and Fire (0-90 deg)");
  btnCustomFire.setLocation(3,0,HALF);  
  btnCustomFire.setColor(MAGENTA);
}

void turnUp() // Turns launcher up by 5 degrees
{
  int newPos = posVERT + TURN; // Set new position
  if(newPos > 90) newPos = 90; // Adjustment if beyond 90 degree limit
  for(posVERT; posVERT < newPos; posVERT++) // Move servo to new position
  {
    servoVERT.write(posVERT);
    delay(50);
  } 
}

void turnDown() // Turns launcher down by 5 degrees
{
  int newPos = posVERT - TURN; // Sets new position
  if(newPos < 0) newPos = 0; // Adjust if beyond 0 degree limit
  for(posVERT; posVERT > newPos; posVERT--)  // Move servo to new position
  {
    servoVERT.write(posVERT);
    delay(50); 
  } 
}

void fire() // Just fires rubber band
{
  // Brings down servo arm to release rubber band
  for(pos = 180; pos > 0; pos--)
  {  
    servoFire.write(pos);
    delay(10);
  }
  
  // Raises servo arm again so you can reload the next rubber band
  for(pos = 0; pos < 180; pos++) 
  { 
    servoFire.write(pos);
    delay(10);
  }     
}

void fire(int angle) // Moves to a user-specified angle before firing
{
   // If specified angle is higher than current angle, move servo up
  if(angle > posVERT)
  {
    for(posVERT; posVERT < angle; posVERT++)
    {
      servoVERT.write(posVERT);
      delay(50);
    }   
  }
  else // Otherwise, move servo down
  {
    for(posVERT; posVERT > angle; posVERT--)  
    {                                 
      servoVERT.write(posVERT);             
      delay(50);      
    }       
  }
  
  // Brings down servo arm to release rubber band 
  for(pos = 180; pos > 0; pos--)
  {
    servoFire.write(pos);
    delay(10);
  }  
  
  // Raises servo arm again so you can reload the next rubber band
  for(pos = 0; pos < 180; pos++)
  {
    servoFire.write(pos);
    delay(10);
  }     
}

void loop()
{
  // Draw these objects on screen once connected.
  if(Andee.isConnected())
  {
    btnFire.update();
    btnCustomFire.update();
    btnUp.update();
    btnDown.update();
    // As these buttons (above) don't change,
    // there's no need to refresh them
    
    displayStatus.update(); 
  }
  
  // When fire button is pressed
  if(btnFire.isPressed())
  {
    btnFire.ack();
    fire();
  }
  
  // When the other fire button is pressed
  if(btnCustomFire.isPressed())
  {
    btnCustomFire.getKeyboardMessage(input); // Get user input
    btnCustomFire.ack();
    fire(atoi(input)); // Convert user input string to integer
  }
  
  // When up button is pressed
  if(btnUp.isPressed())
  {
    btnUp.ack();
    turnUp();
  }
  
  // When down button is pressed
  if(btnDown.isPressed())
  {
    btnDown.ack();
    turnDown();
  }
  
  // Display new angle on screen
  displayStatus.setData(posVERT);
  displayStatus.update();
  delay(500);
}
comments powered by Disqus