Introduction: Robot Bottle Opener

This whole project started with a dead robot that we wanted to bring back to life. If I've learned anything from Bender, its that there is no better way to rejuvenate a robot than to have it open some beer bottles.

The task of controlling a robot to have it interact with specifically shaped objects and operate heavy loads is challenging and required significant prototyping and modelling. After many tests and many failures, we were very excited to watch our robot successfully maneuver through arm movements to open a beer bottle. And now we can relax as our robot cracks open a few beers for our hard work!

Step 1: Equipment & Materials

The robotic equipment we found was made by Rhino Robotics. The code we use to control it is general enough to work for any type of robotics using dc motors.

Electronics:

  • 3 DC motors (see picture for size, we don't have specs for the motors)
  • Arduino Duemilanove (or any Arduino board)
  • Arduino relay shield
  • 1 SPST relay (12V, 1A)
  • 1 2N3904 NPN transistor (or similar)
  • 1 LED (any color)
  • 3 limit switches
  • 4 10k ohm resistors
  • 1 330 ohm resistor
  • 12V power supply with DC barrel jack
  • Wires!

Hardware:

  • Zip ties
  • Nuts, bolts, and washers (1/4")
  • short screws for mounting
  • MDF board to mount on
  • 8 Tin soup cans
  • Various scraps of metal and rods for mounting

Tools:

  • Soldering Iron
  • Drill / dremel
  • Voltmeter for testing
  • Wire strippers / cutters
  • Wrenches
  • Hex keys

Step 2: Hardware

There were four primary tasks to prepare the hardware for the robot:

  1. Weight reduction of the robot arm to allow maximum torque / force from the arm.
  2. Bottle holders for the beers. We emptied out tin soup cans to hold the bottles in. The cans were then bolted down to the rotary plate of our robot setup.
  3. Mount the bottle opener and limit switches to the robot.
  4. Mount the robot parts to a sheet of MDF to maintain alignment.


Weight Reduction

To reduce the weight of the arm, we simply took off the last two motors of the robot arm to make the carriage head lighter. This left us with an arm that was much easier to control reliably and to get the torque we needed to open the bottle caps.

Bottle Holders

We emptied 8 tin cans of their contents and drilled to holes in the bottom 5cm apart (the spacing on our base plate). We put a washer between the bolt heads and tin can bottom to help with wiggle. We placed nuts on the bottom and tightened, although if we did this again we would have used lock nuts/washers to help with the nuts loosening in between runs.

Mounting the Opener & Switches

The opener was zip tied over some rods to the front of the arm's head. It was placed and tethered in a secure fashion with no particular mounting guidance except that it pointed up :)

The limit switches also had some variability in where they were mounted. The code uses the switches to find a reliable position after opening the caps (which causes the motors to slip sometimes and lose position memory) and then proceeds to move the motors in whatever direction it needs. So the limit switches were placed at a position that would allow the robot to pull the arm back first and then move back into the starting position while avoiding hitting the bottle again. For the limit switches on the rotary mount, the bolts used to secure the tin cans were used to trigger the switch so that they would hit the switch during rotation every 22.5 degrees. Since every can is spaced 45 degrees apart, every 2 clicks of the switch meant the next bottle was in alignment.

Mounting the Robot

We used a 2' x 4' piece of MDF to mount the robot arm and rotating base plate to. We used a combination of 1/4" bolts and screws to mount both parts.

Step 3: Electronics

The circuitry is all controlled by 9 pins on an arduino. There are 3 digital input pins and 6 digital output pins used. The pin usage is detailed below:

  • Arduino pin 0 - OUTPUT - Controls the rotary platform
  • Arduino pin 1 - INPUT - Limit switch for the head tilting
  • Arduino pin 2 - INPUT - Limit switch for the arm
  • Arduino pin 3 - INPUT - Limit switch for the rotary platform
  • Arduino pin 4 - OUTPUT - Tilts head down
  • Arduino pin 5 - OUTPUT - Tilts head up
  • Arduino pin 6 - OUTPUT - Moves arm down
  • Arduino pin 7 - OUTPUT - Moves arm up
  • Arduino pin 8 - OUTPUT - Controls a LED indicator

Pins 4 - 7 control the relay shield to operate the arm and head side of the robot. All of their electronics are built-in to the relay shield. The common pin of relay 1 on the relay shield is connected to the positive wire of the arm motor. The common pin of relay 2 is connected to the negative wire of the arm motor. The normally closed (NC) contact is connected to ground and the normally open (NO) contact of each relay is connected to 12V. The 12V power supply must be provided by a secondary power source via wires or by powering the Arduino from 12V and taking the 12V before it is regulated on the Arduino. The way the motor is hooked up means that the motor can turn on in either direction depending on which relay sources 12V and which one sinks to ground. If both relays are turned off or both are turned on, then the motor will not move. Note: having both relays on may be unreliable since there can still be a small change between the 12V line through one relay and the 12V line on the other relay, causing undesirable current flow through the switched on relays.

The rotating wheel operated in a similar way except only has one relay to be either on or off, so the motor only runs in one direction. As shown in the figure below, the relay can switch on or off the 12V line going to the motor.

The LED indicator for the setup I have tells me when it is ok to plug in the 12V power line. I left it unconnected when the arduino turns on and runs through its setup cycle because some of the motors were turning on randomly during setup. So the LED indicator gives me a 4 second pause in the code where the light turns on to let me know it is time to plug in the 12V power supply. After this the LED doesn't serve any purpose.

The limit switches all follow the same circuit to connect to the arduino. The robot uses digital read to tell when the switches are triggered and uses that information to finish aligning each motor.

Step 4: Software

The following code is made for the arduino IDE to control the robotic arm. Just as a note, It takes advantage of our circuitry and shouldn't be used on a working Rhino Robotics arm because the ribbon cable connections would be different!

The code starts with setting up all the input / output pins and sets them all LOW. It then turns on the LED briefly to let us know we can plug in the 12V power source. Then we get to the loop() where each cycle starts by calibrating the arm and head. After calibration, the head is left in position to remove the bottle cap. The motors then follow our pre-defined set of motions to lift up and tilt forward the bottle opener. Then the calibration repeats and the stage rotates for the next bottle and everything starts again!

In the code below, motor 1A means the relay controlling one side of the motors pins and 1B would be the other side of the motors pins. For example, you would need 1A HIGH and 1B LOW to drive the motor in one direction, or 1A LOW and 1B HIGH to drive the motor in the other direction, or both LOW to turn the motor off.

/*
  motor 1A (relay 1) on digital pin 7  
  motor 1B (relay 2) on digital pin 6
  motor 2A (relay 3) on digital pin 5
  motor 2B (relay 4) on digital pin 4
*/

void setup() 
{                
  pinMode(8, OUTPUT);  // LED
  pinMode(7, OUTPUT);  // arm up
  pinMode(6, OUTPUT);  // arm down
  pinMode(5, OUTPUT);  // head up
  pinMode(4, OUTPUT);  // head down
  pinMode(3, INPUT);   // wheel switch
  pinMode(2, INPUT);   // arm switch
  pinMode(1, INPUT);   // head switch
  pinMode(0, OUTPUT);  // wheel
  
  digitalWrite(7,LOW);
  digitalWrite(6,LOW);
  digitalWrite(5,LOW);
  digitalWrite(4,LOW);
  digitalWrite(0,LOW);
  
  digitalWrite(8,HIGH);        // turn on LED to indicate ready
  delay(2000);
  digitalWrite(8,LOW);
  delay(2000);                 // insert 12V source during this pause
}

void loop() 
{  
  calibrate();
  digitalWrite(4,HIGH); // tilt head down
  delay(500);
  digitalWrite(7,HIGH); // lift arm up
  delay(2000);
  digitalWrite(7,LOW);  
  delay(3000);
  digitalWrite(4,LOW);
  delay(10);
  digitalWrite(4,HIGH);
  digitalWrite(7,HIGH); 
  delay(1000);
  digitalWrite(7,LOW);
  digitalWrite(4,LOW);
  delay(10);  
}

void calibrate()
{
  while(!digitalRead(3))       // rotate wheel 22.5 degrees so that bottle isnt in the way
  {
    digitalWrite(0,HIGH); 
    delay(10);
  }
  delay(100);
  digitalWrite(0,LOW);
  
  while(digitalRead(1))        // move head away from bottle
  {
    digitalWrite(5,HIGH); 
    delay(10);
  }
  digitalWrite(5,LOW);
  digitalWrite(4,HIGH);
  delay(2000);
  digitalWrite(4,LOW);
  delay(10);
  
  while(!digitalRead(2))        // calibrate arm
  {
    digitalWrite(6,HIGH); 
    delay(10);
  }
  delay(50);
  digitalWrite(6,LOW);
  
  while(digitalRead(1))        // calibrate head
  {
    digitalWrite(5,HIGH); 
    delay(10);
  }
  digitalWrite(5,LOW);
  digitalWrite(4,HIGH);
  delay(250);
  digitalWrite(4,LOW);
  delay(10);
  
  while(!digitalRead(3))       // rotate wheel 22.5 degrees into position for next bottle
  {
    digitalWrite(0,HIGH); 
    delay(10);
  }
  delay(100);
  digitalWrite(0,LOW); 
}

Step 5: Testing

Our tests were successful! We got 7 for 8 bottles to open in the first try!