ord

[MOC] Cartesian Parallel Robot

Recommended Posts

Here is my latest MOC; a 3DOF cartesian parallel robot with suction gripper.

It is capable of lifting small parts within a work envelope of 7x7x5 studs.

51008698507_799aff48d9_w_d.jpg51008718162_2308750a85_w_d.jpg

 

Share this post


Link to post
Share on other sites

That looks really interesting and innovative!

What is that suction cylinder? A standard pneumatic cylinder with a transparent body?

Share this post


Link to post
Share on other sites

This is a well thought mechanical solution. I am surprised by its precision. I suppose that each arm is kept only by a single (long) thread link. Am I right?

Do you think that it could be enlarged to get a slightly larger working space?

 

Share this post


Link to post
Share on other sites

Awesome!

Attach an filament extruder and you have a 3D printer!

Excellent!

Btw what language did you program it with?

Share this post


Link to post
Share on other sites

@Jonas That's right about the tread link. I think it could be enlarged, I was just restricted by my longest axles being 12M. With 32M axles it could be enlarged significantly I think. 

@NikosSprocket thanks. It was programmed using Pybricks.

Share this post


Link to post
Share on other sites
Posted (edited)

Amazing creation as always. I adore the smoothness of the arm movements and the compactness of the machine. Would it be possible to share  the Pybricks code please? Building a recreation looks simple enough, programming in the other hand is nigh impossible for me. Thanks in advance.

Edited by domleg
Spelling.

Share this post


Link to post
Share on other sites

It seems that there is interest in this amazing creation. Would it be possible for you to add some more pictures from other angles? Thanks in advance. 

Share this post


Link to post
Share on other sites

@domleg Thank you! I am reluctant to share the code because it is unrefined and was thrown together just to be good enough for the video. That being said, maybe you can get something out of it, just bear in mind that it could do with some work:

Spoiler

from pybricks.hubs import TechnicHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Stop, Color, Direction
from pybricks.tools import wait
from math import sin, pi, fabs, sqrt

print("START")

# Initialize the hub
hub = TechnicHub()

# Initialize the motors
motor_x = Motor(Port.A, Direction.COUNTERCLOCKWISE, [20, 75])
motor_y = Motor(Port.B, Direction.COUNTERCLOCKWISE, [20, 75])
motor_z = Motor(Port.C, Direction.COUNTERCLOCKWISE, [20, 75])
motor_suction = Motor(Port.D, Direction.CLOCKWISE, [12, 36])

# Initialize variables
old_x = 0.0
old_y = 0.0
old_z = 0.0
    
# Find zero
def reset_motors():
    print("Finding origin...")
    motor_x.run_until_stalled(-100, duty_limit=30)
    print("x zero set.")

    motor_y.run_until_stalled(-100, duty_limit=30)
    print("y zero set.")

    motor_z.run_until_stalled(-100, duty_limit=30)
    print("z zero set.")

    motor_x.reset_angle(0)
    motor_y.reset_angle(0)
    motor_z.reset_angle(0)
    motor_suction.reset_angle(0)

# Move end effector
def move(x, y, z, speed):
    global old_x
    global old_y
    global old_z
    rel_x = x - old_x
    rel_y = y - old_y
    rel_z = z - old_z
    segment_length = sqrt(pow(rel_x,2) + pow(rel_y,2) + pow(rel_z,2))
    time = segment_length / speed
    if time == 0: time = 0.01
    x_speed = fabs(rel_x) / time
    y_speed = fabs(rel_y) / time
    z_speed = fabs(rel_z) / time

    if x_speed > 1: motor_x.run_target(x_speed, x*10, then=Stop.COAST, wait=False)
    if y_speed > 1: motor_y.run_target(y_speed, y*10, then=Stop.COAST, wait=False)
    if z_speed > 1: motor_z.run_target(z_speed, z*10, then=Stop.COAST, wait=False)
    wait(time * 12000)
    old_x = x
    old_y = y
    old_z = z

# Move each axis +/-
def axes_demo(speed):
    move(7,7,0,speed)
    move(0,7,0,speed)
    move(0,0,0,speed)
    move(0,7,0,speed)
    move(0,7,5,speed)
    move(0,7,0,speed)

