Stewart Platform
Ever dreamed of creating a versatile robot that can effortlessly move in any direction? Look no further than the Stewart Platform – a dynamic system capable of motion in all six degrees of freedom, driven by the precise coordination of linear actuators. These platforms are commonly utilized in motion simulators and the precise positioning of instruments, such as telescopes.
The exciting part? Building your own Stewart Platform is not only feasible but also surprisingly affordable. I'll walk you through the process of crafting one using stepper motor linear actuators, a Raspberry Pi, wooden panels, and other readily available craft materials. What's more, the beauty of this project lies in its adaptability – feel free to substitute components based on what you have at hand.
While this guide provides a broad overview rather than detailed step-by-step instructions, the attached files should empower you to successfully create a Stewart platform. Feel free to reach out if you need assistance!
Supplies
Note: Tailor this project to your existing components. I've suggested potential suppliers, alternatives, and provided rationale in the respective steps. Feel free to reach out if you need assistance; I'm here to help.
Tools:
- Driller
- 3d Printer
- Jigsaw
- CNC milling machine (advantageous)
Mechanics:
- 2 Wooden Panels (600x600x10 mm)
- 1 Wooden Panel (560x510x5 mm)
- Cable Canal (40x40x1000 mm)
- 12 Flange Bearings with Ball Stud (Igus GFSM-10-AG; possibly 3d-printed)
- 12 Clevises (3d-printed)
- 4 Wooden Posts or Aluminium Slot Profile (30x30x100 mm)
Electronics:
- 1 Power Adapter 12V ~ 2A
- 1 Raspberry Pi (3B)
- 6 Stepper Motor Driver A4988
- 1 Interface Board (gerber files provided)
- 12 Stepper Motor Linear Actuators 12V (countless cheap offers on Alibaba)
- 1 Emergency Stop
- 1 Fan
- 2 m Cable 1 mm²
Prepare the Bases and the Platform
Note: You have the flexibility to scale the parts according to your specific application needs. The attached CAD files provide the necessary details. For optimal precision, especially in crafting the platform, consider utilizing CNC milling.
- Cut the wooden panels to the specified lengths.
- Drill mounting holes for the flange bearings in both the upper base and platform. The precise positioning of flange bearings isn't critical; the platform can be arranged at an angle between 60° and 120° to the base.
- Cut the aluminum profiles (or alternatively, wooden posts) to 100 mm.
- Screw the posts into the four corners of the lower platform.
- Divide the cable duct into three pieces and screw them onto the upper base.
Get the construction files here: https://github.com/smwwims/hexapodPlatform
Mount Electronics
- Utilize the specially developed Raspberry Pi stepper motor interface board designed for this project (Gerber files attached). You can order this board from your trusted manufacturer. Alternatively, explore online options for available 6-axis shields compatible with the RPI. If preferred, you can also substitute the RPI with an Arduino. However, the RPI was chosen for its superior application scalability.
- Populate the interface board following the provided circuit diagram.
- Attach the RPI and interface board to the lower platform. Place spacer sleeves between the boards and the wooden base, then secure the assembly using wood screws.
Mount Linear Actuators
- Secure the flange bearings onto the upper base.
- Print out the clevises and attach them to the flange bearings (STL files attached).
- Repeat the same process for the platform.
- Proceed to screw the linear drive units onto the upper and lower fork heads. The Stewart platform achieves stability only when all six drive units are securely fastened. For optimal results, it's recommended to perform this step with two people—one to hold the linear drive units.
- Route the linear drive unit cables through the holes in the top base and guide them through the cable channels to the interface board.
Software
Install the flask, RpiMotorLib and GPIO libraries and execute the following script:
from flask import Flask, render_template_string, request
from time import sleep
import RPi.GPIO as GPIO
from RpiMotorLib import RpiMotorLib
#define GPIO pins
GPIO_pins = (-1, -1, -1) # Microstep Resolution MS1-MS3 -> GPIO Pin
# Declare an named instance of class pass GPIO pins numbers
LAE1 = RpiMotorLib.A4988Nema(17, 4, GPIO_pins, "A4988")
LAE2 = RpiMotorLib.A4988Nema(22, 27, GPIO_pins, "A4988")
LAE3 = RpiMotorLib.A4988Nema(25, 24, GPIO_pins, "A4988")
LAE4 = RpiMotorLib.A4988Nema(5, 1, GPIO_pins, "A4988")
LAE5 = RpiMotorLib.A4988Nema(19, 13, GPIO_pins, "A4988")
LAE6 = RpiMotorLib.A4988Nema(20, 26, GPIO_pins, "A4988")
app = Flask(__name__)
#HTML Code
TPL = '''
<html>
<head><title>HIVE - Control</title></head>
<body>
<h2>HIVE Control Page</h2>
<form method="POST" action="axis1">
<p>Achse 1 <input type="range" min="1" max="20" name="LAE1" /> </p>
<input type="submit" value="submit" />
</form>
<form method="POST" action="axis2">
<p>Achse 2 <input type="range" min="1" max="20" name="LAE2" /> </p>
<input type="submit" value="submit" />
</form>
<form method="POST" action="axis3">
<p>Achse 3 <input type="range" min="1" max="20" name="LAE3" /> </p>
<input type="submit" value="submit" />
</form>
<form method="POST" action="axis4">
<p>Achse 4 <input type="range" min="1" max="20" name="LAE4" /> </p>
<input type="submit" value="submit" />
</form>
<form method="POST" action="axis5">
<p>Achse 5 <input type="range" min="1" max="20" name="LAE5" /> </p>
<input type="submit" value="submit" />
</form>
<form method="POST" action="axis6">
<p>Achse 6 <input type="range" min="1" max="20" name="LAE6" /> </p>
<input type="submit" value="submit" />
</form>
</body>
</html>
'''
@app.route("/")
def home():
return render_template_string(TPL)
@app.route("/axis1", methods=["POST"])
def axis1():
# Linearantriebseinheit 1
LAE1value = request.form["LAE1"]
print(int(LAE1value))
if (int(LAE1value)>10):
LAE1.motor_go(True, "Full" , 600,int(LAE1value)*.0004, False, .05)
print("Rotating Clockwise")
elif (int(LAE1value)<10):
LAE1.motor_go(False, "Full" , 600,int(LAE1value)*.001, False, .05)
print("Rotating Anti-Clockwise")
return render_template_string(TPL)
@app.route("/axis2", methods=["POST"])
def axis2():
# Linearantriebseinheit 2
LAE2value = request.form["LAE2"]
print(int(LAE2value))
if (int(LAE2value)>10):
LAE2.motor_go(True, "Full" , 600,int(LAE2value)*.0004, False, .05)
print("Rotating Clockwise")
elif (int(LAE2value)<10):
LAE2.motor_go(False, "Full" , 600,int(LAE2value)*.001, False, .05)
print("Rotating Anti-Clockwise")
return render_template_string(TPL)
@app.route("/axis3", methods=["POST"])
def axis3():
# Linearantriebseinheit 3
LAE3value = request.form["LAE3"]
print(int(LAE3value))
if (int(LAE3value)>10):
LAE3.motor_go(True, "Full" , 600,int(LAE3value)*.0004, False, .05)
print("Rotating Clockwise")
elif (int(LAE3value)<10):
LAE3.motor_go(False, "Full" , 600,int(LAE3value)*.001, False, .05)
print("Rotating Anti-Clockwise")
return render_template_string(TPL)
@app.route("/axis4", methods=["POST"])
def axis4():
# Linearantriebseinheit 4
LAE4value = request.form["LAE4"]
print(int(LAE4value))
if (int(LAE4value)>10):
LAE4.motor_go(True, "Full" , 600,int(LAE4value)*.0004, False, .05)
print("Rotating Clockwise")
elif (int(LAE4value)<10):
LAE4.motor_go(False, "Full" , 600,int(LAE4value)*.001, False, .05)
print("Rotating Anti-Clockwise")
return render_template_string(TPL)
@app.route("/axis5", methods=["POST"])
def axis5():
# Linearantriebseinheit 5
LAE5value = request.form["LAE5"]
print(int(LAE5value))
if (int(LAE5value)>10):
LAE5.motor_go(True, "Full" , 600,int(LAE5value)*.0004, False, .05)
print("Rotating Clockwise")
elif (int(LAE5value)<10):
LAE5.motor_go(False, "Full" , 600,int(LAE5value)*.001, False, .05)
print("Rotating Anti-Clockwise")
return render_template_string(TPL)
@app.route("/axis6", methods=["POST"])
def axis6():
# Linearantriebseinheit 6
LAE6value = request.form["LAE6"]
print(int(LAE6value))
if (int(LAE6value)>10):
LAE6.motor_go(True, "Full" , 600,int(LAE6value)*.0004, False, .05)
print("Rotating Clockwise")
elif (int(LAE6value)<10):
LAE6.motor_go(False, "Full" , 600,int(LAE6value)*.001, False, .05)
print("Rotating Anti-Clockwise")
return render_template_string(TPL)
# Run the app on the local development server
if __name__ == "__main__":
app.run()
Finished!
Congratulations on building your own Stewart Platform! While this guide provides a broad overview rather than detailed step-by-step instructions, the attached files should empower you to successfully create a Stewart platform. Remember, should you encounter any challenges or find instructions unclear, don't hesitate to reach out. I'm here to assist you on your journey. Thank you for undertaking this exciting build!
https://linktr.ee/simonwimmer