Fast Block Flipper
Python code and building instructions for the LEGO MINDSTORMS Robot Inventor Other Fan Creations (51515).
A Four-motor robot that quickly moves and flips blocks
Description
This robot arm has four motors to allow it to grab, lift, flip, and move blocks between the three small raised platforms. The program uses some of the advanced motor control APIs to control all four motors at the same time and get fast and accurate motion.
Instructions
This program controls the 4-Motor Arm autonomously, so you don’t have to build the hand controller. You can just attach the hub to the base as shown.
Start with the two blocks on the outside (left and right) platforms, and the arm near the middle between them.
Program
from pybricks.hubs import InventorHub
from pybricks.pupdevices import Motor, ColorSensor, UltrasonicSensor
from pybricks.parameters import Button, Color, Direction, Port, Stop
from pybricks.robotics import DriveBase
from pybricks.tools import wait, StopWatch
hub = InventorHub()
lift = Motor(Port.A)
turntable = Motor(Port.B)
wrist = Motor(Port.D)
claw = Motor(Port.F)
# This is beyond a max motor speed (deg/s) and so ensures full speed
FULL_SPEED = 2000
# Turntable, lift, and claw positions
LEFT_POS = 115
CENTER_POS = 0
RIGHT_POS = -115
LIFT_UP_POS = 100
LIFT_DOWN_POS = 5
CLAW_OPEN_POS = -50
CLAW_CLOSED_POS = 0
# Get the default motor max speed, acceleration, and torque
(max_speed, accel, torque) = claw.control.limits()
# Get the motors ready at their starting position
def setup():
# Increase the default acceleration for the claw, turntable, and wrist
claw.control.limits(FULL_SPEED, accel * 5, torque * 5)
turntable.control.limits(FULL_SPEED, accel * 5, torque * 5)
wrist.control.limits(FULL_SPEED, accel * 3, torque)
# Decrease precision for the lift and claw since these are critical path
(speed_slop, pos_slop) = claw.control.target_tolerances()
claw.control.target_tolerances(speed_slop * 4, pos_slop * 4)
lift.control.target_tolerances(speed_slop * 2, pos_slop * 2)
# If the wrist starts upside down, then we need to first close and lift it
# before it gets flipped to 0, to keep it from hitting the platform.
if abs(wrist.angle()) > 90:
claw.run_target(FULL_SPEED, CLAW_CLOSED_POS, wait=False)
lift.run_target(FULL_SPEED, LIFT_UP_POS)
if wrist.angle() < -90: # then run_target would go the wrong way
wrist.reset_angle(360 + wrist.angle()) # forces counter-clockwise
# Start with turntable centered, lift down, wrist upright, and claw open
turntable.run_target(FULL_SPEED, CENTER_POS, wait=False, then=Stop.BRAKE)
lift.run_target(FULL_SPEED, LIFT_DOWN_POS, wait=False, then=Stop.BRAKE)
wrist.run_target(FULL_SPEED, 0, wait=False, then=Stop.BRAKE)
claw.run_target(FULL_SPEED, CLAW_OPEN_POS)
wait(500) # give all motors time to finish
# Start lifting up and wait a bit to be clear to rotate
def start_lifting():
# Use higher acceleration and torque for the lift when lifting up
lift.control.limits(FULL_SPEED, accel * 2, torque * 2)
lift.run_target(FULL_SPEED, LIFT_UP_POS, wait=False)
wait(150)
# Move the turntable to pos, then lower the lift, overlapping the motions
# during the final specified degrees of turntable movement.
def turn_and_lower(pos, overlap):
turntable.run_target(FULL_SPEED, pos, wait=False)
while abs(turntable.angle() - pos) > overlap:
pass
# Use faster acceleration, default decelleration, and very low torque
# for the lift when lowering because gravity is also pulling it down.
lift.control.limits(FULL_SPEED, (accel * 2, accel), torque / 10)
lift.run_target(FULL_SPEED, LIFT_DOWN_POS)
# Move a block from source_pos to dest_pos.
# The arm is assumed to start down, open, and not at source_pos.
def move(source_pos, dest_pos):
# Raise up and move to source
start_lifting()
turn_and_lower(source_pos, 400)
# Grab the block with a short burst of claw power then maintain light grip
claw.dc(100)
wait(70)
claw.dc(35)
# Lift and invert the block
start_lifting()
if abs(wrist.angle()) > 90:
wrist.run_angle(FULL_SPEED, -180, wait=False)
else:
wrist.run_angle(FULL_SPEED, 180, wait=False)
# Pivot and lower to the destination platform, then open claw to release
turn_and_lower(dest_pos, 150)
claw.run_target(FULL_SPEED, CLAW_OPEN_POS, wait=False)
# Main program
setup()
while True:
# This 3-move sequence can repeat forever
move(LEFT_POS, CENTER_POS)
move(RIGHT_POS, LEFT_POS)
move(CENTER_POS, RIGHT_POS)
This project was submitted by Dave Parker.