Jump to content

ord

Eurobricks Citizen
  • Posts

    218
  • Joined

  • Last visited

Everything posted by ord

  1. Hi, the code is written in pybricks, so if you want to use it you have to install pybricks on your hub from https://pybricks.com/. Specifics of what each line means can be found in the documentation at https://docs.pybricks.com/en/latest/.
  2. Here's the code. Note that it's raw and a bit messy - I never intended to publish it. 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 # Flash light def flash(): hub.light.on(Color.GREEN) wait(100) hub.light.off() # Find zero def reset_motors(): print("Finding origin...") motor_x.run_until_stalled(-100, duty_limit=30) print("x zero set.") #flash() motor_y.run_until_stalled(-100, duty_limit=30) print("y zero set.") #flash() motor_z.run_until_stalled(-100, duty_limit=30) print("z zero set.") #flash() 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 #print("Time = " + str(time) + "; Segment length = " + str(segment_length) + "; Speed = " + str(x_speed) + ", " + str(y_speed) + ", " + str(z_speed) + "; Move to " + str(x) + ", " + str(y) + ", " + str(z)) 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) # Circle (diagonal) def circle(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) # Circle (diagonal reverse) def circle2(speed): move(6.0,1.8,4.3,speed) move(4.9,0.5,3.5,speed) move(3.7,0.0,2.5,speed) move(2.1,0.5,1.5,speed) move(1.0,1.7,0.7,speed) move(0.7,3.5,0.5,speed) move(1.0,5.3,0.7,speed) move(2.1,6.5,1.5,speed) move(3.5,7.0,2.5,speed) move(4.9,6.5,3.5,speed) move(6.0,5.3,4.3,speed) move(6.3,3.5,4.5,speed) # Circle (diagonal reverse raised) def circle3(speed): move(6.7,1.8,4.8,speed) move(5.6,0.5,4.0,speed) move(4.2,0.0,3.0,speed) move(2.8,0.5,2.0,speed) move(1.7,1.7,1.2,speed) move(1.4,3.5,1.0,speed) move(1.7,5.3,1.2,speed) move(2.8,6.5,2.0,speed) move(4.2,7.0,3.0,speed) move(5.6,6.5,4.0,speed) move(6.7,5.3,4.8,speed) move(7.0,3.5,5.0,speed) # Circle (top plane) def circle4(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) #wait(500) 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) #wait(500) move(x,y,5.3,150) #wait(500) move(x,y,1.5,150) #wait(500) # Suction off motor_suction.run_target(500, 0, then=Stop.BRAKE, wait=True) wait(100) # Video part 1a def part_1a(): # Bottom square move(0,7,0,60) wait(500) move(7,7,0,60) wait(500) move(7,0,0,60) wait(500) move(0,0,0,60) wait(1000) # Move z move(0,0,5,300) wait(500) #move(0,0,5,300) #wait(500) #move(7,0,0,300) #wait(500) #move(0,7,5,300) #wait(500) #move(0,7,0,300) #wait(500) move(7,0,5,300) wait(1000) # Two circles then home move(6.3,3.5,4.5,250) circle(140) circle(140) wait(500) move(0,0,0,100) # Video part 1b def part_1b(): move(0,7,0,100) wait(3000) axes_demo(70) wait(1000) # Top circle move(7,0,5,100) wait(1000) circle4(100) wait(2000) move(6.3,3.5,4.5,100) circle(130) circle(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_1b() #part_1b or part_2 here print("END")
  3. Robust looking switching - it seems to lock into positions nicely. Can't wait to see the full video.
  4. Nice work! Congratulations on getting it so accurate.
  5. Ah, I now see that this is apparently what you had in the first version. I had similar problems when building my XY plotter. It seems like the increased friction is happening in the same position vertically... perhaps the ball chain is catching on something...
  6. Wow, interesting project. I hope you can get it working. If the up/down mechanism is what's inadvertently triggering the clutch, could you just decouple the up/down so it's directly powered by the motor?
  7. Impressive! It seems like you have achieved your goal of less than 1% error .
  8. Nice! How is the performance of the bearings? It looks like you've kept a 2L space between both the inner and outer rings?
  9. The year is selected first then the red carriage will move to one of two positions depending if it's a leap year or not, if I understand correctly? Maybe you could use the 14-tooth sprocket with treads with tiles attached:
  10. Wow, another interesting entry. Curious to see how you handle leap years and the '400 year rule'.
  11. I have a feeling that it can. The joints appear to be able to attach in series using 2x 2L axles, and a friction pin would make that connection even more robust. I was thinking that too. Interestingly, the joint that part is designed for has a very similar function to this joint - 2 articulations with 15 degree increments.
  12. Fascinating and creative use of Lego. Following closely .
  13. It is essentially the method that Glaysche mentioned of using two parallel gear trains. It is explained in this thread: I am looking forward to this!
  14. There was some discussion recently in this topic: This is the smoothest ball bearing design I've seen:
  15. In some sets they come in grey, I guess for aesthetics.
  16. Have you considered this? Someone posted it in a MOC recently and I thought it was smart. Not sure about it's real world performance.
  17. Wow, that's great! I especially like the conveyor design but there are lots of things to like here.
  18. An almost perfect fit that is new for me: The width of three stacked beams (red dimension) is 8 x 3 = 24mm. According to The Unofficial Lego Technic Builder's Guide, beams are 7mm wide on the thin side, which would make the sides of the yellow triangle (2.5 x 8) - (7 / 2) = 16.5 and the hypotenuse sqrt(16.5² + 16.5²) = 23.33mm. 0.67mm undersize might seem like a lot, but in reality the three stacked beams are held rather snugly at 45°. This can be tested easily inside a 5x7 frame. Edit: like this...
  19. Again, I learnt from the great Akiyuki: I was looking into this last night. The train wheels don't stand up on their own so I think they need a carrier ring connecting them together. Maybe only four wheels could fit on such a ring, which might compromise performance. Also, the 1x1 tiles do a surprisingly good job at providing radial support, but the train wheels not as much, so the bearing might require extra support if using the train wheels. I will build one and see...
  20. I built a bearing based on Akiyuki's design but with the smaller banana gears and it works well: I even managed to pass two axles through it. I think I'll be incorporating this into my robot arm as it seems very rigid.
  21. It's an interesting problem @sammypants and one I have been scratching my head at too. Having built Akiyuki's design (first video), I think it's possibly the best solution - it runs smoothly and is the most rigid design that I've built. The design in the second video is easier to build and remains in-grid, but doesn't have the upper gear form-locked below the lower gear, so is less rigid. I'm not sure how either design would go with the smaller banana gears, but would be interested to see!
  22. Making a video is too much work so I don't plan to do that. Yes the subject is complicated but all of the information is available if you follow the installation instructions on the vpype github - this is how I learnt how to do it. The mechanics of my plotter are fundamentally pretty simple. It's the coding of complex plots, I would say, that make it a complex system.
  23. Once you have vpype and vpype-gcode installed (you will need Python installed first to install them), copy the custom profile above into ~/.vpype.toml (open this file in a text editor and paste the custom profile at the bottom). From there it's just a matter of saving your svg file as input.svg in the C:\ drive and running the "vpype read..." code above in vpype. Feel free to share photos/dimensions of your plotter. The only thing that might change for your plotter should be the size of the paper (mine is 297x210cm).
  24. Ah, I misunderstood. Please see the first page of this thread for where I got my source images from and how I converted them to machine code. Basically, for a line-drawing, a vector file is usually needed that contains the lines to be drawn (I have been using the .svg file type). That file needs to be converted to code, which I do using software called vpype (and a plugin for it called vpype-gcode). This is all detailed on the first page of this thread, including the custom profile I used in vpype-gcode to output code that is readable by Pybricks :).
  25. @lego aram it might look complicated but it's actually quite simple. If you copy some of the examples from the bottom of this page onto your hub you should have a moving plotter, and from there it's just a matter of changing/adding lines of code. https://docs.pybricks.com/en/latest/pupdevices/motor.html Feel free to direct message me on Eurobricks if you get stuck :).
×
×
  • Create New...