Roborodentia 2011

From rev0wiki
Jump to: navigation, search

Team Members: Dennis Cagle, Justin Kenny, Zach Negrey

Introduction

Roborodentia is a robotics competition held annually at Cal Poly SLO. The 2011 Roborodentia competition resembled a game of soccer. There were two sides to a playing field with a net on each end and troughs on the sides to hold ping-pong balls (Figure 1). The goal of the contest is to create an autonomous robot capable of scoring the most ping-pong balls into an opponent’s net.

Roborodentia Field

Strategy

Our overall plan was to stay simple. Past experience has taught us that a really well working simple design is better then a not working complex one. We decided to make a basic robot that would go around in a square collecting balls and shooting as it went. In retrospect from past competitions, we decided to go with a mechanical switch-based location system, as opposed to an optical or line following approach. We have noticed that IR dependent sensors may vary dramatically based on different lighting and environments, whereas touch is easy to implement and almost perfectly reliable. In order to score, we would only go after the main balls and shoot them as we picked them up (rather then storing them for later).

Design

The plans for Marvin can be seen in Figure 2. Marvin is made of plexiglass with a square base. Marvin was designed to fit within the 12x12x12 inch box requirements of the competition, but allow enough room for additions or changes to the design. We ended up trimming the base down so we could have the “scoopers” (see below), but the base still had enough room for a stray ping pong ball to fit between a wall and the wheels. This was to prevent the bot from getting “stuck” because we could not hit a wall (and prevent the touch sensors from knowing we reached the wall). On top of the base is a vertical piece of plexiglass to hold our Xiphos board (Atmel AVR based microcontroller board), and to add some defense/blocking capability to the bot. The shooter is at the front of the robot, and the servos on the sides were for picking up the balls. Each of the individual portions of the robot is explained below. A picture of Marvin on competition day can be seen in Figure 3.

Final Marvin Autodesk Inventor Design
Marvin on the day of the competition

Base:

We decided to go with a tried and true square platform using four omniwheels as shown in Figure 4. Two motors/wheels are configured diagonally from each other facing the same direction; with an identical set rotated 90 degrees. Omniwheels allow free movement perpendicular to the wheel’s direction by lining the outside of the wheel with rollers. In this configuration, with only one motor driver (two diagonal motors connected together in parallel to each channel), the bot can move freely in any planar direction, with the same heading. Using two motor drivers (each motor driven by an independent channel) the bot has full 2D movement, including rotation in either direction. For this year’s competition, we saw no need for the bot to rotate, so we went with a single Sabertooth 2x10 Motor Controller between the wheels.

Marvin Base

Picking up balls

At first, our plan was to use paintbrushes attached to rotating servos to pick up balls from the trough. We initially built, coded, and tested this idea with limited success – but our robot had to drive very slowly to ensure we collect every ball. We added a “scoop” to the sides that would keep the balls in front of the brush as we drove (Figure 5) and found that the scoop alone worked so well to pick up the balls that the brushes were no longer needed. In the end the scoops were spring loaded and held in place by the paintbrush servos, and at start they would lift and release the scoops.


"Scooper" to pick up balls

Troughs

The goal of the troughs was to direct ping pong balls into the motor. They were formed from bailing wire so they could be easily adjusted as needed and still strong enough to stay in place (Figure 6). During testing, we used thick paper as “walls” to make sure the balls stayed on path. Eventually, the back walls were made from sheet aluminum.

Shooter

The plan for the shooter was to have a single motor in the center and deflect the balls as they shot out of the front (Figure 7). The balls were directed from the troughs into the shooter – which was a motor with a rotating foam wheel mounted above the ball path. The motor mount was built to allow adjustable height, so we could tweak the position to get the distance we wanted. Immediately after the wheel was an adjustable height ramp and a set of bumpers to direct the ball towards the net. The bumpers were attached to a servo on top of the shooting mechanism that rotated based on what side of the course Marvin was on.

Marvin's shooter

Electronics:

A block diagram for all the electronic components can be seen in Figure 8. Our system was powered by a 11.1V 2.2AH Lithium Polymer Battery driving an Atmel based microcontroller (Xiphos board). As was mentioned above, servos were used to deploy the scoopers and direct the balls from our shooter motor. A Sabertooth 2x10 Motor Controller was responsible for driving our four motors with 2” omniwheels. Finally, eight touch sensors around Marvin controlled movement.

