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

@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

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

@ord This is great, thanks for sharing!

Is each code to position the head during each step hard coded (looks to be from the code) or is there an algorithm that calculates the points on the x, y, z axis and converts that to the rotation of each motor? 

I going to build one and have a play, I might even use the new Mindstorm brick and motors which will make it easier to add sensors without having to add another control box.

Would you be able to share some phots of the back that cannot be seen (and any other perspectives you may think are helpful to recreate it). 

Back.JPG

Thanks

Henry

Share this post


Link to post
Share on other sites

@HRU_Bricks thank you. The beauty of this robot is that each motor's rotation directly correlates to an axis movement. To reach a point in x, y, z the motors must simply rotate to x, y, z (multiplied by some gearing factor). In my case the x, y, z position is input in Lego studs. 

Sorry, I've already dismantled the model but there is really not much behind the back. 

Share this post


Link to post
Share on other sites

Thanks for the info @ord. I thought that might be the case with the positioning the point. 

It is probably is a good thing you pulled it apart as it made me think about the build more and come up with some new ideas. 

This is the result so far:

Cartesian%20Parallel%20Robot_2.jpg

Cartesian%20Parallel%20Robot_3.jpg

Edited by HRU_Bricks

Share this post


Link to post
Share on other sites

Hi @ord, such a neat and amazing design! I’m new to LEGO and just got the Mindstorms, I want to rebuild your robot for some certain movements, wondering if you have the Studio file to share? Thanks!

Edited by melon

Share this post


Link to post
Share on other sites

@melon I am working on a studio file and will posted here when it is done. it will be based on the new Powered Up line but it would be easy enough to modify to Ev3

 

Share this post


Link to post
Share on other sites

Finally finished (though I haven't programmed it yet). There was a few more tweak's as I built. It is an easy build that shouldn't cost the world to do. I did not add the chain to the model (but they are off to the side in the model) because it was doing my head it to get it looking right.

Here is the link to the file (let me know if it does not work) --> https://bricksafe.com/files/HRU_Bricks/cartesian-parallel-robot-by-ord/Cartesian Parallel Robot by ord.io

To Bricksafe Location --> https://bricksafe.com/pages/HRU_Bricks/cartesian-parallel-robot-by-ord

Have fun!

Cartesian%20Parallel%20Robot%20by%20ord% 

Share this post


Link to post
Share on other sites

@HRU_Bricks Thanks for the file!

Just stumbled upon this topic. Would have saved me some time if I had seen it sooner as I reverse engineered it also but made a wider version with 16L slider axles :)

Share this post


Link to post
Share on other sites

@Berthil indeed it would have!

I was thinking of using 16L's but my LugBulk order hasn't arrived yet,

My plan was to see  if it could be used for GBC in some way. I have been working on and off on a design to lift balls in the same way this lifts the yellow parts (with a vacuum) but the groves in the Lego GBC balls always stopped the idea. 

 

How does it go with the longer axles? 

Share this post


Link to post
Share on other sites

@HRU_Bricks I'm also going to use it in a GBC. I have the whole machine ready and am about to stick on the 3D arm contraption so don't know yet how it will run.

I anticipated the vacuum would not work on the grooved balls (and some have a hole) so did not start with a vacuum.
The 4th port I am using for a color sensor to create a color sorter. I have the program running, last step is to program the motors in when they are on the machine so I hope to be finished in a few weeks.

And of course also thank you @ord , when finished and working I will show the GBC here. I'll be creating free instructions for the GBC.

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.