Powered Up Remote Control

Python code and building instructions for the LEGO Technic App-Controlled Transformation Vehicle (42140).

Powered Up Remote Control
Image credit: Lasse Deleuran

Control the Technic App-Controlled Transformation Vechicle with the Powered Up Remote.


In this project we’ll show you how to control the App-Controlled Transformation Vehicle with the Powered Up remote.

Program

This program enables control of the flip vehicle with the Powered Up Remote. Check out the video above for an additional program, and more coding ideas.

from pybricks.hubs import TechnicHub
from pybricks.pupdevices import Motor, Remote
from pybricks.parameters import Port, Stop, Direction, Button, Color, Side
from pybricks.tools import wait, StopWatch

# Motor speed
# Speed levels
speed_levels = [400, 800, 1470]  # Slow, Medium, Fastest
current_speed_index = 1  # Start with Medium speed
SPEED = speed_levels[current_speed_index]

# Initialize the hub, motors, and remote
hub = TechnicHub()
left_motor = Motor(Port.B)
right_motor = Motor(Port.A)
remote = Remote()
inactivity_timer = StopWatch()

# Increase motor acceleration
left_motor.control.limits(speed=1470, acceleration=4000)
right_motor.control.limits(speed=1470, acceleration=4000)

# Variables to track the previous state of the red buttons
prev_left_button_pressed = False
prev_right_button_pressed = False

# Main control loop
while True:
    # Check which buttons are pressed
    buttons_pressed = remote.buttons.pressed()

    # Detect single presses on the red buttons
    left_button_pressed = Button.LEFT in buttons_pressed
    right_button_pressed = Button.RIGHT in buttons_pressed

    if left_button_pressed and not prev_left_button_pressed:
        current_speed_index = max(0, current_speed_index - 1)  # Decrease speed index
        SPEED = speed_levels[current_speed_index]  # Update SPEED

    if right_button_pressed and not prev_right_button_pressed:
        current_speed_index = min(
            len(speed_levels) - 1, current_speed_index + 1
        )  # Increase speed index
        SPEED = speed_levels[current_speed_index]  # Update SPEED

    # Store the current state for the next iteration
    prev_left_button_pressed = left_button_pressed
    prev_right_button_pressed = right_button_pressed

    # Determine hub orientation
    # Note: Slight bugginess when flipping from Orange to Blue side
    # Might be improved by including FRONT here
    invert_direction = hub.imu.up() == Side.BOTTOM

    # Control motors with remote
    left_speed = 0
    right_speed = 0

    if Button.LEFT_PLUS in buttons_pressed:
        left_speed = SPEED
    elif Button.LEFT_MINUS in buttons_pressed:
        left_speed = -SPEED

    if Button.RIGHT_PLUS in buttons_pressed:
        right_speed = -SPEED
    elif Button.RIGHT_MINUS in buttons_pressed:
        right_speed = SPEED

    # Swap motor direction if the hub is upside down
    if invert_direction:
        left_speed, right_speed = right_speed, left_speed  # Swap the motor controls

    # Run motors
    left_motor.run(left_speed)
    right_motor.run(right_speed)

    # Update light color based on orientation
    hub.light.on(Color.ORANGE if invert_direction else Color.BLUE)
    remote.light.on(Color.ORANGE if invert_direction else Color.BLUE)

    # Check for inactivity - Power off if left untouched to save batteries
    # Reset the timer if there's any button pressed
    if buttons_pressed:
        inactivity_timer.reset()

    if inactivity_timer.time() > 120000:  # 2 minute in milliseconds
        hub.system.shutdown()

    # Small delay to prevent overloading the CPU
    wait(10)

Additional program submitted by @mikeyupol:

from pybricks.pupdevices import Motor, Remote
from pybricks.hubs import TechnicHub
from pybricks.parameters import Button, Color, Direction, Port
from pybricks.tools import wait, StopWatch

# This drives like a car.
# Left +/- control going forwards/backwards, and right +/- turn.
# When the vehicle is moving turn is gradual, when it's stationary turn is faster.

remote = Remote()

hub = TechnicHub()

# Set very high speed limits to ensure maximum is reached.
DRIVE_SPEED = 10000
TURN_SPEED = 650
DRIVE_ACCELERATION = 7000

# Initialize the motors.
right_motor = Motor(Port.A, Direction.COUNTERCLOCKWISE)
left_motor = Motor(Port.B)

left_motor.control.limits(acceleration=DRIVE_ACCELERATION)
right_motor.control.limits(acceleration=DRIVE_ACCELERATION)

while True:
    # Check which buttons are pressed
    wait(10)
    pressed = remote.buttons.pressed()

    # Choose forward/backward and turn right/left based on pressed buttons
    left_speed = 0
    right_speed = 0
    pitch, roll = hub.imu.tilt()
    sign = -1 if abs(roll) > 90 else 1
    speed = sign * DRIVE_SPEED
    turn = sign * TURN_SPEED
    if Button.LEFT_PLUS in pressed or Button.LEFT_MINUS in pressed:
        # Going forwards/backwards
        left_speed = speed
        right_speed = speed

        # Turn slowly when moving
        turn_right = Button.RIGHT_PLUS in pressed
        turn_left = Button.RIGHT_MINUS in pressed
        if (turn_right and sign > 0) or (turn_left and sign < 0):
            right_speed = turn
        elif turn_right or turn_left:
            left_speed = turn

        if Button.LEFT_MINUS in pressed:
            left_speed *= -1
            right_speed *= -1
    else:
        # Not moving, fast turn
        if Button.RIGHT_PLUS in pressed:
            left_speed = DRIVE_SPEED
            right_speed = -DRIVE_SPEED
        if Button.RIGHT_MINUS in pressed:
            left_speed = -DRIVE_SPEED
            right_speed = DRIVE_SPEED

    # Activate the driving motors.
    left_motor.run(left_speed)
    right_motor.run(right_speed)


This project was submitted by Geoff Stearns.