Arduino 6DOF Motion Platform LoRes
Arduino 6DOF Motion Platform LoRes
This instructable will show you how to create your own six degree of freedom motion platform using an Arduino microcontroller and some standard servo motors for ~$100. The
math/programming is somewhat complicated and will be covered in another instructable.
Here's a video of some basic movements just by moving a few arms (no math involved yet):
http://youtu.be/cfnBnx8Cvcg
Here is a list of the items (and potential sources) needed to complete this project:
1 Arduino Uno microcontroller (Amazon)
6 standard servos (Parallax)
12 4-40 rod ends (ServoCity)
12 conical spacers (New Era Models)
2 ft 4-40 threaded rod (McMaster-Carr)
16 4-40 11/16" flat head machine screws (McMaster-Carr)
12 4-40 nylok nuts (McMaster-Carr)
4 4-40 3/16" pan head machine screws (McMaster-Carr)
4 4-40 threaded aluminum spacers (McMaster-Carr)
1 mini breadboard (Amazon)
2 sq. ft. 1/4" thick acrylic (TAP plastics)
The only hand tools you will need are a small phillips-head screwdriver, a 1/4" wrench, and a
1/8" drill bit/drill, but you will need access to a laser cutter to cut the acrylic. I used a laser
cutter at TechShop in Menlo Park. TechShop is a DIY workshop, if you are interested check
out their website, www.techshop.ws.
Here is my code, I have commented it with descriptions of each variable, and I'll try to
explain as much as I can here about how to use it. I have also attached the .ino file if you
want to load it directly into the Arduino IDE.
Looking down at the platform with the USB port pointing away from you, the positive x axis
is to your right, positive y away from you (in line with the USB port), and positive z is up.
rotation follows the right-hand rule (point your thumb in the direction of the positive axis,
your fingers curl in the positive rotation direction), so positive x rotation will tilt the platform
back, positive y rotation will tilt the platform to the right, and positive z rotation will rotate
the platform counter-clockwise.
The platform will "rest" at a specific height (z_home)
The array pe[6] contains the information about where the platform should be:
pe[ x position , y position, z position, x rotation , y rotation , z rotation]
changing the x position, y position, and z position variables will move the platform accordingly (in inches). Changing the x roation, y rotation, and z rotation variables will rotate the
platform accordingly (in radians).
So tell the platform where you want it to be by changing the appropriate variables, then
uploading the code. Once uploaded, the platform will initialize to the "home" position and
pause for one second, then move to the desired position.
I'll talk about incorporating some type of realtime position input in another instructable.
ALternatively, you could write a loop to run the platform through a series of movements
such as this: http://youtu.be/cfnBnx8Cvcg
The code:
#include <Servo.h>
const float pi = 3.14159, theta_r = radians(48.0), theta_p = radians(23.2), theta_s[] = {-pi/3,
2*pi/3, pi, 0, pi/3, -2*pi/3},
RD = 2.395, PD = 3.3, L1 = 1.0, L2 = 4.72, z_home = 4.25, servo_min, servo_max,
servo_mult
p[2][6] = {{PD*cos(pi/6 + theta_p), PD*cos(pi/6 - theta_p), PD*cos(-(pi/2 - theta_p)),
-PD*cos(-(pi/2 - theta_p)), -PD*cos(pi/6 - theta_p), -PD*cos(pi/6 + theta_p)},
{PD*sin(pi/6 + theta_p), PD*sin(pi/6 - theta_p), PD*sin(-(pi/2 - theta_p)),
PD*sin(-(pi/2 - theta_p)), PD*sin(pi/6 - theta_p), PD*sin(pi/6 + theta_p)}},
re[2][6] = {{RD*cos(pi/6 + theta_r), RD*cos(pi/6 - theta_r), RD*cos(-(pi/2 - theta_r)),
-RD*cos(-(pi/2 - theta_r)), -RD*cos(pi/6 - theta_r), -RD*cos(pi/6 + theta_r)},
{RD*sin(pi/6 + theta_r), RD*sin(pi/6 - theta_r), RD*sin(-(pi/2 - theta_r)),
RD*sin(-(pi/2 - theta_r)), RD*sin(pi/6 - theta_r), RD*sin(pi/6 + theta_r)}};
/*
theta_r = angle between attachment points
theta_p = angle between rotation points
theta_s = orientation of the servos
RD = distance to end effector attachment points
PD = distance to servo rotation points
L1 = servo arm length
L2 = connecting arm length
z_home = default z height with servo arms horizontal
servo_min = lower limit for servo arm angle
servo_max = upper limit for servo arm angle
servo_mult = multiplier to convert to milliseconds
p = location of servo rotation points in base frame [x/y][1-6]
re = location of attachment points in end effector frame [x/y][1-6]
*/
const int servo_pin[] = {9,3, 5, 11, 6, 10}, servo_zero[6] = {1710, 1280, 1700, 1300, 1680, 1300};
/*
servo_pin = servo pin assignments,
servo_zero = zero angles for each servo (horizontal)
*/
Servo servo[6];
/*
Servos 0, 2, 4: reversed (+ = down, - = up)
Servos 1, 3, 5: normal (+ = up, - = down)
*/
void setup()
{
//Serial.begin(9600);
for(int i = 0; i < 6; i++)
{
servo[i].attach(servo_pin[i]);
servo[i].writeMicroseconds(servo_zero[i]);
}
delay(1000);
}
void loop()
{
static float pe[6] = {0,0,0,radians(0),radians(0),radians(0)}, theta_a[6], servo_pos[6],
q[3][6], r[3][6], dl[3][6], dl2[6];
/*
pe = location and orientation of end effector frame relative to the base frame [sway, surge,
heave, pitch, roll, yaw)
theta_a = angle of the servo arm
servo_pos = value written to each servo
q = position of lower mounting point of connecting link [x,y,x][1-6]
r = position of upper mounting point of connecting link
dl = difference between x,y,z coordinates of q and r
dl2 = distance between q and r
*/
Base_bottom.eps
Base_top.eps
Platform.eps