Tri-BotHack

Problem/Finish Description

 * 1) Get all 5 tribots running
 * 2) Begin programming tribots to go in a patterns like squares, circles
 * 3) Add remote emergency take over capability
 * 4) Add automous ability to travel the cooridors of first floor Clark Library Building
 * 5) Add features from the head
 * 6) Replace arduino with papilio
 * 7) Pull all existing documentation into one place in the below context

Conceive
Project was inspired by this video that shows a robot balanced on top of a basketball. A completely powered Omni wheel connected to some accelerometer/gryo can create a powered unicycle that moves sideways. This is completely different than the one wheel motor cycle, the monocycle or the R.O.I.T wheel.

The goal is to duplicate the robot balanced on top of a basketball and ultimately duplicate the powered unicycle.

The idea was to start with hacking a toy. Here is an example hack:

WowWee Tribots retail anywhere from $300 and below here The robot is officially called the "WowWee Tribot Talking Companion." There is a Wowwee Mini Tri-bot that retails for around $21 that should not be confused with the bigger brother. Online it is hard to tell them apart. The Mini Tri-bot does not ship with universal or Omni wheels.

Design
Reverse engineering a toy is similar to forward design. It starts with re-creating the implmentation/operation documentation that already exists.

Implement
These are the steps to take apart a toy Tribot WowWee and add an arduino

Operate

 * 1) Find screwdriver that works
 * 2) Put batteries in (8 AA batteries)
 * 3) Turn on
 * 4) Push head down
 * 5) Turn off
 * 6) Take batteries out

/* BallBot Exercise This is test code to exercise the WowWee Tri-Bot capabilities Have to push down the head to get the robot to move This example code is in the public domain. */

// constants won't change. They're used here to // set pin numbers: const int buttonPin = 3;    // the number of the pushbutton pin const int ledPin = 13;      // the number of the LED pin

// variables will change: int buttonState = 0;        // variable for reading the pushbutton status int headPush=0; //if 0 means execute any instructions and wait, if 1 then do and check if headpushed regularly