Block diagram for Marvin

Code

The code for Marvin was relatively simple due to the simple design. We basically used a loop to drive in a square - and turned on the appropriate motors at each side. In order to stay on course, we would also push against the wall while driving (e.g. when driving forward, we also drove slightly left to stay against the left wall). In addition to changing the aim of the deflector, the speed of the motor was also adjusted so that we would slow down or speed up the shooter based on the distance from the net. The only real thought that went into the code was to trigger a direction change if the robot did not hit a wall in a specified time (assume that Marvin is stuck). Marvin’s code is attached to the end of this report.

Lessons Learned

One of the major pitfalls of our bot was the inconsistency of our shooter. The shooter motor was built early on into the project, with decent results, but the wheel was poorly balanced, causing a lot of vibration. The deflector was a late addition to the bot, and did not provide enough consistency or deflection at higher motor speeds. Due to the imbalanced wheel, the motor tended to fire balls at various distances, but was more consistent at higher speeds. At higher speeds, however, the deflectors were knocked out of the way by the force of the ball and were far less effective. A better design would be a two-shooter method, employed by several bots in this competition and in the previous Roborodentia. We chose to go with a single shooter to save parts and reduce the amount of design and testing, but it ended up being difficult to modify to try and meet our goals.

Another weakness, although less evident, was the drive system. We chose to use the same 4-motor omniwheel configuration that we and several other teams used in previous competitions. In last year’s competition, we had issues with the wheels being unbalanced, and one or more not contacting the ground fully. We purchased a new set of wheels and hubs to fix this problem, but each wheel needed to be drilled manually to fit the hubs. Even using a drill press, some of the holes were misaligned, and this again caused one of the wheels to be unbalanced. Ultimately, our temporary fix for competition was to add a large weight to the bot (we simply taped a lead-acid battery to a free corner of the bot), which solved the problem well enough to prevent any issues during competition. Next time, we would opt for a set of wheels and motors that were pre-drilled and would be well balanced.


Conclusion

Marvin placed 3rd out of the 19 teams that competed in Roborodentia 2011. We (Figure 9) had a great time with the project and learned many valuable lessons about creating a working robot from scratch. Roborodentia is an excellent example of Cal Poly’s “Learn by Doing” philosophy and is an invaluable experience to the students involved. We hope to continue building robots and look forward to Roborodentia 2012!

Zach Negrey, Justin Kenny, Dennis Cagle, and Marvin
Code