def circle_diagonal(speed):
    move(6.0,5.3,4.3,speed)
    move(4.9,6.5,3.5,speed)
    move(3.7,7.0,2.5,speed)
    move(2.1,6.5,1.5,speed)
    move(1.0,5.3,0.7,speed)
    move(0.7,3.5,0.5,speed)
    move(1.0,1.7,0.7,speed)
    move(2.1,0.5,1.5,speed)
    move(3.5,0.0,2.5,speed)
    move(4.9,0.5,3.5,speed)
    move(6.0,1.8,4.3,speed)
    move(6.3,3.5,4.5,speed)

def circle_top(speed):
    move(7,3.5,5,speed)
    move(6.96,4,5,speed)
    move(6.85,4.5,5,speed)
    move(6.66,5,5,speed)
    move(6.37,5.5,5,speed)
    move(5.95,6,5,speed)
    move(5.46,6.4,5,speed)
    move(4.92,6.7,5,speed)
    move(4.33,6.9,5,speed)
    move(3.5,7,5,speed)
    move(2.67,6.9,5,speed)
    move(2.08,6.7,5,speed)
    move(1.54,6.4,5,speed)
    move(1.05,6,5,speed)
    move(0.63,5.5,5,speed)
    move(0.34,5,5,speed)
    move(0.15,4.5,5,speed)
    move(0.04,4,5,speed)
    move(0,3.5,5,speed)
    move(0.04,3,5,speed)
    move(0.15,2.5,5,speed)
    move(0.34,2,5,speed)
    move(0.63,1.5,5,speed)
    move(1.05,1,5,speed)
    move(1.54,0.6,5,speed)
    move(2.08,0.3,5,speed)
    move(2.67,0.1,5,speed)
    move(3.5,0,5,speed)
    move(4.33,0.1,5,speed)
    move(4.92,0.3,5,speed)
    move(5.46,0.6,5,speed)
    move(5.95,1,5,speed)
    move(6.37,1.5,5,speed)
    move(6.66,2,5,speed)
    move(6.85,2.5,5,speed)
    move(6.96,3,5,speed)
    move(7,3.5,5,speed)

# Suction movement
def suction_move(x,y,z):
    move(6.8,1.2,5,100)
    move(6.8,1.2,z,100)
    wait(200)

    # Suction on
    motor_suction.run_target(500, 180, then=Stop.BRAKE, wait=False)
    
    wait(1000)
    move(6.8,1.2,5.3,100)
    move(x,y,5.3,150)
    move(x,y,1.5,150)

    # Suction off
    motor_suction.run_target(500, 0, then=Stop.BRAKE, wait=True)
    
    wait(100)

# Video part 1
def part_1():
    move(0,7,0,100)
    wait(3000)
    
    axes_demo(70)
    wait(1000)
    
    move(7,0,5,100)
    wait(1000)
    circle_top(100)
    wait(2000)
    
    move(6.3,3.5,4.5,100)
    circle_diagonal(130)
    circle_diagonal(130)
    wait(600)
    
    move(0,0,0,140)                         

# Video part 2
def part_2():
    move(0,0,5,300)
    wait(500)
    
    suction_move(0,2.8,3.0)
    move(0,2.8,5,150)
    
    suction_move(3,2.8,2.0)
    move(3,2.8,5,150)
    
    suction_move(0,4.8,1.0)
    move(0,4.8,5,150)
    
    suction_move(3,4.8,0.0)
    
    # Push tray
    wait(1000)
    move(1.5,7,1.5,80)
    move(1.5,7,0,80)
    move(1.5,0,0,50)
    wait(200)
    
    # Back right top corner
    move(7,7,5,400)
    wait(500)





# PROGRAM HERE
reset_motors()
hub.light.on(Color.WHITE * 0.8)
wait(5000)
part_2() #part_1 or part_2 here


print("END")

 

 

@Jonas Sure, hopefully these help:

51028508886_577caf891d_w_d.jpg

51028508836_decd8c8c17_c_d.jpg

51028609732_4ab6be1c0e_c_d.jpg

(Flickr album)

Share this post


Link to post
Share on other sites
4 hours ago, ord said:

 

@Jonas Sure, hopefully these help:

Thank you very much. I have already built it (or at least something very similar), so I can check some details now. I was not sure mainly regarding the front-rear axis where I had some problems with smooth movement. At the moment I can move the axes only by hand crank as I need to wait for my EV3 motors to become available after disassembling the current robot.

Once again I must say that your design is really nice, clever and compact. Thanks to it I learned some new stuff about parallely controlled robotic arms and found some other nice examples on youtube.

Share this post


Link to post
Share on other sites

You're both welcome, I'm glad I could help :).

I find these types of robots interesting with some good examples on YouTube. I hope to build some different types in the future (maybe with more axes).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.