void setup { // initialize the digital pin as an output. pinMode(12, OUTPUT); //yellow wire to motor enable 1 pinMode(11, OUTPUT); //teal wire to motor enable 2 pinMode(10, OUTPUT); //blue wire to motor enable 3 pinMode(9, OUTPUT); // white wire to motor direction 1 pinMode(8, OUTPUT); //gray wire to motor direction 2 pinMode(7, OUTPUT); //purple wire to motor direction 3 pinMode(6, INPUT); //orange encoder from motor 1 pinMode(5, INPUT); //red encoder from motor 1 pinMode(4, INPUT); //brown encoder from motor 1 pinMode(ledPin, OUTPUT);  // initialize the LED pin as an output: pinMode(buttonPin, INPUT); // initialize the pushbutton pin as an input: }

void loop{ while (headPush == 0) { // wait for head push before starting buttonState = digitalRead(buttonPin); if (buttonState == HIGH) { // turn LED on: digitalWrite(ledPin, HIGH); headPush = 1; } } //  oneMotorAtATime; // spinTightCCW; oneMotorAtATime; delay(1000); spinTightCCW; delay(1000); spinTightCW; delay(1000); gradualTurn; delay(1000); forWard; delay(1000); backWard; delay(1000); rightForward; delay(1000); rightBackward; delay(1000); headPush=0; }

void oneMotorAtATime {

//motors turning individually delay(1000);             // wait for a second digitalWrite(12, HIGH);  // set the LED on  delay(2000);              // wait for a second digitalWrite(12, LOW);   // set the LED off delay(2000);             // wait for a second digitalWrite(11, HIGH);  // set the LED on  delay(2000);              // wait for a second digitalWrite(11, LOW);   // set the LED off delay(2000);             // wait for a second digitalWrite(10, HIGH);  // set the LED on  delay(2000);              // wait for a second digitalWrite(10, LOW);   // set the LED off headPush=0; }

void spinTightCCW { delay(1000); digitalWrite(9, HIGH);  // reverse motor 1 digitalWrite(8, HIGH);  // reverse motor 2 digitalWrite(7, HIGH);  // reverse motor 3 delay(100); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(11, HIGH);   // turn motor 1 on  digitalWrite(10, HIGH);   // turn motor 3 on  delay(840); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(11, LOW);  // turn motor 2 off digitalWrite(10, LOW);  // turn motor 3 off digitalWrite(9, LOW);  // normal motor 1 digitalWrite(8, LOW);  // normal motor 2 digitalWrite(7, LOW);  // normal motor 3 headPush=0; }

void spinTightCW { delay(1000); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(11, HIGH);   // turn motor 1 on  digitalWrite(10, HIGH);   // turn motor 3 on  delay(840); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(11, LOW);  // turn motor 2 off digitalWrite(10, LOW);  // turn motor 3 off headPush=0; }

void forWard { delay(1000); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(8, HIGH);   // reverse direction of motor 2 digitalWrite(11, HIGH);  // turn motor 2 on  delay(2000); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(8, LOW);  // make direction of motor 2 normal digitalWrite(11, LOW);  // turn motor 2 off headPush=0; }

void backWard { delay(1000); digitalWrite(9, HIGH);  // reverse direction of motor 1 digitalWrite(12, HIGH);  // turn motor 1 on     digitalWrite(11, HIGH);   // turn motor 2 on  delay(2000); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(9, LOW);  // make direction of motor 2 normal digitalWrite(11, LOW);  // turn motor 2 off headPush=0; }

void rightForward { delay(1000); digitalWrite(11, HIGH);  // turn motor 1 on   digitalWrite(7, HIGH);   // reverse direction of motor 2 digitalWrite(10, HIGH);  // turn motor 2 on  delay(2000); digitalWrite(11, LOW);  // turn motor 1 off digitalWrite(7, LOW);  // make direction of motor 2 normal digitalWrite(10, LOW);  // turn motor 2 off headPush=0; }

void rightBackward { delay(1000); digitalWrite(11, HIGH);  // turn motor 1 on   digitalWrite(8, HIGH);   // reverse direction of motor 2 digitalWrite(10, HIGH);  // turn motor 2 on  delay(2000); digitalWrite(11, LOW);  // turn motor 1 off digitalWrite(8, LOW);  // make direction of motor 2 normal digitalWrite(10, LOW);  // turn motor 2 off headPush=0; }

void gradualTurn { delay(1000); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(8, HIGH);   // reverse direction of motor 2 digitalWrite(11, HIGH);  // turn motor 2 on  delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(8, LOW);  // make direction of motor 2 normal digitalWrite(11, LOW);  // turn motor 2 off headPush=0; }

Use the Motor test to see a "skeleton" of what the coding in Tribot should look like. The setup tells you which pins are wired to what. The loop tells you all of the commands Tribot will follow. In this case it's -one motor at a time -spin tight CCW -one motor at a time -spin tight CCW -spin tight CW -gradual turn -forward -backward -right forward -right backward Each command is followed by a delay of 1000 miliseconds

Decide what new pattern will be Envision what you want the Tribot to do. In this case, it needs to go in a square. A square looks like the graphic above. This new pattern begins with a starting point, then a forWard command from the point then a gradualTurn then forWard then gradualTurn then forWard then gradualTurn and lastly one more forWard command.

Change the original Copy the original code into a word document. Decide what you want in the new code. In the loop part of the code, erase what you do not want. At the end, insert the new commands that will make a square. The new commands come from the graphic of the path. Each command is followed by a 1000 millisecond delay. After the loop comes the individual sections for each command. They're titled "void (insert name)". Keep only the commands that you will be using. Erase the rest of the sections.

The final code The final code should look like this:

void setup { // initialize the digital pin as an output. pinMode(12, OUTPUT); //yellow wire to motor enable 1 pinMode(11, OUTPUT); //teal wire to motor enable 2 pinMode(10, OUTPUT); //blue wire to motor enable 3 pinMode(9, OUTPUT); // white wire to motor direction 1 pinMode(8, OUTPUT); //gray wire to motor direction 2 pinMode(7, OUTPUT); //purple wire to motor direction 3 pinMode(6, INPUT); //orange encoder from motor 1 pinMode(5, INPUT); //red encoder from motor 1 pinMode(4, INPUT); //brown encoder from motor 1 }

void loop // oneMotorAtATime; // spinTightCCW; { oneMotorAtATime; delay(1000); spinTightCCW; delay(1000); gradualTurn; delay(1000); rightForward; delay(1000); gradualTurn; delay(1000); forWard; delay(1000); gradualTurn; delay(1000); forWard; delay(1000); gradualTurn; delay(1000); forWard; delay(1000); }

void oneMotorAtATime {

//motors turning individually delay(1000);             // wait for a second digitalWrite(12, HIGH);  // set the LED on  delay(2000);              // wait for a second digitalWrite(12, LOW);   // set the LED off delay(2000);             // wait for a second digitalWrite(11, HIGH);  // set the LED on  delay(2000);              // wait for a second digitalWrite(11, LOW);   // set the LED off delay(2000);             // wait for a second digitalWrite(10, HIGH);  // set the LED on  delay(2000);              // wait for a second digitalWrite(10, LOW);   // set the LED off }

void spinTightCCW { delay(1000); digitalWrite(9, HIGH);  // reverse motor 1 digitalWrite(8, HIGH);  // reverse motor 2 digitalWrite(7, HIGH);  // reverse motor 3 delay(100); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(11, HIGH);   // turn motor 1 on  digitalWrite(10, HIGH);   // turn motor 3 on  delay(840); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(11, LOW);  // turn motor 2 off digitalWrite(10, LOW);  // turn motor 3 off digitalWrite(9, LOW);  // normal motor 1 digitalWrite(8, LOW);  // normal motor 2 digitalWrite(7, LOW);  // normal motor 3

} void forWard { delay(1000); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(8, HIGH);   // reverse direction of motor 2 digitalWrite(11, HIGH);  // turn motor 2 on  delay(2000); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(8, LOW);  // make direction of motor 2 normal digitalWrite(11, LOW);  // turn motor 2 off

}

void rightForward { delay(1000); digitalWrite(11, HIGH);  // turn motor 1 on   digitalWrite(7, HIGH);   // reverse direction of motor 2 digitalWrite(10, HIGH);  // turn motor 2 on  delay(2000); digitalWrite(11, LOW);  // turn motor 1 off digitalWrite(7, LOW);  // make direction of motor 2 normal digitalWrite(10, LOW);  // turn motor 2 off

}

void gradualTurn { delay(1000); digitalWrite(12, HIGH);  // turn motor 1 on   digitalWrite(8, HIGH);   // reverse direction of motor 2 digitalWrite(11, HIGH);  // turn motor 2 on  delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(10,HIGH); // turn motor 3 on delay(200); digitalWrite(10,LOW); // turn motor 3 on delay(200); digitalWrite(12, LOW);  // turn motor 1 off digitalWrite(8, LOW);  // make direction of motor 2 normal digitalWrite(11, LOW);  // turn motor 2 off

}

Powering Tribot If batteries are left in the tribot, they will corrode the battery case. The problem can be solved by scrapping off the corrosion. Corrosion is mostly found on the removable red lid, but it also occurs at the top of the battery, deep inside the base.

Wheels spin when turning on Send motor test to the arduino. It probably has another program loaded.

Demo
Presentation

Seminar Presentation 2014MAR20

A demonstration of a working tribot with the Motor test installed is shown on the following video: Tribot Demo Test

Next Steps

 * 1) Explore possibilities of line-following tribot
 * 2) Apply power to the head and try to control it's features with arduion
 * 3) Start capturing wheel turning information from the encoder
 * 4) Test new base to see if tribot can work equally well on ground and ball
 * 5) Define working, test all 5 and document current status
 * 6) Add simple mechanism so that all 5 spill out of a door when is opened
 * 7) Add remote controller
 * 8) Add speakers
 * 9) add a camara
 * 10) Determine if accelerometer and gyro have to be calibrated, start testing with PID software