CARDBOARD ROBOT --- DANCE, DANCE, DANCE!!
by marc.cryan in Circuits > Robots
17995 Views, 15 Favorites, 0 Comments
CARDBOARD ROBOT --- DANCE, DANCE, DANCE!!
Robots:
-Can hear or see, or both - kinda
-Are strong, but break easily
-Can robot dance
The goal here is to build a robot, that is like a robot. It should be able to do human scale stuff, and look like a robot.
Don't get too excited - it does not end well!
This is Emma's clean up robot -
-It is supposed to:
- Here what you say
- Pick stuff up and put it away
- Look like a robot
The big challanges are: getting good motors( harvest from drills at Harbor Freight ) , controlling the motors, powering the motors, voice recognition, navigation, not catching on fire, not breaking things, not spending to much money..... -- link to drill --
Very few of these goals are completed in this instructable - but it is getting too long.
So, lets begin!
NOTE: If you follow this instructable step-be-step from begining to end, it will probably drive you insane (have you every tried following a cat all day?) I say, learn what you can, put a fresh battery in your smoke detector, and bash on.
Everybody likes videos up front - here are a few:
Video - shows basic functions - all motors running bi-directional
Video: Wheels working well (ie before they broke)
Video: Crash:
Video: Emma explains:
Video - with head - serial commands
Plans
Get Motors
Right now I'm going for quick and dirty.
So, HarborFreight.com here I come! -- here is a link to the drill I am using -- link--
I bought a bunch of cordless drills from Harbor Freight for about 15$ each. They come with the motor (of course), 18V battery, and charger. That is a pretty good price for all that. Also I like the way you can just jam stuff in the drill chuck and tighten it down. Nothing easier than that for attaching an axle, drive-screw, or whatever.
The problem with these motors, is that with coil resistance of only 0.5ohm and a 18V power supply, we are dealing with alot of power. (some math: V = IR... so I = V/R or I = 18/.5 which is 36Amps) ( more math: W = VI (right?) or W = 36 * 18 which is 648 Watts (is that right?) if that is correct, then running these at full power uses as much power a 6-and-a-half 100 watt light bulbs (really?))
If you are used to regular Arduino type stuff, then this kind of power will, as they say, burn up your sh*t. (even if my math is wrong - 648 watts? yikes)
But let's deal with that latter and play with the boxes!
Take 'em Apart
Ummmm...
Right, the drills.
Take them apart.
You know how.
See the pictures (unless you want to be surprised (also, there is a screw under the label))
So, What Is All This Stuff
Now, what do we have here?
Well, we have the parts that make a cordless drill do what a cordless drill does.
- Motor (with gear box and a chuck)
- A trigger to control the speed (in a fancy way it turns out)
- Forward/reverse switch (this is heavy duty - you will see why)
- The connection for the battery
- Some plastic
- And an LED (yay!)
This drill is not really made out of cheap parts, but you can tell it was cheaply assembled. Very few of the wires are soldered in place, they are mostly just sort of jammed in holes.
So:
(a)Now you know why stuff like this often stops working suddenly, then works fine, then stops working again, then it sounds like something is loose.
and
(b) This is easy to take apart, you just pull the wires out
but
(c)* It is easy to break stuff that would have been useful, expect now it is just a little pile of wire, plastic and springs never to be put back together again (like the head of a Barbie that is attached with a plastic ring on the end of a little rubber band, so to get it back together you have to pull the ring out of the head, and stretch the rubber band far enough (but no so far it breaks off) and jam the wring back in the neck whole. You know? I'll take a picture. (no I won't, even if I remember to take a picture I'll never come back and add it in))
Now!
- Take the motor out and set aside
-Take out and examine the trigger mechanism.
The trigger mechanism is actually a complete little PWM motor driver, complete with a microcontroller and everything. Unfortunately, even if you new what was going on here, it would be very hard to get back together once you'd opened it up. The more useful (and easy to use) part is the high power mosfet on a big heat sink. We will use this plus and Arduino in the next step to get the motor running.
*why are these lettered?
Control Motor Speed With Arduino
Control Direction... or Burn Things
err..
Remember that big mechanical switch that controlls the motor direction?
Not me.
I confidently wired up some relays on a neat little perf-board.
Plugged it all in.
AND
hmm... the relays are clicking but the motor isn't turning... it is making some high pitched noise though, so that's good (right?)
(puts ear up to board)
well, I can here the relays clicking. So I have clearly done everything correctly.
hmm... my ear is hot.
(pffffff sound)
hmmm... what's all this smoke?
ohhhhhh....... right the 648watts of power!!! Yikes, I've burnt all that stuff up. I grabbed these nice big relays with a big 2amp rating - but these are not hobby motors - they pull 36amps and up. So I haven't made a direction switcher --- I've made a fire starter!!
So that explains why among all the little pieces the drill had that big mechanical switch to reverse direction, which big metal, spring loaded contacts. We are dealing with some power!
And, in electronics, as in life, power = money, power components get expensive quick (maybe only 1-3$ per part, but then you need four of them for each motor, and we want to use like 8 motors... so pretty soon we'll be spending more to switch directions then we did on the motors, MOSFET, batteries, and charger...
Let's find a cheap (and roboty) way out of this mess!
Video: testing current draw with digital multimeter (fuse will blow above 2 amp)
Tiny Servos to the Rescue?
Have Some Cake
Build the Mechanical Parts of the Mechanical Man
What do we want to move?
- Arms, starting with the shoulders
- Wheels, to get a round (legs would be nice, but we have to start somewhere)
- Hips - to bend at the waist --- maybe this is a torso, I don't know....
What do we have?
- All these drills we took apart
- Screws
- Plywood
- Bits of plumbing supplies
- General basement debris
- Whatever is cheap at the Depot
- Cat poo
Here is a look at what we will end up with as the basic skeleton and joints.
Mount Drill Motors
Plumbers Strap:
I like to use metal plumbers strap to mount motors - cheap and easy.
However this stuff will break if you bend it too many times.
Here are the basic steps:
- Position motor
- Cut a peice of plumbers strap
- Bend the plumbers strap over the motor
- Drill the strap down with short screws (using 1 inch drywall screws)
- Make sure it is tight (you can usually do this by adding third screw, but you might have to shim it a little)
The gear box is a little wider than the motor, so I am a wooden shim to make up the difference.
- Add a second strap if needed
A Fancy Bracket
I went looking for a 'better' way, and found these brackets for hanging electrical conduit.
The one labeled ' #2 ' is the right side (in the electrical stuff section of Depot, near conduit - but in an aisle, not against the wall)
Steps:
- Bolt the bracket to the plywood
- Put the motor in the bracket
- Tighten the bolt on the bracket
Wheels
Then find something to use for wheels.
I'm using circles cut out of some MDF using a 4" hole saw.
Using 1/4"-20 machine screw for axles.
This looks like something that might need to get re-done latter.
Arms (or Shoulders at Least)
I am using #2 conduit clamps to hold the motors.
A bent steel rod serves as a temporary arm.
Basic Structure
There is one 'leg' made from a 4x4.
Some plywood makes the hips, back and chest.
The upper body is attached to the lower body with a strap hinge, so it can bend at the 'waist'
Latter we are going to fit the cardboard boxes over this frame, it doesn't have to be perfect - sloppy is good here, you can tighten things up as needed.
Something to Make It Bend at Waist
The motor will need to take some weight. We will also want to be able to leave it in a fixed position (such as upright), without having to keep power to the motor.
After some tinkering, I decided to use a drive-screw attached to a crude linkage.
The key to this is a part from the plumbing department (down towards the end and sort of high up). It is a '3/8 Side Beam' - but who cares - it cost $1.30 and is heavy duty.
Here are the steps:
- Mount the thing to the ply-wood. ( getting lazy here)
- Get a 3/8" threaded rod (cheapest is back in the conduit section, but there are shorter pieces near the nails)
- Cut the threaded rod to a good length (guess)
-put 2 bolts and a lock washer one end of the rod
- screw the rod into the threaded part of the 'side beam'
- Add a spot to mount a motor
- Hope that it will work out okay.
Update: this mechanism has problems - here is one:
Video -
Go to Maker Fair NY
Slap Some Cardboard on and See How It Works
Now lets take a minute to put the cardboard pieces on to see if this is going to work out.
Man - this is a long instructable.... isn't this the same as step 1?
What Next?
It is clear that unless we can run these motors, we don't have a robot.
Speed control is not a problem because we have the power mosfets from the drill. Switching directions is still a problem. Position feedback will be needed, at least for the arms, but let's forget about that for now.
Let's get the motor controls running well. As I said, and will repeat now, switching directions is still a problem. Doing it for less than the cost of the drills is the goal.
Here is my problem solving method:
- Give up
- Eat cake
- Find and use multi-meter
- Shop for big servos from McCmaster Carr
- Check bank account
- Have a cookie
- Shop for a motor controller kit
- Shop for components from digikey
- Check credit card balance
- Drink beer
- Scrounge around the house
- Repeat until out of beer, money, or cake
Foward and Reverse Motor Control
Cofrol the stock (original or 'as purchased') switch witha cheap little servo. These are havea small motor and a bunch of gears. You just need to give it some power and then tell it what position to go to. These go from 0 to 180 degress ( or 0 to pi radians). They are low power and mainly plastic and nylon.
Here's how -
- get a servo
- hold it up to switch
- scratch head
- find the little bag of plastic gears that it somes with
- snap a gear on the servo
- hold it up to the switch
- get a knife
- wittle down the gear so that it looks like it will work
- bandage wounds
- hold it up to the switch
Now - ge the servo some power
servo has 3 lines
- brown/black - is ground
- Red - is power - 5volt for these
- orange or yellow - is communication
Run some test code with arduino
- get arduino
- open the example scetch - Sketch -> examples -> servo -> sweep
-
upload to arduino
- right com port?
- right board selected?
- pluged in
- most recent arduino software on PC?
- Did you break the arduino board las time....
-
Wire servo to arduino like this
- Black - Ground
- Red -> 5 Volt
- Orange -> Digital 9 (PWM)
- Press reset button (you really should have unplugged the arduino while doing the wiring...)
- Watch it go!
Now - get it all to work
- edit the example program so it goes to 90deg and stops
- with srvo at 90deg, hold it up to switch so it looks right
- Take off the plastic gear, and put it back on, so the switch is in the middle position
- Tape it all togetehr with electrical tape (or do somehting better..)
- Now, edidt the the sweep example so it goes like this - 45deg -- 90deg -- 135 deg -- 90 -- 135 -- 90 --135...
- Load it up
- Now the servo should move the swtich back and forth ... pretty much
- Make adjustements
- The servos will try to go to whatever angle it is told, if it can't then things might break.
- Reducing the angles helps --- I wound up with - 40deg --- 90deg --- 140deg (that doesn't seem right... 50--90--140 makes more sense)
- This runs better, but the motor is still straining at eitheend
- Now - you could get everything perfect --- or you can just limit how long the motors try to reach the position
- This is done by setting the angle, waiting a moment, then turning off the servo n(there is a function called 'detach' that does this.
- The final test code is below.
- This tells the servo to move, gives it a moment (0.3seconds) to move, then tuns the motor off
- This works well enough to move on
-
(why was this all a numbered list? eh...)
Arduino code that works:
//////////////////ARDUINO//////////////////
// This example code is in the public domain.
#include
Servo myservo; // create servo object to control a servo
int pos = 0; // variable to store the servo position
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
myservo.attach(9);
myservo.write(90); // go to middle
delay(300); // try to get to position for 0.3 seconds
myservo.detach(); // let servo give up
delay(2000);
myservo.attach(9);
myservo.write(140); //got to side
delay(300); //trying
myservo.detach(); //give up
delay(2000);
myservo.attach(9);
myservo.write(90); //go to middle
delay(300); //trying
myservo.detach(); //give up
delay(2000);
myservo.attach(9);
myservo.write( 40); //go to other side
delay(300); // trying
myservo.detach(); //give up
delay(2000);
}
Build First Version of Motor Controller
//////////////ARDUINO CODE////////////////////////
////////////////TEST CODE ////////////////
////////////////MOTOR SPEED CHANGES/////////////////
////////////////MOTOR DIRECTION CHANGES///////////////
// This example code is in the public domain.
#include
Servo myservo; // create servo object to control a servo
int pos = 0; // variable to store the servo position
int Ctrl = 6; // pin that will controll mosfet (to blue)
int spd = 0; // variable for speed
void setup()
{
// myservo.attach(9); // attaches the servo on pin 9 to the servo object
pinMode(Ctrl, OUTPUT); // set control pin as output
}
void loop()
{
// set direction with servo //
analogWrite(Ctrl, 0 ); // power off
delay(100);
myservo.attach(9);
myservo.write(140); // go to side
delay(600); // try to get to position for 0.6 seconds
myservo.detach(); // let servo give up
delay(1000);
//run the drill motor at different speeds
analogWrite(Ctrl, 20);
delay(1000);
analogWrite(Ctrl, 50);
delay(1000);
analogWrite(Ctrl, 100);
k
]]
1000);
analogWrite(Ctrl, 20);
delay(1000);
analogWrite(Ctrl, 50);
delay(1000);
analogWrite(Ctrl, 100);
delay(1000);
analogWrite(Ctrl,150);
delay(1000);
analogWrite(Ctrl, 200);
delay(500);
analogWrite(Ctrl,150);
delay(500);
analogWrite(Ctrl,100);
delay(500);
analogWrite(Ctrl,50);
delay(500);
analogWrite(Ctrl,20);
delay(500);
analogWrite(Ctrl,100);
delay(500);
analogWrite(Ctrl,200); // a little different
delay(500);
analogWrite(Ctrl,20);
delay(500);
analogWrite(Ctrl,0);
delay(500);
delay(3000); // 3 second delay befor repeat
}
Use a Relay Instead
Here is a much better way to control the motor direction -- ahhhh -- I seem to have lost all the build photos -- I will have to come back and fill this in --- There are photos of the breadboard version..... crap.
Parts:
- Relay - RTE24005F, tcyco - DPDT - contacts rated at 30VDC and 8 amps - Coil uses 5V and draws 400mW (will need a transistor to control this)
- Transistor (to control relay) - 2N3906TF - PNP - controls a max of 40V, 200mA, 625mW. ('max' means that if you go past any of these it will break)
- MOSFET - (to control motor speed) - use the MOSFET from the drill - - this one is good too: BUK7511 - N channel MOSFET, can control up to 55V, 75A, 157W
- Diodes - to protect against kickback from motor and solenoid (white line goes towards positive voltage, other side to ground/negative voltage)
- Screw terminals (because they are useful) - 1935161, Phoenix, - these have 2 positions (spots for wires) and a spacing of 5mm (0.2")
- Perfboards - (very useful) - 21-113, Datak - 2.8"x1.8" -- Electronix Express, RSR Electronics, www.elexp.com
- Wires
Video of test run with relay:
Build Motor Control Boards
Assembled Driver Boards - Clear Pictures
Wiring - Motor Power
For this I used the cords from wall-warts. I have a big box of these. A thicker wire would be better, but this is what I have, the wires do not get hot.
A power bus can be made by wiring together all the power inputs on the motor drivers, I've used orange for +18V.
I guessed at the pinouts from the relays to the motors. Basically, if a motor is running the wrong way you just need to switch these wires.
Wire screws are used to make connections to motors; these are commonly used in household wiring, and are brightly colored.
Wiring - 5volt Supply
For this I've used more zip cords from wall-warts. All 5volt inputs are connected. All grounds are connected.
5V and 18V grounds are connected to each other. A common ground is needed for the mosfets to work.
Wiring - Control Lines From Arduino to Motor Drivers
So - we have already brought the 5V and Grounds from the arduino to the relay boards, all that is left are the control lines.
Each board has 2 inputs that control the speed and direction of the motor. CatV cable is convenient because it is already bundled into pairs of 2.
Get organized:
Solid = direction pin (digital)
Striped = speed pin (pwm)
Wiring:
Orange 4 - left arm direction 5 - left arm speed
Green 7 - waist bend direction 6 - waist bend speed
Brown 8 - right wheel direction 9 - right weel speed
Blue 12 - left wheel direction 10 - Left wheel direction
not used 13 11
yet 0
1
not used Analog
yet 0 to 5
Using Firmata to Test Stuff
There are at least two parts to the program:
- Firmware that you load onto the Arduino (ie Arduino Code) this is included in the Arduino IDE: Examples -> Firmata -> Firmata 2_2 for Arduino UNO (if you are using an UNO)
- The other half runs on the computer - There is example code in Processing (get from Processing.org) ( http://www.arduino.cc/playground/Interfacing/Processing ) There is also an executable with a GUI here http://firmata.org/wiki/Main_Page
Test All Motors With Arduino - Autonomish
So here is some simple (but long) Arduino code.
It runs each motor - forward and backward - fast and slow.
///////////////////////// ARDUINO ////////////////////////////
// Direction low = towards body or Foward
//Direction High = away from body or Backward
int RightArmDir = 2;
int RightArmSpeed = 3;
int LeftArmDir = 4;
int LeftArmSpeed = 5;
int WaistDir = 7;
int WaistSpeed = 6;
int RightWheelDir = 8;
int RightWheelSpeed = 9;
int LeftWheelDir = 12;
int LeftWheelSpeed = 10;
int Slow = 20;
int Fast = 40;
int t1 = 500;
int t2 = 100;
void setup() {
pinMode(RightArmDir, OUTPUT);
pinMode(RightArmSpeed, OUTPUT);
pinMode(LeftArmDir, OUTPUT);
pinMode(LeftArmSpeed, OUTPUT);
pinMode(WaistDir, OUTPUT);
pinMode(WaistSpeed, OUTPUT);
pinMode(RightWheelDir, OUTPUT);
pinMode(RightWheelSpeed, OUTPUT);
pinMode(LeftWheelDir, OUTPUT);
pinMode(LeftWheelSpeed, OUTPUT);
Serial.begin(9600);
}
void loop() {
//BASIC TESTS//
Serial.println("BASIC TESTS");
// Test Right Arm
Serial.println("Right Arm");
//Right Arm Up
Serial.println("Up");
digitalWrite(RightArmDir, HIGH);
digitalWrite(RightArmSpeed, Slow);
delay (t1);
digitalWrite(RightArmSpeed,Fast);
delay (t2);
digitalWrite(RightArmSpeed,Slow);
delay(t1);
digitalWrite(RightArmSpeed, 0);
delay(t1);
//Right Arm Down
Serial.println("Down");
digitalWrite(RightArmDir, LOW);
digitalWrite(RightArmSpeed, Slow);
delay (t1);
digitalWrite(RightArmSpeed, Fast);
delay (t2);
digitalWrite(RightArmSpeed, Slow);
delay(t1);
digitalWrite(RightArmSpeed, 0);
delay(t1);
// Test Left Arm
Serial.println("Left Arm");
//Left Arm Up
Serial.println("Up");
digitalWrite(LeftArmDir, HIGH);
digitalWrite(LeftArmSpeed, Slow);
delay (t1);
digitalWrite(LeftArmSpeed, Fast);
delay (t2);
digitalWrite(LeftArmSpeed, Slow);
delay (t1);
digitalWrite(LeftArmSpeed, 0);
delay(t1);
//Left Arm Down
Serial.println("Down");
digitalWrite(LeftArmDir, LOW);
digitalWrite(LeftArmSpeed, Slow);
delay (t1);
digitalWrite(LeftArmSpeed, Fast);
delay (t2);
digitalWrite(LeftArmSpeed,Slow);
delay(t1);
digitalWrite(LeftArmSpeed, 0);
delay(t1);
// Test Waist
Serial.println("Waist");
//Bend Down
Serial.println("Down");
digitalWrite(WaistDir, HIGH);
digitalWrite(WaistSpeed, Slow);
delay (t1);
digitalWrite(WaistSpeed, Fast);
delay (t2);
digitalWrite(WaistSpeed, Slow);
delay(t1);
digitalWrite(WaistSpeed, 0);
delay(t1);
//Bend Up
Serial.println("Up");
digitalWrite(WaistDir, LOW);
digitalWrite(WaistSpeed, Slow);
delay (t1);
digitalWrite(WaistSpeed, Fast);
delay (t2);
digitalWrite(WaistSpeed, Slow);
delay(t1);
digitalWrite(WaistSpeed, 0);
delay(t1);
//Test Right Wheel
Serial.println("Right Wheel");
//Right Wheel Foward'
Serial.println("Foward");
digitalWrite(RightWheelDir, HIGH);
digitalWrite(RightWheelSpeed, Slow);
delay (t1);
digitalWrite(RightWheelSpeed, Fast);
delay (t2);
digitalWrite(RightWheelSpeed, Slow);
delay(t1);
digitalWrite(RightWheelSpeed, 0);
delay(t1);
//Right Wheel Backward
Serial.println("Backward");
digitalWrite(RightWheelDir, LOW);
digitalWrite(RightWheelSpeed, Slow);
delay (t1);
digitalWrite(RightWheelSpeed, Slow);
delay (t2);
digitalWrite(RightWheelSpeed, Slow);
delay (t1);
digitalWrite(RightWheelSpeed, 0);
delay(t2);
//Test Left Wheel
Serial.println("Left Wheel");
//Left Wheel Foward
Serial.println("Foward");
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(LeftWheelSpeed, Slow);
delay (t1);
digitalWrite(LeftWheelSpeed, Slow);
delay (t2);
digitalWrite(LeftWheelSpeed, Slow);
delay(t1);
digitalWrite(LeftWheelSpeed, 0);
delay(t1);
//Left Wheel Back
Serial.println("Backward");
digitalWrite(LeftWheelDir, LOW);
digitalWrite(LeftWheelSpeed, Slow);
delay (t1);
digitalWrite(LeftWheelSpeed, Slow);
delay (t2);
digitalWrite(LeftWheelSpeed,Slow);
delay(t1);
digitalWrite(LeftWheelSpeed, 0);
delay(t1);
//FANCY TESTS//
Serial.println("FANCY TESTS");
//Touch Floor
//Touch Sky
//Home Position
//Spin Left
//Spin Right
//Go Foward
//Go Backward
//Robot Dance
Serial.println("Repeat....");
}
Too Loud
Some motors fit inside the inner-tube, like this stepper.
For the drill motors you can jab rubber between the motors and the brackets/plywood.
Shoulder - With Two Hinges
We can do slightly better by building a super hinge, out of two hinges. Goal is to get up/down and side/side.
Here is a video of the 2 way hinge:
Mount Shoulder Motor - Cut Screw Rod to Length
- Attach everything with motor loose
- Raise and lower arm to find good motor position
- Mount motor - had to make L bracket
- Find max/min heights on threaded rod
- Cut rod (note: best cut ever)
- Re-attach rod
SpeakJet - Arduino Shield From SparkFun
Here is the assembly and testing of the Voice Box Shield from SparkFun.
This is pretty easy - however, it is not what I thought it would be. I'd expected to be able to spew out words straight from regular text. This can be done, but you need a second chip that does text-to-speech. As is, there is a table of phonetic sounds that can be strung together to make words. That should be fine, but I was hoping for really really easy.
Anyway - solder on some stackable headers and attach a speaker.
Load up some sample code and see how it sounds!
Here is molly running it -
/////////ARDUINO CODE//////////
/*
Voice Box Demo Sketch
Written by Ryan Owens
SparkFun Electronics
Uses the Voice Box Shield from SparkFun to send the message "All your base are belong to us" and a series
of robot sounds to the SpeakJet chip on the shield.
A speaker can be plugged directly into the SPK+ and - pins on the shield.
*/
//Soft serial library used to send serial commands on pin 2 instead of regular serial pin.
#include
//Define the Pin Numbers for the sketch.
#define E0 5
#define E1 6
#define E2 7
#define E3 8
#define E4 9
#define E5 10
#define E6 11
#define E7 12
#define RDY 13
#define RES 3
#define SPK 4
#define txPin 2
//Create a SoftSerial Objet
SoftwareSerial speakjet = SoftwareSerial(0, txPin);
//The message array contains the command for sounds to be sent in order to inunciate the words "All your base belong to us." Check the SpeakJet Manual for more information
//on producing words
//All Your Base Are Belong to us
char message[] = {20, 96, 21, 114, 22, 88, 23, 5, 8, 135, 8, 146, 5, 128, 153, 5, 170, 154, 8, 188, 5, 152, 5, 170, 8,128,146,8,135,8,144,5,8,191,162,5,8,134,187};
//The sounds array contains the commands to send robot sounds to the SpeakJet chip.
char sounds[] = {200, 201, 202, 203, 220, 221, 222};
void setup()
{
//Configure the pins for the SpeakJet module
pinMode(txPin, OUTPUT);
pinMode(SPK, INPUT);
//Set up a serial port to talk from Arduino to the SpeakJet module on pin 3.
speakjet.begin(9600);
//Configure the Ready pin as an input
pinMode(RDY, INPUT);
//Configure Reset line as an output
pinMode(RES, OUTPUT);
//Configure all of the Event pins as outputs from Arduino, and set them Low.
for(int i=E0; i<=E7; i++)
{
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
}
//All I/O pins are configured. Reset the SpeakJet module
digitalWrite(RES, LOW);
delay(100);
digitalWrite(RES, HIGH);
}
void loop()
{
//Send "All Your Base are Belong to Us" to the SpeakJet module
speakjet.print(message);
//Wait before sending the next string.
delay(3000);
//Send the robotic sounds to the module.
speakjet.print(sounds);
while(1);
}
Get Ready for a Test Run of Motors
In preparation:
- Attach Arduino Vin to 18v battery - allows it to run without being plugged into USB port
- Fasten individual circuit boards to the wooden board, with screws and nails (do not smash stuff)
- Take some 'before' photos - so it will be easier to rebuild after the tests
Robot Motor Test - Gone Awry
Video - First Try -
1 - Motors are running at very fast
2 - Burns out the mosfet controlling the waist motor
Video 2 - Try turning off and on again
1 - Motors are running at very fast
Do you see why?
I have run all the speeds as digital outputs, so we are just getting 0Volts or 18Volts going to the motor.
So wherever there is something like this:
digitalWrite(RightArmSpeed, Fast);
it should be;
analogWrite(RightArmSpeed, Fast);
the analogWrite command sends what is basically a variable voltage between 0 and 5V (with 0 = 0V; and 255 = 5V)- running this through the mosfet gives an output with 0 = 0V; and 255 = 18V.
So - below is the code fixed. The speed values are now in the range of 0-255, and can be changed at the top of the code.
2 - Burns out the mosfet controlling the waist motor
Two problems here - the first is that we are not properly controlling power to the motor - but that should now be fixed. The other issue is that it is really hard to lift up the back of the robot like this - so the motor is drawing a lot of current to get the robot to bend at the waist. We should be able to fix this mechanically by: building a better linkage; adding springs or weights to balance the upper body, or something else..... I feel like there will be a whole long step about fixing this part. I will ignore the problem for now.
///////// Arduino Code to Control Speed with analogWrite function ////////
// Direction low = towards body or Foward
//Direction High = away from body or Backward
int RightArmDir = 2;
int RightArmSpeed = 3;
int LeftArmDir = 4;
int LeftArmSpeed = 5;
int WaistDir = 7;
int WaistSpeed = 6;
int RightWheelDir = 8;
int RightWheelSpeed = 9;
int LeftWheelDir = 12;
int LeftWheelSpeed = 10;
int Slow = 100;
int Fast = 200;
int t1 = 500;
int t2 = 100;
int WheelSpeed =120;
void setup() {
pinMode(RightArmDir, OUTPUT);
pinMode(RightArmSpeed, OUTPUT);
pinMode(LeftArmDir, OUTPUT);
pinMode(LeftArmSpeed, OUTPUT);
pinMode(WaistDir, OUTPUT);
pinMode(WaistSpeed, OUTPUT);
pinMode(RightWheelDir, OUTPUT);
pinMode(RightWheelSpeed, OUTPUT);
pinMode(LeftWheelDir, OUTPUT);
pinMode(LeftWheelSpeed, OUTPUT);
Serial.begin(9600);
}
void loop() {
//BASIC TESTS//
Serial.println("BASIC TESTS");
// Test Right Arm
Serial.println("Right Arm");
//Right Arm Up
Serial.println("Up");
digitalWrite(RightArmDir, HIGH);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed,Fast);
delay (t2);
analogWrite(RightArmSpeed,Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(t1);
//Right Arm Down
Serial.println("Down");
digitalWrite(RightArmDir, LOW);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed, Fast);
delay (t2);
analogWrite(RightArmSpeed, Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(t1);
// Test Left Arm
Serial.println("Left Arm");
//Left Arm Up
Serial.println("Up");
digitalWrite(LeftArmDir, HIGH);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, Fast);
delay (t2);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, 0);
delay(t1);
//Left Arm Down
Serial.println("Down");
digitalWrite(LeftArmDir, LOW);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, Fast);
delay (t2);
analogWrite(LeftArmSpeed,Slow);
delay(t1);
analogWrite(LeftArmSpeed, 0);
delay(t1);
// Test Waist
Serial.println("Waist");
//Bend Down
Serial.println("Down");
digitalWrite(WaistDir, HIGH);
analogWrite(WaistSpeed, Slow);
delay (2 * t1);
analogWrite(WaistSpeed, Fast);
delay (4 * t2);
analogWrite(WaistSpeed, Slow);
delay(2 * t1);
analogWrite(WaistSpeed, 0);
delay(t1);
//Bend Up
Serial.println("Up");
digitalWrite(WaistDir, LOW);
analogWrite(WaistSpeed, Slow);
delay (2 * t1);
analogWrite(WaistSpeed, Fast);
delay (4 * t2);
analogWrite(WaistSpeed, Slow);
delay(2 * t1);
analogWrite(WaistSpeed, 0);
delay(t1);
//Test Right Wheel
Serial.println("Right Wheel");
//Right Wheel Foward'
Serial.println("Foward");
digitalWrite(RightWheelDir, HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(RightWheelSpeed, 0);
delay(t1);
//Right Wheel Backward
Serial.println("Backward");
digitalWrite(RightWheelDir, LOW);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(RightWheelSpeed, 0);
delay(t2);
//Test Left Wheel
Serial.println("Left Wheel");
//Left Wheel Foward
Serial.println("Foward");
digitalWrite(LeftWheelDir, HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
delay(t1);
//Left Wheel Back
Serial.println("Backward");
digitalWrite(LeftWheelDir, LOW);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
delay(t1);
//FANCY TESTS//
Serial.println("FANCY TESTS");
//Touch Floor
//Touch Sky
//Home Position
//Spin Left
//Spin Right
//Go Foward
Serial.println("Go Foward");
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(RightWheelDir,HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed, 0);
delay(t1);
//Go Backward
//Robot Dance
Serial.println("Repeat....");
}// Direction low = towards body or Foward
//Direction High = away from body or Backward
int RightArmDir = 2;
int RightArmSpeed = 3;
int LeftArmDir = 4;
int LeftArmSpeed = 5;
int WaistDir = 7;
int WaistSpeed = 6;
int RightWheelDir = 8;
int RightWheelSpeed = 9;
int LeftWheelDir = 12;
int LeftWheelSpeed = 10;
int Slow = 100;
int Fast = 200;
int t1 = 500;
int t2 = 100;
int WheelSpeed =120;
void setup() {
pinMode(RightArmDir, OUTPUT);
pinMode(RightArmSpeed, OUTPUT);
pinMode(LeftArmDir, OUTPUT);
pinMode(LeftArmSpeed, OUTPUT);
pinMode(WaistDir, OUTPUT);
pinMode(WaistSpeed, OUTPUT);
pinMode(RightWheelDir, OUTPUT);
pinMode(RightWheelSpeed, OUTPUT);
pinMode(LeftWheelDir, OUTPUT);
pinMode(LeftWheelSpeed, OUTPUT);
Serial.begin(9600);
}
void loop() {
//BASIC TESTS//
Serial.println("BASIC TESTS");
// Test Right Arm
Serial.println("Right Arm");
//Right Arm Up
Serial.println("Up");
digitalWrite(RightArmDir, HIGH);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed,Fast);
delay (t2);
analogWrite(RightArmSpeed,Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(t1);
//Right Arm Down
Serial.println("Down");
digitalWrite(RightArmDir, LOW);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed, Fast);
delay (t2);
analogWrite(RightArmSpeed, Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(t1);
// Test Left Arm
Serial.println("Left Arm");
//Left Arm Up
Serial.println("Up");
digitalWrite(LeftArmDir, HIGH);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, Fast);
delay (t2);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, 0);
delay(t1);
//Left Arm Down
Serial.println("Down");
digitalWrite(LeftArmDir, LOW);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, Fast);
delay (t2);
analogWrite(LeftArmSpeed,Slow);
delay(t1);
analogWrite(LeftArmSpeed, 0);
delay(t1);
// Test Waist
Serial.println("Waist");
//Bend Down
Serial.println("Down");
digitalWrite(WaistDir, HIGH);
analogWrite(WaistSpeed, Slow);
delay (2 * t1);
analogWrite(WaistSpeed, Fast);
delay (4 * t2);
analogWrite(WaistSpeed, Slow);
delay(2 * t1);
analogWrite(WaistSpeed, 0);
delay(t1);
//Bend Up
Serial.println("Up");
digitalWrite(WaistDir, LOW);
analogWrite(WaistSpeed, Slow);
delay (2 * t1);
analogWrite(WaistSpeed, Fast);
delay (4 * t2);
analogWrite(WaistSpeed, Slow);
delay(2 * t1);
analogWrite(WaistSpeed, 0);
delay(t1);
//Test Right Wheel
Serial.println("Right Wheel");
//Right Wheel Foward'
Serial.println("Foward");
digitalWrite(RightWheelDir, HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(RightWheelSpeed, 0);
delay(t1);
//Right Wheel Backward
Serial.println("Backward");
digitalWrite(RightWheelDir, LOW);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(RightWheelSpeed, 0);
delay(t2);
//Test Left Wheel
Serial.println("Left Wheel");
//Left Wheel Foward
Serial.println("Foward");
digitalWrite(LeftWheelDir, HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
delay(t1);
//Left Wheel Back
Serial.println("Backward");
digitalWrite(LeftWheelDir, LOW);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
delay(t1);
//FANCY TESTS//
Serial.println("FANCY TESTS");
//Touch Floor
//Touch Sky
//Home Position
//Spin Left
//Spin Right
//Go Foward
Serial.println("Go Foward");
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(RightWheelDir,HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed, 0);
delay(t1);
//Go Backward
//Robot Dance
Serial.println("Repeat....");
}
Still Messed Up
You will notice that instead of doing an orderly - right arm, left arm, waist, right wheel, left wheel, both wheels
It is doing something like - right arm, left arm, wheel, right arm, left arm, right wheel, left wheel, right arm, right arm, left arm, right arm....
What is happening?
Well, one problem is that the program is restarting before it is finished. The Arduino is probably being reset, either because power is dropping when a motor kicks on, or just due to noise (probably both)/. There is porbably noise on the digital lines also, enough to randomly toggle the relays and stuff. So we will have some fixing to do.
Do We Need Separate Power Supply for Arduino?
Easiest thing to do is to disconnect the positve 18V line from the arduino Vin, and plug the Arduino USB into a computers USB port. This will give 5V power to the arduino. We have to leave the grounds attached to each other (0V from battery to ground on USB/Arduino). There is some risk of breaking the computers USB port.
This also lets us monitor the program by getting the serial ouput telling us which step the program is at.
Here is video.
Since this does seem to solve alot of problems, it will be very useful to add a separate power supply for the arduino. The Arduino Uno (and many others) have a built in 5Volt regulater (this is what allows the arduino to run of the 18V battery) - an input between 5 and 12Volts will be good. For example a 9V battery with a plug - or 4 AA batteries (6V).
********* IMPORTANT NOTE***********
Plug does not work right on this board - seems to be converting to 3.3V - or just not right.
So: CONNECT POWER TO Vin and GROUND
Check 5V on Arduino (from the regulator - "5V" pin) with meter
************************************
Take It Outside
I had connected the 6V battery pack to the jack on the arduino - but the jack was knocking the power way down to 3V.
Re-wiring to Vin fixes the problem.
Also - it is obvious that the wheels will need to be redone
Waist Linkage Redo
-moved motor a little
-added L bracket to try and get more leverage (had to make L bracket)
-added small link to give it some slack
-added a screw to keep the link from locking up when robot is bent all the way down
-also - replace mosfet driving waist motor (second time - should add fuse, or something better)
Test Code Redo - Using Function
The test code is getting long and confusing.
As it is now, every action needs its own block of code with all the details in it. So, repeating an action needs a whole 'nother copy of the code.
An easy way to deal with this is to make each action into a 'Function' then call the function from the main loop.
The new code is below. I have taken everything that was in the main loop and moved it down to the end. Then I made each action into its own function, with its own name.
Like this (the changes are in bold):
void RightArmDown(){
//Right Arm Down
Serial.println("Right Arm Down");
digitalWrite(RightArmDir, LOW);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed, Fast);
delay (2*t2);
analogWrite(RightArmSpeed, Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(2*t1);
}
Now - in the main loop, you can replace the long section of code with the name of the function:
void RightArmDown();
So - that makes things a little easier.
Below is the newly organized code (copied as html...)
A video with it working well:
[1318]
////////////////////// ARDUINO CODE //////////////////////////
////// Robot test with little routines made into functions////// /////VARIABLES///////// // Direction low = towards body or Foward //Direction High = away from body or Backward int RightArmDir = 2; int RightArmSpeed = 3; int LeftArmDir = 4; int LeftArmSpeed = 5; int WaistDir = 7; int WaistSpeed = 6; int RightWheelDir = 8; int RightWheelSpeed = 9; int LeftWheelDir = 12; int LeftWheelSpeed = 10; int Slow = 100; int Fast = 200; int t1 = 100; int t2 = 500; int WheelSpeed =120; ///////// SETUP ///////// void setup() { pinMode(RightArmDir, OUTPUT); pinMode(RightArmSpeed, OUTPUT); pinMode(LeftArmDir, OUTPUT); pinMode(LeftArmSpeed, OUTPUT); pinMode(WaistDir, OUTPUT); pinMode(WaistSpeed, OUTPUT); pinMode(RightWheelDir, OUTPUT); pinMode(RightWheelSpeed, OUTPUT); pinMode(LeftWheelDir, OUTPUT); pinMode(LeftWheelSpeed, OUTPUT); Serial.begin(9600); } //////// MAIN LOOP /////// void loop() { Serial.println("Start...."); delay(2000); RightArmUp(); RightArmDown(); LeftArmUp(); LeftArmDown(); WaistBendDown(); WaistBendUp(); Foward(); Backward(); Spin(); Serial.println("Repeat...."); } /////////////////////////////////////////////// ///////// BASIC FUNCTIONS /////////////////// /////////////////////////////////////////////// void RightArmUp(){ // Test Right Arm Serial.println("Right Arm"); //Right Arm Up Serial.println("Up"); digitalWrite(RightArmDir, HIGH); analogWrite(RightArmSpeed, Slow); delay (t1); analogWrite(RightArmSpeed,Fast); delay (2*t2); analogWrite(RightArmSpeed,Slow); delay(t1); analogWrite(RightArmSpeed, 0); delay(t1); } void RightArmDown(){ //Right Arm Down Serial.println("Right Arm Down"); digitalWrite(RightArmDir, LOW); analogWrite(RightArmSpeed, Slow); delay (t1); analogWrite(RightArmSpeed, Fast); delay (2*t2); analogWrite(RightArmSpeed, Slow); delay(t1); analogWrite(RightArmSpeed, 0); delay(2*t1); } void LeftArmUp(){ // Test Left Arm Serial.println("Left Arm Up"); //Left Arm Up digitalWrite(LeftArmDir, HIGH); analogWrite(LeftArmSpeed, Slow); delay (t1); analogWrite(LeftArmSpeed, Fast); delay (2*t2); analogWrite(LeftArmSpeed, Slow); delay (t1); analogWrite(LeftArmSpeed, 0); delay(t1); } void LeftArmDown(){ //Left Arm Down Serial.println("Left Arm Down"); digitalWrite(LeftArmDir, LOW); analogWrite(LeftArmSpeed, Slow); delay (t1); analogWrite(LeftArmSpeed, Fast); delay (2*t2); analogWrite(LeftArmSpeed,Slow); delay(t1); analogWrite(LeftArmSpeed, 0); delay(2*t1); } void WaistBendDown(){ // Test Waist Serial.println("Waist Bend Down"); digitalWrite(WaistDir, HIGH); analogWrite(WaistSpeed, Slow); delay (t1); analogWrite(WaistSpeed, Fast); delay (2*t2); analogWrite(WaistSpeed, Slow); delay(t1); analogWrite(WaistSpeed, 0); delay(t1); } void WaistBendUp(){ //Bend Up Serial.println("Up"); digitalWrite(WaistDir, LOW); analogWrite(WaistSpeed, Slow); delay (t1); analogWrite(WaistSpeed, Fast); delay (2*t2); analogWrite(WaistSpeed, Slow); delay(t1); analogWrite(WaistSpeed, 0); delay(2*t1); } void Spin(){ Serial.println("SPIN"); digitalWrite(LeftWheelDir, LOW); digitalWrite(RightWheelDir,HIGH); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); delay(2*t1); } void Foward(){ Serial.println("Go Foward"); digitalWrite(LeftWheelDir, HIGH); digitalWrite(RightWheelDir,HIGH); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); delay(2*t1); } void Backward(){ Serial.println("Go Backward"); digitalWrite(LeftWheelDir, LOW); digitalWrite(RightWheelDir,LOW); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); delay(2*t1); }
Move to the Floor - Wheels Bad
The wheels do not work well.
Video:
[1319]
I tried changing the wheel speed - but it is still no good.
Video:
[1320]
Wheel Redo
A soluction that works okay - is to add casters to the base of the robot. The casters will support most of the weight and the drills will just have to rotate the wheels.
I was lucky to have a heavy duty 5 wheel caster thing lying around.
To align the drill - I mounted them to a peice of plywood, then bolted the plywood to the caster thing. I've attempted to spring load the wheels, so that they will always make contact with the floor, but this does not really seem to do anything.
Better Wheels and Base
[1333]
The wheels are still not great, but at least we have some ability to move the robot around.
Problems:
- the casters resist changes in direction, because they have to spin
- rolls after stopping - try adding a short motor reverse to halt the wheels ( ie. wheels forward ->reduce speed to zero -> wheels backward for a moment, maybe at a low speed, just enough to stop momentum)
Test Code - Control From PC Via USB
The code is below:
Now the following commands control the motions. They are sent using the serial monitor. Using all lower case (it is actually the ascii codes for the letters that are sent, so case matters)
f = forward
b = backward
r = right arm up
t = right arm down
w = left arm up
e = left arm down
z = waist bend down
x = waist bend up
/////////////////////////////Arduino Code //////////////////////////////
////// Robot test with little routines made into functions////// ////// Added serial control /////VARIABLES///////// // Direction low = towards body or Foward //Direction High = away from body or Backward int RightArmDir = 2; int RightArmSpeed = 3; int LeftArmDir = 4; int LeftArmSpeed = 5; int WaistDir = 7; int WaistSpeed = 6; int RightWheelDir = 8; int RightWheelSpeed = 9; int LeftWheelDir = 12; int LeftWheelSpeed = 10; int Slow = 100; int Fast = 200; int t1 = 200; int t2 = 1000; int WheelSpeed =75; int incomingByte; ///////// SETUP ///////// void setup() { pinMode(RightArmDir, OUTPUT); pinMode(RightArmSpeed, OUTPUT); pinMode(LeftArmDir, OUTPUT); pinMode(LeftArmSpeed, OUTPUT); pinMode(WaistDir, OUTPUT); pinMode(WaistSpeed, OUTPUT); pinMode(RightWheelDir, OUTPUT); pinMode(RightWheelSpeed, OUTPUT); pinMode(LeftWheelDir, OUTPUT); pinMode(LeftWheelSpeed, OUTPUT); Serial.begin(9600); } //////// MAIN LOOP /////// void loop() { Serial.println("...."); delay(2000); if(Serial.available()>0){ incomingByte = Serial.read(); switch(incomingByte){ case 'f': Foward(); break; case 'b': Backward(); break; case 'r': RightArmUp(); break; case 't': RightArmDown(); break; case 'w': LeftArmUp(); break; case 'e': LeftArmDown(); break; case 'z': WaistBendDown(); break; case 'x': WaistBendUp(); break; } } } /////////////////////////////////////////////// ///////// BASIC FUNCTIONS /////////////////// /////////////////////////////////////////////// void RightArmUp(){ // Test Right Arm Serial.println("Right Arm"); //Right Arm Up Serial.println("Up"); digitalWrite(RightArmDir, HIGH); analogWrite(RightArmSpeed, Slow); delay (t1); analogWrite(RightArmSpeed,Fast); delay (2*t2); analogWrite(RightArmSpeed,Slow); delay(t1); analogWrite(RightArmSpeed, 0); delay(t1); } void RightArmDown(){ //Right Arm Down Serial.println("Right Arm Down"); digitalWrite(RightArmDir, LOW); analogWrite(RightArmSpeed, Slow); delay (t1); analogWrite(RightArmSpeed, Fast); delay (2*t2); analogWrite(RightArmSpeed, Slow); delay(t1); analogWrite(RightArmSpeed, 0); delay(2*t1); } void LeftArmUp(){ // Test Left Arm Serial.println("Left Arm Up"); //Left Arm Up digitalWrite(LeftArmDir, HIGH); analogWrite(LeftArmSpeed, Slow); delay (t1); analogWrite(LeftArmSpeed, Fast); delay (2*t2); analogWrite(LeftArmSpeed, Slow); delay (t1); analogWrite(LeftArmSpeed, 0); delay(t1); } void LeftArmDown(){ //Left Arm Down Serial.println("Left Arm Down"); digitalWrite(LeftArmDir, LOW); analogWrite(LeftArmSpeed, Slow); delay (t1); analogWrite(LeftArmSpeed, Fast); delay (2*t2); analogWrite(LeftArmSpeed,Slow); delay(t1); analogWrite(LeftArmSpeed, 0); delay(2*t1); } void WaistBendDown(){ // Test Waist Serial.println("Waist Bend Down"); digitalWrite(WaistDir, HIGH); analogWrite(WaistSpeed, Slow); delay (t1); analogWrite(WaistSpeed, Fast); delay (2*t2); analogWrite(WaistSpeed, Slow); delay(t1); analogWrite(WaistSpeed, 0); delay(t1); } void WaistBendUp(){ //Bend Up Serial.println("Up"); digitalWrite(WaistDir, LOW); analogWrite(WaistSpeed, Slow); delay (t1); analogWrite(WaistSpeed, Fast); delay (2*t2); analogWrite(WaistSpeed, Slow); delay(t1); analogWrite(WaistSpeed, 0); delay(2*t1); } void Spin(){ Serial.println("SPIN"); digitalWrite(LeftWheelDir, LOW); digitalWrite(RightWheelDir,HIGH); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); } void Spin2(){ Serial.println("SPIN2"); digitalWrite(LeftWheelDir, HIGH); digitalWrite(RightWheelDir,LOW); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); } void Foward(){ Serial.println("Go Foward"); digitalWrite(LeftWheelDir, HIGH); digitalWrite(RightWheelDir,HIGH); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); } void Backward(){ Serial.println("Go Backward"); digitalWrite(LeftWheelDir, LOW); digitalWrite(RightWheelDir,LOW); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay (t1); analogWrite(RightWheelSpeed, WheelSpeed); analogWrite(LeftWheelSpeed, WheelSpeed); delay (t2); analogWrite(RightWheelSpeed, WheelSpeed/2); analogWrite(LeftWheelSpeed, WheelSpeed/2); delay(t1); analogWrite(LeftWheelSpeed, 0); analogWrite(RightWheelSpeed, 0); }
Make One Arm Good - Right Handed Robot
Using stepper motors and servos we can get better motion control than by using DC motors (hopefully)
Servos are pretty easy - you just tell them where to go, and they go.
Steppers are a little harder - they have alot of wires.
I will try using a motor shield from Adafruit
It controls 2 servos and 4 dc motors
or
2 servos and 2 stepper motors
Will try:
- 1 stepper: shoulder out (abduction)
- 2 stepper: elbow flex
- 1 servo: wrist
- 2 servo: hand
lots of info: http://www.ladyada.net/make/mshield/use.html
Shoulder - 1 Stepper
- Using stepper motor to pull a string
- Shaft collar with set screw used to mount string to stepper
- Add spring to return arm to down position
Blue:
Black:
Green:
Red:
Elbow Motor - Stepper 2
http://www.adafruit.com/products/168
It has 6 leads:
Green + Read : ground
Brown:M1
Black: M1 (other terminal)
Orange: M2
Yellow: M2 (other terminal)
Will need a new library for this: http://www.ladyada.net/make/mshield/download.html
load that up and run.
Video:
Sample code:
////////////////////////////////
////// http://www.ladyada.net/make/mshield/use.html ///////////////
/////////////////////////
///////////// Cut/paste -- change motor port as needed
/////////////////////////////////////////////////////////////////////////////////////////////
#include <AFMotor.h>
AF_Stepper motor(48, 1); //48 steps per roation - on motor port 1
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Stepper test!");
motor.setSpeed(10); // 10 rpm
motor.step(100, FORWARD, SINGLE);
motor.release();
delay(1000);
}
void loop() {
motor.step(100, FORWARD, SINGLE);
motor.step(100, BACKWARD, SINGLE);
motor.step(100, FORWARD, DOUBLE);
motor.step(100, BACKWARD, DOUBLE);
motor.step(100, FORWARD, INTERLEAVE);
motor.step(100, BACKWARD, INTERLEAVE);
motor.step(100, FORWARD, MICROSTEP);
motor.step(100, BACKWARD, MICROSTEP);
}
Put the Skin (cardboard) Back On
Cut and tape as needed.
Good for kids.
Used some deck screws.
Neck - Servo to Move Head
The axle pokes through the cardboard, then a plastic gear is added. I've taped a a piece of carboard to the plastic gear. The head will be taped to this.
Servos are easy with arduino.
3 wires from servo -
Yellow - position - attaches to pin 11 (pwm) on arduino
Red - 5V - to 5V arduino supply
Black - ground - to arduino ground.
The only tricky part is to figure out the angles that are useful.
Turned out to be:
5deg - faces left
80deg - faces forward
155 deg - faces left
This will be different depending on how the servo is mounted.
I've adapted this servo example code to output the position via USB.
Also the movements are all in a function called moveHead()
Should be able to mash this in with the other test code and run it from the serial port.
Video:
[neck]
Video:
[head]
////////////////////// ARDUINO CODE /////////////////////
// Sweep
// by BARRAGAN <http://barraganstudio.com>
// This example code is in the public domain.
/////pin 9 to pin11
//// changed angles
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created
int pos = 0; // variable to store the servo position
int posFront = 81;
void setup()
{
myservo.attach(11); // attaches the servo on pin 11 to the servo object
Serial.begin(9600);
}
void loop()
{
moveHead(); // call the function move head
}
void moveHead(){ //create function move head// head go back anbd forth
for(pos = 5; pos < 145; pos += 1) //goes from 5 to 145degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
Serial.println(pos);
delay(15); // waits 15ms for the servo to reach the position
if(pos == posFront){
delay(600);
}
}
for(pos = 145; pos>=5; pos-=1) // goes from 145 degrees to 5 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
if(pos == posFront){
delay(600);
}
}
}
Added MoveHead() to the Rest of the Serial Test Code
serial commands added:
'h' - to move the head - runs through full sweep
's' - spin one way (function was already there, but did not have a case)
'd' - spin the other way (function was already there, but did not have a case)
This code should be made shorter but here it is:
video
[allMoves
//////////////////////////////// ARDUINO CODE//////////////////////////////////
////// Robot test with little routines made into functions//////
//// added head moving ////
/////motor VARIABLES/////////
// Direction low = towards body or Foward
//Direction High = away from body or Backward
int RightArmDir = 2;
int RightArmSpeed = 3;
int LeftArmDir = 4;
int LeftArmSpeed = 5;
int WaistDir = 7;
int WaistSpeed = 6;
int RightWheelDir = 8;
int RightWheelSpeed = 9;
int LeftWheelDir = 12;
int LeftWheelSpeed = 10;
int Slow = 100;
int Fast = 200;
int t1 = 200; //time at slow speed
int t2 = 1000; //time at fast speed
int tBreak = 100; //time to stop motor by reversing dir
int WheelSpeed =75;
int breakSpeed = 10;
int bendSpeed = 255;
int incomingByte;
///////////// head variables
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int pos = 80;
int posFront = 80;
///////// SETUP /////////
void setup() {
pinMode(RightArmDir, OUTPUT);
pinMode(RightArmSpeed, OUTPUT);
pinMode(LeftArmDir, OUTPUT);
pinMode(LeftArmSpeed, OUTPUT);
pinMode(WaistDir, OUTPUT);
pinMode(WaistSpeed, OUTPUT);
pinMode(RightWheelDir, OUTPUT);
pinMode(RightWheelSpeed, OUTPUT);
pinMode(LeftWheelDir, OUTPUT);
pinMode(LeftWheelSpeed, OUTPUT);
myservo.attach(11); // attaches the servo on pin 11 to the servo object
Serial.begin(9600);
}
//////// MAIN LOOP ///////
void loop() {
Serial.println("....");
delay(400);
if(Serial.available()>0){
incomingByte = Serial.read();
switch(incomingByte){
case 'f':
Foward();
break;
case 'b':
Backward();
break;
case 'r':
RightArmUp();
break;
case 't':
RightArmDown();
break;
case 'w':
LeftArmUp();
break;
case 'e':
LeftArmDown();
break;
case 'z':
WaistBendDown();
break;
case 'x':
WaistBendUp();
break;
case 'h':
MoveHead();
break;
case 's':
Spin();
break;
case'd':
Spin2();
break;
}
}
}
///////////////////////////////////////////////
///////// BASIC FUNCTIONS ///////////////////
///////////////////////////////////////////////
void RightArmUp(){
// Test Right Arm
Serial.println("Right Arm");
//Right Arm Up
Serial.println("Up");
digitalWrite(RightArmDir, HIGH);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed,Fast);
delay (1.8*t2);
analogWrite(RightArmSpeed,Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(t1);
}
void RightArmDown(){
//Right Arm Down
Serial.println("Right Arm Down");
digitalWrite(RightArmDir, LOW);
analogWrite(RightArmSpeed, Slow);
delay (t1);
analogWrite(RightArmSpeed, Fast);
delay (1.8*t2);
analogWrite(RightArmSpeed, Slow);
delay(t1);
analogWrite(RightArmSpeed, 0);
delay(2*t1);
}
void LeftArmUp(){
// Test Left Arm
Serial.println("Left Arm Up");
//Left Arm Up
digitalWrite(LeftArmDir, HIGH);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, Fast);
delay (2*t2);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, 0);
delay(t1);
}
void LeftArmDown(){
//Left Arm Down
Serial.println("Left Arm Down");
digitalWrite(LeftArmDir, LOW);
analogWrite(LeftArmSpeed, Slow);
delay (t1);
analogWrite(LeftArmSpeed, Fast);
delay (2*t2);
analogWrite(LeftArmSpeed,Slow);
delay(t1);
analogWrite(LeftArmSpeed, 0);
delay(2*t1);
}
void WaistBendDown(){
// Test Waist
Serial.println("Waist Bend Down");
digitalWrite(WaistDir, HIGH);
analogWrite(WaistSpeed, Slow);
delay (t1);
analogWrite(WaistSpeed, bendSpeed);
delay (2*t2);
analogWrite(WaistSpeed, Slow);
delay(t1);
analogWrite(WaistSpeed, 0);
delay(t1);
}
void WaistBendUp(){
//Bend Up
Serial.println("Up");
digitalWrite(WaistDir, LOW);
analogWrite(WaistSpeed, Slow);
delay (t1);
analogWrite(WaistSpeed, bendSpeed);
delay (2*t2);
analogWrite(WaistSpeed, Slow);
delay(t1);
analogWrite(WaistSpeed, 0);
delay(2*t1);
}
void Spin(){
Serial.println("SPIN");
digitalWrite(LeftWheelDir, LOW);
digitalWrite(RightWheelDir,HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
analogWrite(LeftWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed, 0);
delay(t1);
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(RightWheelDir,LOW);
analogWrite(LeftWheelSpeed, breakSpeed);
analogWrite(RightWheelSpeed, breakSpeed);
delay(tBreak);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed,0);
}
void Spin2(){
Serial.println("SPIN2");
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(RightWheelDir,LOW);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
analogWrite(LeftWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed, 0);
delay(t1);
digitalWrite(LeftWheelDir, LOW);
digitalWrite(RightWheelDir,HIGH);
analogWrite(LeftWheelSpeed, breakSpeed);
analogWrite(RightWheelSpeed,breakSpeed);
delay(tBreak);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed,0);
}
void Foward(){
Serial.println("Go Foward");
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(RightWheelDir,HIGH);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
analogWrite(LeftWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed, 0);
delay(t1);
digitalWrite(LeftWheelDir, LOW);
digitalWrite(RightWheelDir,LOW);
analogWrite(LeftWheelSpeed, breakSpeed);
analogWrite(RightWheelSpeed,breakSpeed);
delay(tBreak);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed,0);
}
void Backward(){
Serial.println("Go Backward");
digitalWrite(LeftWheelDir, LOW);
digitalWrite(RightWheelDir,LOW);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay (t1);
analogWrite(RightWheelSpeed, WheelSpeed);
analogWrite(LeftWheelSpeed, WheelSpeed);
delay (t2);
analogWrite(RightWheelSpeed, WheelSpeed/2);
analogWrite(LeftWheelSpeed, WheelSpeed/2);
delay(t1);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed, 0);
delay(t1);
digitalWrite(LeftWheelDir, HIGH);
digitalWrite(RightWheelDir,HIGH);
analogWrite(LeftWheelSpeed, breakSpeed);
analogWrite(RightWheelSpeed,breakSpeed);
delay(tBreak);
analogWrite(LeftWheelSpeed, 0);
analogWrite(RightWheelSpeed,0);
}
////////////move head////////////
void MoveHead(){ //create function move head// head go back anbd forth
for(pos = 5; pos < 145; pos += 1) //goes from 5 to 145degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
Serial.println(pos);
delay(15); // waits 15ms for the servo to reach the position
if(pos == posFront){
delay(600);
}
}
for(pos = 145; pos>=posFront; pos-=1) // goes from 145 degrees to front
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
if(pos == posFront){
delay(600);
}
}
}
Second Battery (or Third I Guess)
when both wheels are run at the same time - it does not work well.
I tried running each wheel of a seperate battery ---- but I did not do it correctly....
video (not much here):
Emma explains:
Video
Fabric Bend Sensors - Not Used
Robot Claw - Premade
Motor Sheild - Adafruit - Small Motors
Messed Up the Wheels
Video:
[bad wheels]
Paint!
Unlike the direction control - which has become difficult and tedious.