This is my hexapod robot inspired by the PhantomX AX from Trossen Robotics. The PhantomX costs $1300, which is way too expensive for my taste, so I decided to design a robot using cheap 180 degree MG996R clone 11kg-cm servos. Before starting, I added up the approximate weights of the servos, 3D printed parts, hardware, and electronics and computed the worst-case required torques for the various leg joints, which I found were within the capacity of these servos. I paid about $5 each on Amazon for my 180 degree MG996R clones in packs of 10 – mine were marked LKY62. The rest of the parts (SBEC, Mega 2560, LiPo battery, level converter, 624Z bearings, and screws) totalled about $75. I had the PS2 controller already, but you can find them used on ebay for around $25. The 3D printed parts used around 600g of PLA filament, so figure less than $10 for that. So total cost is right around $200.
Here is a demonstration video of the finished robot:
I designed the robot in Autodesk Fusion 360 and printed the parts on my Creality CR-10S 3D printer. The parts were designed with low weight in mind (thin walls, lightening holes, etc.) to maximize the chances of this working with the servos I had chosen. The PLA parts were printed a bit on the hot side (210° C) for better layer-to-layer adhesion and part strength. All parts were printed with a 0.4mm nozzle at 0.2mm layer height. Files for all the 3D printed parts are available on Thingiverse.
The following parts and quantities are printed in PLA at 30% infill, no support material is needed:
- 1 – Body Bottom Plate
- 6 – Body Risers
- 1 – Body Top Plate
- 12 – Femur Bracket End Caps
- 12 – Femur Brackets
- 18 – Servo Bearing Centers
- 6 – Tibia Base Plates
- 6 – Tibia Bracket End Caps
- 6 – Tibia Brackets
- 6 – Tibia Foot Plates
- 6 – Tibia Sides 1
- 6 – Tibia Sides 2 (Note: the tibia sides are identical, they are just printed with opposing sides down)
- 6 – Tibia Spacer Tubes
The following parts and quantities are printed in PLA at 30% infill with support:
- 1 – Receiver Holder
- 1 – SBEC Holder
- 18 – Servo Mounts
- 6 – Wire Guides
The following parts and quantities are printed in TPU at 10% infill, no support needed
- 6 – Tibia Foot Bumpers
The following images show a Fusion 360 CAD rendering of the hexapod and the leg numbering scheme (1 to 6 clockwise starting at the front right) and servo assignments to the processor pins. Note that the servo assignment information is defined in the constants declaration section in the Arduino code.
3/8″, 1/2″, and 5/8″ 4-40 machine screws and nuts and 1/4″ #2 screws from McMaster-Carr . I originally started out by tapping the holes in the plastic parts but I found that the screws worked just fine when driven into the raw holes with an electric drill-driver. The 624Z bearings fit tightly into the servo mounts, so heating the bearings before pressing them into the mount made assembly easier.
Important note: the servos need to be ‘centered’ (i.e. set to 90 degrees) before they are attached and assembled into the leg parts. The ‘select’ button on the PS2 controller provides a convenient way to set the outputs to all the servos to 90 degrees, which is the center value. This drawing from below shows the Tibia and Femur servos at their 90 degree positions for reference. The coxa servo center is just where you’d think it would be – with the bracket facing directly outward for each leg.
- a Mega 2560 processor board (Arduino clone).
- a YEP 20A HV (2~12S) SBEC to power the servos. I removed the shrink wrap and remounted it in a 3D printed base, which required resoldering the power leads. The regulator was set to output 6 volts by placing the jumper in the appropriate spot.
- a Logitech PS2 wireless controller and receiver. I carefully removed the receiver circuit board from its case using a Dremel cutting wheel and remounted it in a 3D printed base. The excellent ps2x_lib code library from Bill Porter was used in the software to interface with the PS2 receiver. Bill’s website has a page for troubleshooting issues if your PS2 doesn’t work right with your Arduino. I made a couple changes to the ps2x_lib library for it to work with my controller – see the bottom of this page for the modifications to see if they could help you in case you’re having trouble.
- a 5000mAh 3S 20C LiPo battery. I happened to have this pack on-hand, but the robot probably would work fine with a smaller mAh capacity and possibly a 2 cell 2S pack instead. If a 2S battery is used, some minor changes will need to be made to the battery voltage monitor in the code.
- a bi-directional level converter. This is an addition made after investigating some incompatibility problems with certain wireless PS2 receivers. See more discussion about this below.
I also used two 7×15 hole perfboards as servo headers, and a 9×17 hole perfboard for the LED status display board. There are just a handful of discrete components besides this. See the complete parts list and schematics below.
- Tripod: a group of 3 legs moves forward while the other 3 legs provide support
- Wave: legs move forward one at a time while the other 5 legs provide support
- Ripple: left legs move forward rear-to-front while right also do the same, but right side is offset so the right rear starts midway through the left middle stroke
- Tetrapod: right front and left rear legs move forward together, then right rear and left middle, and finally right middle and left front legs move
When walking, the robot uses the remote joystick inputs – x and y from the right joystick and rotation from the left joystick – to tell the body which way to move. The gait engines compute the individual foot tip positions required to accomplish the desired movement. Then the IK calculation is applied to each leg’s foot tip coordinate to tell the individual servos where to go to position the legs as requested by the gait engine.
There are also modes programmed to stand in-place and translate or rotate the body. The translation is just a simple addition of an x, y, or z offset to the coordinate system. Body rotation is more involved, but is derived as shown in below where the x, y, and z offsets are computed using matrix multiplication.
ps2x_lib files (mine are installed in the path Documents\Arduino\libraries\PS2X_lib) as shown in red below:
1. In “PS2X_lib.h” change these lines:
#define CTRL_CLK 4
#define CTRL_BYTE_DELAY 3
#define CTRL_CLK 16
#define CTRL_BYTE_DELAY 16
2. In “PS2X_lib.cpp” change these lines:
digitalWrite(dat, HIGH); //enable pull-up
//digitalWrite(dat, HIGH); //enable pull-up
The picture below shows the mapping of the modes and controls to the buttons on the remote.
Update on the PS2 wireless receiver connections:
Upon investigating issues that several users were having with their wireless PS2 receivers, an important discovery was made! According to the webpage where I got the excellent PS2_X library, PS2 receivers are “5V tolerant”. While this appears to be true for the one that I used (a Logitech Cordless Action Controller and Receiver model number G-X2D11), several users have not been so lucky with the PS2 controllers/receivers that they were using. The PS2 receiver is powered from the Arduino’s 3.3V output. However in my testing, the voltage when the receiver is connected measured somewhat higher – in the range of 3.5V to 3.8V. When the the receiver was disconnected, the 3.3V output reverted to its correct 3.3V level.
What’s happening here is that the PS2 receiver has an interface consisting of 4 pins (DAT, CMD, ATT, and CLK) which were connected directly to the 5V Arduino processor in the original schematic – that means the PS2 receiver is seeing input waveforms pulsing up to about 5V, which can back-power the receiver and raise the apparent supply voltage greater than 3.3V. Some PS2 receivers can’t handle these increased input levels and this increased supply voltage and either stop working entirely or become intermittent.
The solution is to convert all four signals between the 3.3V receiver reference to the 5.0V Arduino reference. A bi-directional level converter is perfect for this application. The 3.3V Low Voltage (LV) side of the converter is connected to the receiver and the 5.0V High Voltage (HV) side is connected to the Arduino. I made a little “shield” perfboard that fits across the applicable Arduino pins to mount the level converter and also moved the input diode D1 and the battery monitoring voltage divider resistors R1 and R2 to this board as shown below. For reference, here’s also a copy of the updated schematic.
Here is the complete operational software source for this robot:
Here are some more detailed notes about the software:
The TRAVEL constant defines the maximum distance in millimeters that the robot’s body moves in the translate mode (square button on the remote). Check out the translate_control() routine – the right joystick will allow the robot’s body to move up to +60mm (2*TRAVEL) and -60mm (-2*TRAVEL) forward and backward as well as right and left, and the left joystick will allow the robot’s body to move up to 30mm (TRAVEL) in the down direction and 90mm (-3*TRAVEL) in the up direction. In translate mode, think of it like the feet stay planted at the same points on the floor, and the body moves around within the capabilities of the legs to reach. Note that the IK computations prevent the legs from going where they can’t reach, so the commanded travel is potentially limited at some point.
The A12DEG and A30DEG constants are integer shortcuts to aid in the sine and cosine computations in the rotate mode (circle button on the remote). A12DEG is 12 degrees in radians times 1 million. That’s 12 x pi/180 = 0.209440 times 1 million = 209440. A30DEG is 30 degrees in radians times 1 million. That’s 30 x pi/180 = 0.523599 times 1 million = 523599. These are multiplied by a million to make the radian value an integer so the Arduino map() function works with sufficient precision at the beginning of the rotate_control() routine. The resultant mapped integer is divided again by a million to make a floating point radian number and then the sin() or cos() function does the trigonometric computation. In the rotate_control() routine, the rotation inputs from the right joystick will allow the robot’s body to rotate up to +/-12 degrees in X and Y and inputs from the left joystick will allow the robot’s body to rotateup to +/-30 degrees in Z. Again, think of it like the feet stay planted at the same points on the floor, and the body moves around within the capabilities of the legs to reach.
If you want to use my software with a hexapod with different body or leg part lengths, you’ll need to change a few things:
- COXA_LENGTH, FEMUR_LENGTH, and TIBIA_LENGTH are the constant lengths are in millimeters between the servo pivot points. You can see how they are measured in the design pictures above – they are in red font in the diagrams.
- BODY_X, BODY_Y, and BODY_Z will need to change to match your robot’s body center-to-coxa servo distances. See this design picture from above – the body center to coxa servo distances are shown in red. So for example, the front right leg’s coxa pivot point is 110.4mm forward of the body center and 58.4mm to the right of the body center. I considered my robot’s body center to be at the same height as the coxa servo centers, so the Z value is 0.0 for all of these.
- HOME_X, HOME_Y, and HOME_Z will probably need to change to match your robot’s desired ‘resting’ stance. This is the default startup and not-moving positions of each of the toe tips. So again, for example with the default values in the code, the front right leg’s toe is at 82.0mm forward, 82.0mm to the right of, and 80.0mm below (the value is actually -80.0) the body’s center. Another example. the right middle leg’s toe is at 0.0mm forward, 116.0mm to the right of,and 80.0mm below (the value is actually -80.0) the body’s center.
COXA_CAL, FEMUR_CAL, and TIBIA_CAL are values you can use to correct for servo centering errors. When you put your robot together, you’ll want to be sure that the servos are centered at 90 degrees before assembling the legs. The legs joints need to be assembled so that the servos are in the ‘straight’ or center position shown in this design picture from above. The ‘select’ button on the PS2 controller provides a convenient way to set the outputs to all the servos to 90 degrees, which is the center value. The coxa servo center is just where you’d think it would be – with the bracket facing directly outward for each leg. You’ll probably find that you can’t get the servos exactly at 90 degrees because of the way the servo horns attach to the servos – they usually have a 25 spline shaft which can make precise alignment impossible. The CAL values allow you to add small offsets (units are degrees) to adjust the alignment to be exactly 90 degrees. The default values in the code are the ones that my robot uses – you should set these all to 0.0 for starters and then you can play with them once you get your robot working.