Here is the code that was run during the competition:

  1. /*
  2.    Marvin
  3.    Dennis Cagle, Justin Kenny, Zach Negrey
  4.    roborodentia.h
  5.     
  6.  */
  7.  
  8. // globals.h is a common file used by Xiphos applications
  9. #include "globals.h"
  10.  
  11. #ifndef roborodentia_h_file
  12.  
  13. #define CLOCKTIMEFB 200  // 20 seconds
  14. #define CLOCKTIMELR 110  //11 seconds
  15.  
  16. //Speeds
  17. #define STOP 127
  18. #define STOPR 129
  19. #define FBSPEED 30
  20. #define BACKWARDS ((STOP-3)+FBSPEED)
  21. #define FORWARD (STOP-FBSPEED)
  22. #define RIGHT 175
  23. #define LEFT 60
  24.  
  25. //Speeds to push against the wall
  26. #define NUDGE_L 110
  27. #define NUDGE_R 136
  28. #define NUDGE_F 90
  29. #define NUDGE_B 155
  30.  
  31. // Drive speeds
  32. #define FULL 255
  33. #define FULL_R 0
  34.  
  35. // Paintbrush speeds
  36. #define BRUSH_SPEED 50
  37. #define BRUSH_SPEED_L (STOP + BRUSH_SPEED)
  38. #define BRUSH_SPEED_R (STOPR - BRUSH_SPEED)
  39.  
  40. // Deflect left and right positions
  41. #define DEFLECT_R 255
  42. #define DEFLECT_L 0
  43.  
  44. // Shooting motor speeds at various points in the course
  45. #define SMOTOR_SPEED_L 149
  46. #define SMOTOR_SPEED_R 148
  47. #define SMOTOR_SPEED_MIN_L 146
  48. #define SMOTOR_SPEED_MIN_R 144
  49.  
  50. //Motor Locations
  51. #define T_FWD 0
  52. #define T_BWD 1
  53. #define T_RGT 2
  54. #define T_LFT 3
  55. #define F_MOTORS 1
  56. #define S_MOTORS 0
  57. #define D_MOTOR 2
  58. #define SHOOTER 1
  59. #define BRUSH_R 4
  60. #define BRUSH_L 6
  61.  
  62. //Touch sensor locations
  63. #define BL 3
  64. #define LB 4
  65. #define BR 2
  66. #define RB 1
  67. #define RF 0
  68. #define FR 7
  69. #define FL 6
  70. #define LF 5
  71.  
  72.  
  73. //Function declarations
  74. void botInit();
  75. u08 aDigital2(u08 pin);
  76. void drive();
  77. int driveWithTouch(int direction);
  78. void stopAll();
  79. void moveForward();
  80. void moveBackwards();
  81. void moveRight();
  82. void moveLeft();
  83.  
  84. #endif
  85.  
  86.  
  87. /* 
  88.    Marvin
  89.    Dennis Cagle, Justin Kenny, Zach Negrey
  90.    roborodentia.c
  91.     
  92.     Winter 2011
  93.     Roborodentia 2011
  94.     
  95.     Marvin is an autonomous robot that drives in a 
  96.     square picking up and shooting ping pong balls.
  97.     He is awesome.
  98.  */
  99.  
  100. #include "Roborodentia.h"
  101.  
  102. int main()
  103. {
  104.    // Initialize the Xiphos board and set up pins
  105.    initialize();
  106.    botInit();
  107.  
  108.    // STOP the drive motors (just in case)
  109.    stopAll();
  110.    motor0(STOP);
  111.  
  112.    // Wait for button press
  113.    clearScreen();
  114.    printString("Robo 2011");
  115.    lowerLine();
  116.    printString("I'm so depressed");
  117.    buttonWait();
  118.  
  119.    // Push the fins out by spinning the paintbrushes
  120.    servo(BRUSH_R, BRUSH_SPEED_L);
  121.    servo(BRUSH_L, BRUSH_SPEED_R);
  122.    // Stop the paintbrushes (the two 
  123.    //   paintbrushes don't stop at the same value.)
  124.    delayMs(500);
  125.    servo(BRUSH_R, STOPR);
  126.    servo(BRUSH_L, STOP);   
  127.  
  128.    // Go around the course 4 times to ensure all balls
  129.    //   have been collected (and to have a shot at deflecting
  130.    //   from anywhere on the course)
  131.    drive();
  132.    drive();
  133.    drive();
  134.    drive();
  135.  
  136.    // Stop the drive motors and the shooting motor, we're done
  137.    stopAll();
  138.    motor0(STOP);
  139.  
  140.    // Dummy loop (chill out until a reset or power off)
  141.    while (1) {}
  142. }
  143.  
  144. /* 
  145.    Set up analog pins to be used as digital inputs 
  146.  */
  147. void botInit() 
  148. {
  149.    // Use the analog pins as digital inputs for the touch sensors
  150.    PORTF = 0xFF; // Use PORTF (analog port) as input (enable pull-ups)
  151.    digitalDirections(0x0000);
  152.    digitalPullups(0xFFFF);
  153. }
  154.  
  155. /* 
  156.    Check to see if touch sensors are pressed 
  157.  */
  158. u08 aDigital2(u08 pin)
  159. {
  160.    // Read sensor input and initialize a u08 comparator variable
  161.    u08 temp = analog(pin);
  162.    u08 comp = 127;
  163.  
  164.    return (temp > comp);
  165. }
  166.  
  167. /* 
  168.    Normal drive mode. Goes around course once, changing directions
  169.    each time the touch sensor is pressed. 
  170.  */
  171. void drive()
  172. {
  173.    driveWithTouch(T_FWD);
  174.    delayMs(500);
  175.    driveWithTouch(T_RGT);
  176.    delayMs(500);
  177.    driveWithTouch(T_BWD);
  178.    delayMs(500);
  179.    driveWithTouch(T_LFT);
  180.    delayMs(500);
  181. }
  182.  
  183.  
  184. /* 
  185.    Drive in a specified direction (see: T_FWD, T_BWD, T_RGT, and T_LFT)
  186.    until the touch sensors are pressed, at which point the drive motors
  187.     stop. Also controls the speed of the shooting wheel. In all cases,
  188.     if this method takes too long, it will break out and return so that
  189.     the next stage can start (in case Marvin gets stuck on a rogue 
  190.     ping-pong ball).
  191.  */
  192. int driveWithTouch(int direction)
  193. {
  194.    int count = 0, var_shoot = 0;
  195.    switch(direction) 
  196.    {
  197.       case T_FWD:
  198.          // Start driving forward
  199.          var_shoot = SMOTOR_SPEED_L;
  200.          moveForward();
  201.  
  202.          // Adjust the speed of the shooting wheel based on how far
  203.          //   along the wall the robot is (as determined by the time
  204.          //   spent in the stage)
  205.          while ((aDigital2(FR) && aDigital2(FL)) && (count < CLOCKTIMEFB))
  206.          {
  207.             // Slow down the shooting motor by 1 every five seconds
  208.             count++;
  209.             if ((count % 50) == 0)
  210.             {
  211.                var_shoot--;
  212.  
  213.                // Make sure shooting motor doesn't become too slow
  214.                if (var_shoot < SMOTOR_SPEED_MIN_L)
  215.                {
  216.                   var_shoot = SMOTOR_SPEED_MIN_L;
  217.                }
  218.             }
  219.  
  220.             // Send the adjusted speed to the shooting motor
  221.             motor0(var_shoot);
  222.             delayMs(100);
  223.          }
  224.  
  225.          // Stop driving forward
  226.          stopAll();
  227.          return 1;
  228.  
  229.       case T_BWD:
  230.          // Start driving backwards
  231.          moveBackwards();
  232.          var_shoot = SMOTOR_SPEED_MIN_R;
  233.  
  234.          // Adjust the speed of the shooting wheel based on how far
  235.          //   along the wall the robot is (as determined by the time
  236.          //   spent in the stage)
  237.          while ((aDigital2(BR) && aDigital2(BL)) && (count < CLOCKTIMEFB))
  238.          {
  239.             // Speed up the shooting motor by 1 every 3.5 seconds
  240.             count++;
  241.             if ((count % 35) == 0)
  242.             {
  243.                var_shoot++;
  244.  
  245.                // Make sure shooting motor doesn't become too fast
  246.                if (var_shoot > SMOTOR_SPEED_R)
  247.                {
  248.                   var_shoot = SMOTOR_SPEED_R;
  249.                }
  250.             }
  251.  
  252.             // Send the adjusted speed to the shooting motor
  253.             motor0(var_shoot);
  254.             delayMs(100);
  255.          }
  256.  
  257.          // Stop driving backwards
  258.          stopAll();
  259.          return 1;
  260.  
  261.       case T_RGT:
  262.          // Start moving right
  263.          moveRight();
  264.  
  265.          // Keep track of how long we have been moving right. If it
  266.          //   takes too long, break out and start moving backwards.
  267.          while ((aDigital2(RF) && aDigital2(RB)) && (count < CLOCKTIMELR))
  268.          {
  269.             count++;
  270.             delayMs(100);
  271.          }
  272.  
  273.          stopAll();
  274.          return 1;
  275.  
  276.       case T_LFT:
  277.          // Start moving left
  278.          moveLeft();
  279.  
  280.          // Keep track of how long we have been moving left. If it
  281.          //   takes too long, break out and start moving forwards
  282.          while ((aDigital2(LF) && aDigital2(LB)) && (count < CLOCKTIMELR))
  283.          {
  284.             count++;
  285.             delayMs(100);
  286.          }
  287.  
  288.          stopAll();
  289.          return 1;
  290.  
  291.       default:
  292.          return 0;
  293.    }
  294.  
  295. }
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306. /* 
  307.    Stop the drive wheels and paintbrushes
  308.  */
  309. void stopAll() 
  310. {
  311.    clearScreen();
  312.    printString("stopAll");
  313.    servo(F_MOTORS, STOP);
  314.    servo(BRUSH_L, STOP);
  315.    delayMs(100);
  316.    servo(S_MOTORS, STOP);
  317.    servo(BRUSH_R, STOPR);
  318.    //motor0(STOP);
  319. }
  320.  
  321. /* 
  322.    Drive forward while also staying against the wall.
  323.  */
  324. void moveForward()
  325. {
  326.    // Stay against the left wall by slowly driving into it
  327.    servo(S_MOTORS, NUDGE_L);
  328.    delayMs(100);
  329.    clearScreen();
  330.    printString("Forward");
  331.    // Aim deflector to the right
  332.    servo(D_MOTOR, DEFLECT_R);
  333.    // Drive forwards
  334.    servo(F_MOTORS, FORWARD);
  335. }
  336.  
  337. /* 
  338.    Drive backwards while also staying against the wall.
  339.  */
  340. void moveBackwards()
  341. {
  342.    // Stay against the right wall by slowly driving into it
  343.    servo(S_MOTORS, NUDGE_R);
  344.    delayMs(100);
  345.    clearScreen();
  346.    printString("Backwards");
  347.    // Aim deflector to the left
  348.    servo(D_MOTOR, DEFLECT_L);
  349.    // Drive backwards
  350.    servo(F_MOTORS, BACKWARDS);
  351. }
  352.  
  353. /* 
  354.    Drive right while also staying against the wall.
  355.  */
  356. void moveRight()
  357. {
  358.    // Stay against the center wall by slowly driving into it
  359.    servo(F_MOTORS, NUDGE_F);
  360.    delayMs(100);
  361.    clearScreen();
  362.    printString("Right");
  363.    // Drive right
  364.    servo(S_MOTORS, RIGHT);
  365. }
  366.  
  367. /* 
  368.    Drive left while also staying against the wall.
  369.  */
  370. void moveLeft()
  371. {
  372.    // Stay against the back wall by slowly driving into it
  373.    servo(F_MOTORS, NUDGE_B);
  374.    delayMs(100);
  375.    clearScreen();
  376.    printString("Left");
  377.    // Drive left
  378.    servo(S_MOTORS, LEFT);
  379. }

Files

Here is a .zip file containing the Autodesk Inventor mechanical design files for the bot: http://rev0proto.com/files/marvin-inventor.zip

Parts and Materials

Most of the parts and materials used to build the bot were reused from what was on hand in the club room and what was used in last year's bot. The actual total cost of the bot (purchased materials only) is around $120.

Component Quantity Unit Cost Total Cost Source Part Number Purpose
12" x 12" x 0.25" Acrylic Base 2 $5.59 $11.18 eStreetPlastics 1002501212 Serves as a base on which to attach motors, sensors, etc.
Xiphos Board 1 $130 $130 CPRC Marvin's Brain
11.1V 2.2AH Lithium Polymer Battery 1 $9.99 $9.99 HobbyKing T2200.3S.20 Power source for the motors and microcontroller system
Sabertooth 2x10 Motor Controller 1 $79.99 $79.99 Dimension Engineering Sabertooth 2X10 Motor controllers for the four motors driving the bot
Standard Size Servo 2 ~$8 $16 CPRC Servos that open the two scoops for collecting balls
Micro Size Servo 1 $3.94 $3.94 Dealextreme Servo that controls the direction of the ball shooter
Aluminum Sheet 2 ~$7 $14 Home Depot Used for various parts of the bot; ramp, guard walls, brackets, scoops
Aluminum Angle Stock 1 ~$8 $8 Home Depot Used for brackets and mounting the servos/scoops
2" Diameter Omniwheels 4 $7.48 $29.92 Kornylak Corporation FXA314 Wheels that let the bot travel in any direction in 2-D space
6mm Shaft Diameter Hub (Pair) 2 $8.00 $16.00 Lynxmotion HUB-02 Hubs to attach the omniwheels to the motors
4-40 Mounting Hardware 1 ~$15.00 $15.00 Home Depot, Bolt Depot Machine Screws, Nuts, and Washers to hold parts of the bot together
Total Price ~$334.02