pupdevices – Powered Up Devices

LEGO® Powered Up motor, sensors, and lights.

Motors without Rotation Sensors

pupmotors

Figure 18 Powered Up motors without rotation sensors. The arrows indicate the default positive direction.

Show/hide examples

Example 1: Making the motor move back and forth

from pybricks.pupdevices import DCMotor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize a motor without rotation sensors on port A.
example_motor = DCMotor(Port.A)

# Make the motor go clockwise (forward) at 70% duty cycle ("70% power").
example_motor.dc(70)

# Wait for three seconds.
wait(3000)

# Make the motor go counterclockwise (backward) at 70% duty cycle.
example_motor.dc(-70)

# Wait for three seconds.
wait(3000)

Example 2: Seting the positive direction as counterclockwise

from pybricks.pupdevices import DCMotor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait

# Initialize a motor without rotation sensors on port A,
# with the positive direction as counterclockwise.
example_motor = DCMotor(Port.A, Direction.COUNTERCLOCKWISE)

# When we choose a positive duty cycle, the motor now goes counterclockwise.
example_motor.dc(70)

# This is useful when your (train) motor is mounted in reverse or upside down.
# By changing the positive direction, your script will be easier to read,
# because a positive value now makes your train/robot go forward.

# Wait for three seconds.
wait(3000)

Example 3: Starting and stopping

from pybricks.pupdevices import DCMotor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize a motor without rotation sensors on port A.
example_motor = DCMotor(Port.A)

# Start and stop 10 times.
for count in range(10):
    print("Counter:", count)

    example_motor.dc(70)
    wait(1000)

    example_motor.stop()
    wait(1000)
class DCMotor(port, positive_direction=Direction.CLOCKWISE)

Generic class to control simple motors without rotation sensors, such as train motors.

Parameters:
  • port (Port) – Port to which the motor is connected.
  • positive_direction (Direction) – Which direction the motor should turn when you give a positive duty cycle value.
dc(duty)

Rotates the motor at a given duty cycle (also known as “power”).

Parameters:duty (percentage: %) – The duty cycle (-100.0 to 100).
stop()

Stops the motor and lets it spin freely.

The motor gradually stops due to friction.

brake()

Passively brakes the motor.

The motor stops due to friction, plus the voltage that is generated while the motor is still moving.

Motors with Rotation Sensors

pupmotors

Figure 19 Powered Up motors with rotation sensors. The arrows indicate the default positive direction. See the hubs module for default directions of built-in motors.

class Motor(port, positive_direction=Direction.CLOCKWISE, gears=None)

Generic class to control motors with built-in rotation sensors.

Parameters:
  • port (Port) – Port to which the motor is connected.
  • positive_direction (Direction) – Which direction the motor should turn when you give a positive speed value or angle.
  • gears (list) –

    List of gears linked to the motor.

    For example: [12, 36] represents a gear train with a 12-tooth and a 36-tooth gear. Use a list of lists for multiple gear trains, such as [[12, 36], [20, 16, 40]].

    When you specify a gear train, all motor commands and settings are automatically adjusted to account for the resulting gear ratio. The motor direction remains unchanged by this.

Show/hide examples

Example 1: Making the motor move back and forth

from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# Make the motor run clockwise at 500 degrees per second.
example_motor.run(500)

# Wait for three seconds.
wait(3000)

# Make the motor run counterclockwise at 500 degrees per second.
example_motor.run(-500)

# Wait for three seconds.
wait(3000)

Example 2: Using more than one motor

from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize motors on port A and B.
track_motor = Motor(Port.A)
gripper_motor = Motor(Port.B)

# Make both motors run at 500 degrees per second.
track_motor.run(500)
gripper_motor.run(500)

# Wait for three seconds.
wait(3000)

Example 3: Seting the positive direction as counterclockwise

from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait

# Initialize a motor on port A with the positive direction as counterclockwise.
example_motor = Motor(Port.A, Direction.COUNTERCLOCKWISE)

# When we choose a positive speed value, the motor now goes counterclockwise.
example_motor.run(500)

# This is useful when your motor is mounted in reverse or upside down.
# By changing the positive direction, your script will be easier to read,
# because a positive value now makes your robot/mechanism go forward.

# Wait for three seconds.
wait(3000)

Example 4: Using gears

from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait

# Initialize a motor on port A with the positive direction as counterclockwise.
# Also specify one gear train with a 12-tooth and a 36-tooth gear. The 12-tooth
# gear is attached to the motor axle. The 36-tooth gear is at the output axle.
geared_motor = Motor(Port.A, Direction.COUNTERCLOCKWISE, [12, 36])

# Make the output axle run at 100 degrees per second. The motor speed
# is automatically increased to compensate for the gears.
geared_motor.run(100)

# Wait for three seconds.
wait(3000)

Measuring

Show/hide examples

Example 1: Measuring the angle and speed

from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# Start moving at 300 degrees per second.
example_motor.run(300)

# Display the angle and speed 50 times.
for i in range(100):

    # Read the angle (degrees) and speed (degrees per second).
    angle = example_motor.angle()
    speed = example_motor.speed()

    # Print the values.
    print(angle, speed)

    # Wait some time so we can read what is displayed.
    wait(200)

Example 2: Resetting the measured angle

from pybricks.pupdevices import Motor
from pybricks.parameters import Port

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# Reset the angle to 0.
example_motor.reset_angle(0)

# Reset the angle to 1234.
example_motor.reset_angle(1234)

# Reset the angle to the absolute angle.
# This is only supported on motors that have
# an absolute encoder. For other motors, this
# will raise an error.
example_motor.reset_angle()
speed()

Gets the speed of the motor.

Returns:Motor speed.
Return type:rotational speed: deg/s
angle()

Gets the rotation angle of the motor.

Returns:Motor angle.
Return type:angle: deg
reset_angle(angle=None)

Sets the accumulated rotation angle of the motor to a desired value.

If you don’t specify an angle, the absolute angle will be used if your motor supports it.

Parameters:angle (angle: deg) – Value to which the angle should be reset.

Stopping

Show/hide example

Example: Stopping the motor in different ways

from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# Run at 500 deg/s and then stop by coasting.
example_motor.run(500)
wait(1500)
example_motor.stop()
wait(1500)

# Run at 500 deg/s and then stop by braking.
example_motor.run(500)
wait(1500)
example_motor.brake()
wait(1500)

# Run at 500 deg/s and then stop by holding.
example_motor.run(500)
wait(1500)
example_motor.hold()
wait(1500)

# Run at 500 deg/s and then stop by running at 0 speed.
example_motor.run(500)
wait(1500)
example_motor.run(0)
wait(1500)
stop()

Stops the motor and lets it spin freely.

The motor gradually stops due to friction.

brake()

Passively brakes the motor.

The motor stops due to friction, plus the voltage that is generated while the motor is still moving.

hold()

Stops the motor and actively holds it at its current angle.

Action

Show/hide examples

Example 1: Basic usage of all action methods

from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# Run at 500 deg/s and then stop by coasting.
print("Demo of run")
example_motor.run(500)
wait(1500)
example_motor.stop()
wait(1500)

# Run at 70% duty cycle ("power") and then stop by coasting.
print("Demo of dc")
example_motor.dc(50)
wait(1500)
example_motor.stop()
wait(1500)

# Run at 500 deg/s for two seconds.
print("Demo of run_time")
example_motor.run_time(500, 2000)
wait(1500)

# Run at 500 deg/s for 90 degrees.
print("Demo of run_angle")
example_motor.run_angle(500, 180)
wait(1500)

# Run at 500 deg/s back to the 0 angle
print("Demo of run_target to 0")
example_motor.run_target(500, 0)
wait(1500)

# Run at 500 deg/s back to the -90 angle
print("Demo of run_target to -90")
example_motor.run_target(500, -90)
wait(1500)

# Run at 500 deg/s until the motor stalls
print("Demo of run_until_stalled")
example_motor.run_until_stalled(500)
print("Done")
wait(1500)

Example 2: Using the then argument to change how a motor stops

from pybricks.pupdevices import Motor
from pybricks.parameters import Port, Stop
from pybricks.tools import wait

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# By default, the motor holds the position. It keeps
# correcting the angle if you move it.
example_motor.run_angle(500, 360)
wait(1000)

# This does exactly the same as above.
example_motor.run_angle(500, 360, then=Stop.HOLD)
wait(1000)

# You can also brake. This applies some resistance
# but the motor does not move back if you move it.
example_motor.run_angle(500, 360, then=Stop.BRAKE)
wait(1000)

# This makes the motor coast freely after it stops.
example_motor.run_angle(500, 360, then=Stop.COAST)
wait(1000)

Example 3: Using the wait argument to run motors in parallel

from pybricks.pupdevices import Motor
from pybricks.parameters import Port

# Initialize motors on port A and B.
track_motor = Motor(Port.A)
gripper_motor = Motor(Port.B)

# Make the track motor start moving,
# but don't wait for it to finish.
track_motor.run_angle(500, 360, wait=False)

# Now make the gripper motor rotate. This
# means they move at the same time.
gripper_motor.run_angle(200, 720)

Example 4: Waiting for two actions to complete in parallel

from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize motors on port A and B.
track_motor = Motor(Port.A)
gripper_motor = Motor(Port.B)

# Make both motors perform an action with wait=False
track_motor.run_angle(500, 360, wait=False)
gripper_motor.run_angle(200, 720, wait=False)

# While one or both of the motors are not done yet,
# do something else. In this example, just wait.
while not track_motor.control.done() or not gripper_motor.control.done():
    wait(10)

print("Both motors are done!")

Example 5: Running a motor until a mechanical endpoint

from pybricks.pupdevices import Motor
from pybricks.parameters import Port

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# We'll use a speed of 200 deg/s in all our commands.
speed = 200

# Run the motor in reverse until it hits a mechanical stop.
# The duty_limit=30 setting means that it will apply only 30%
# of the maximum torque against the mechanical stop. This way,
# you don't push against it with too much force.
example_motor.run_until_stalled(-speed, duty_limit=30)

# Reset the angle to 0. Now whenever the angle is 0, you know
# that it has reached the mechanical endpoint.
example_motor.reset_angle(0)

# Now make the motor go back and forth in a loop.
# This will now work the same regardless of the
# initial motor angle, because we always start
# from the mechanical endpoint.
for count in range(10):
    example_motor.run_target(speed, 180)
    example_motor.run_target(speed, 90)

Example 6: Centering a steering mechanism

from pybricks.pupdevices import Motor
from pybricks.parameters import Port

# Initialize a motor on port A.
example_motor = Motor(Port.A)

# We'll use a speed of 200 deg/s in all our commands.
speed = 200

# Run the motor in reverse until it hits a mechanical stop.
# The duty_limit=30 setting means that it will apply only 30%
# of the maximum torque against the mechanical stop. This way,
# you don't push against it with too much force.
example_motor.run_until_stalled(-speed, duty_limit=30)

# Reset the angle to 0. Now whenever the angle is 0, you know
# that it has reached the mechanical endpoint.
example_motor.reset_angle(0)

# Now make the motor go back and forth in a loop.
# This will now work the same regardless of the
# initial motor angle, because we always start
# from the mechanical endpoint.
for count in range(10):
    example_motor.run_target(speed, 180)
    example_motor.run_target(speed, 90)
run(speed)

Runs the motor at a constant speed.

The motor accelerates to the given speed and keeps running at this speed until you give a new command.

Parameters:speed (rotational speed: deg/s) – Speed of the motor.
run_time(speed, time, then=Stop.HOLD, wait=True)

Runs the motor at a constant speed for a given amount of time.

The motor accelerates to the given speed, keeps running at this speed, and then decelerates. The total maneuver lasts for exactly the given amount of time.

Parameters:
  • speed (rotational speed: deg/s) – Speed of the motor.
  • time (time: ms) – Duration of the maneuver.
  • then (Stop) – What to do after coming to a standstill.
  • wait (bool) – Wait for the maneuver to complete before continuing with the rest of the program.
run_angle(speed, rotation_angle, then=Stop.HOLD, wait=True)

Runs the motor at a constant speed by a given angle.

Parameters:
  • speed (rotational speed: deg/s) – Speed of the motor.
  • rotation_angle (angle: deg) – Angle by which the motor should rotate.
  • then (Stop) – What to do after coming to a standstill.
  • wait (bool) – Wait for the maneuver to complete before continuing with the rest of the program.
run_target(speed, target_angle, then=Stop.HOLD, wait=True)

Runs the motor at a constant speed towards a given target angle.

The direction of rotation is automatically selected based on the target angle. It does matter if speed is positive or negative.

Parameters:
  • speed (rotational speed: deg/s) – Speed of the motor.
  • target_angle (angle: deg) – Angle that the motor should rotate to.
  • then (Stop) – What to do after coming to a standstill.
  • wait (bool) – Wait for the motor to reach the target before continuing with the rest of the program.
run_until_stalled(speed, then=Stop.COAST, duty_limit=None)

Runs the motor at a constant speed until it stalls.

Parameters:
  • speed (rotational speed: deg/s) – Speed of the motor.
  • then (Stop) – What to do after coming to a standstill.
  • duty_limit (percentage: %) – Torque limit during this command. This is useful to avoid applying the full motor torque to a geared or lever mechanism.
Returns:

Angle at which the motor becomes stalled.

Return type:

angle: deg

dc(duty)

Rotates the motor at a given duty cycle (also known as “power”).

This method lets you use a motor just like a simple DC motor.

Parameters:duty (percentage: %) – The duty cycle (-100.0 to 100).

Advanced motion control

track_target(target_angle)

Tracks a target angle. This is similar to run_target(), but the usual smooth acceleration is skipped: it will move to the target angle as fast as possible. This method is useful if you want to continuously change the target angle.

Parameters:target_angle (angle: deg) – Target angle that the motor should rotate to.
control

The motors use PID control to accurately track the speed and angle targets that you specify. You can change its behavior through the control attribute of the motor. See The Control Class for an overview of available methods.

Color and Distance Sensor

_images/sensor_colordistance.png

Show/hide examples

Example 1: Measuring color

from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.A)

while True:
    # Read the color.
    color = sensor.color()

    # Print the measured color.
    print(color)

    # Move the sensor around and see how
    # well you can detect colors.

    # Wait so we can read the value.
    wait(100)

Example 2: Waiting for a color

from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.A)


# This is a function that waits for a desired color.
def wait_for_color(desired_color):
    # While the color is not the desired color, we keep waiting.
    while sensor.color() != desired_color:
        wait(20)


# Now we use the function we just created above.
while True:

    # Here you can make your train/vehicle go forward.

    print("Waiting for red ...")
    wait_for_color(Color.RED)

    # Here you can make your train/vehicle go backward.

    print("Waiting for blue ...")
    wait_for_color(Color.BLUE)

Example 3: Measuring distance

from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.A)

# Repeat forever.
while True:

    # If the sensor sees an object nearby.
    if sensor.distance() <= 40:

        # Then blink the light red/blue 5 times.
        for i in range(5):
            sensor.light.on(Color.RED)
            wait(30)
            sensor.light.on(Color.BLUE)
            wait(30)
    else:
        # If the sensor sees nothing
        # nearby, just wait briefly.
        wait(10)
class ColorDistanceSensor(port)

LEGO® Powered Up Color and Distance Sensor.

Parameters:port (Port) – Port to which the sensor is connected.
color()

Scans the color of a surface.

You choose which colors are detected using the detectable_colors() method. By default, it detects Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.WHITE, or None.

Returns:Detected color.
Return type:Color
reflection()

Measures the reflection of a surface.

Returns:Reflection, ranging from 0.0 (no reflection) to 100.0 (high reflection).
Return type:percentage: %
ambient()

Measures the ambient light intensity.

Returns:Ambient light intensity, ranging from 0 (dark) to 100 (bright).
Return type:percentage: %
distance()

Measures the relative distance between the sensor and an object using infrared light.

Returns:Relative distance ranging from 0 (closest) to 100 (farthest).
Return type:relative distance: %

Advanced color sensing

Show/hide examples

Example 1: Reading hue, saturation, and value

from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.A)

while True:
    # The standard color() method always "rounds" the
    # measurement to the nearest "whole" color.
    # That's useful for most applications.

    # But you can get the original hue, saturation,
    # and value without "rounding", as follows:
    color = sensor.hsv()

    # Print the results.
    print(color)

    # Wait so we can read the value.
    wait(500)

Example 2: Changing the detectable colors

By default, the sensor is configured to detect red, yellow, green, blue, white, or None, which suits many applications.

For better results in your application, you can measure your desired colors in advance, and tell the sensor to look only for those colors. Be sure to measure them at the same distance and light conditions as in your final application. Then you’ll get very accurate results even for colors that are otherwise hard to detect.

from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.A)

# First, decide which objects you want to detect.
# Then measure their color with the hsv() method,
# as shown in the previous example. Write them down
# as shown below. The name is optional, but it is
# useful when you print the color value.
green = Color(h=132, s=94, v=26, name='GREEN_BRICK')
magenta = Color(h=348, s=96, v=40, name='MAGENTA_BRICK')
brown = Color(h=17, s=78, v=15, name='BROWN_BRICK')
red = Color(h=359, s=97, v=39, name='RED_BRICK')

# Put your colors in a list or tuple.
# Including None is optional. Just omit it if
# you always want to get one of your colors.
my_colors = (green, magenta, brown, red, None)

# Save your colors.
sensor.detectable_colors(my_colors)

# color() works as usual, but it only
# returns one of your specified colors.
while True:
    color = sensor.color()

    # Print the color.
    print(color)

    # Check which one it is.
    if color == magenta:
        print("It works!")

    # Wait so we can read it.
    wait(100)
hsv()

Scans the color of a surface.

This method is similar to color(), but it gives the full range of hue, saturation and brightness values, instead of rounding it to the nearest detectable color.

Returns:Measured color. The color is described by a hue (0–359), a saturation (0–100), and a brightness value (0–100).
Return type:Color
detectable_colors(colors)

Configures which colors the color() method should detect.

Specify only colors that you wish to detect in your application. This way, the full-color measurements are rounded to the nearest desired color, and other colors are ignored. This improves reliability.

If you give no arguments, the currently chosen colors will be returned as a tuple.

Parameters:colors (list) – List of Color objects: the colors that you want to detect. You can pick standard colors such as Color.MAGENTA, or provide your own colors like Color(h=348, s=96, v=40, name='MY_MAGENTA_BRICK') for even better results. You measure your own colors with the hsv() method.

Built-in light

This sensor has a built-in light. You can make it red, green, blue, or turn it off. If you use the sensor to measure something afterwards, the light automatically turns back on at the default color for that sensing method.

Show/hide examples

Example: Blinking the built-in light

from pybricks.pupdevices import ColorDistanceSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.A)

# Repeat forever.
while True:

    # If the sensor sees an object nearby.
    if sensor.distance() <= 40:

        # Then blink the light red/blue 5 times.
        for i in range(5):
            sensor.light.on(Color.RED)
            wait(30)
            sensor.light.on(Color.BLUE)
            wait(30)
    else:
        # If the sensor sees nothing
        # nearby, just wait briefly.
        wait(10)
light.on(color)

Turns on the light at the specified color.

Parameters:color (Color) – Color of the light.
light.off()

Turns off the light.

Power Functions

The ColorDistanceSensor can send infrared signals to control Power Functions infrared receivers. You can use this technique to control medium, large, extra large, and train motors. The infrared range is limited to about 30 cm, depending on the angle and ambient conditions.

_images/pfmotor.png

Figure 20 Powered Up ColorDistanceSensor (left), Power Functions infrared receiver (middle), and a Power Functions motor (right). Here, the receiver uses channel 1 with a motor on the red port.

Show/hide examples

Example 1: Control a Power Functions motor

from pybricks.pupdevices import ColorDistanceSensor, PFMotor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.B)

# Initialize a motor on channel 1, on the red output.
motor = PFMotor(sensor, 1, Color.RED)

# Rotate and then stop.
motor.dc(100)
wait(1000)
motor.stop()
wait(1000)

# Rotate the other way at half speed, and then stop.
motor.dc(-50)
wait(1000)
motor.stop()

Example 2: Controlling multiple Power Functions motors

from pybricks.pupdevices import ColorDistanceSensor, PFMotor
from pybricks.parameters import Port, Color, Direction
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorDistanceSensor(Port.B)

# You can use multiple motors on different channels.
arm = PFMotor(sensor, 1, Color.BLUE)
wheel = PFMotor(sensor, 4, Color.RED, Direction.COUNTERCLOCKWISE)

# Accelerate both motors. Only these values are available.
# Other values will be rounded down to the nearest match.
for duty in [15, 30, 45, 60, 75, 90, 100]:
    arm.dc(duty)
    wheel.dc(duty)
    wait(1000)

# To make the signal more reliable, there is a short
# pause between commands. So, they change speed and
# stop at a slightly different time.

# Brake both motors.
arm.brake()
wheel.brake()
class PFMotor(sensor, channel, color, positive_direction=Direction.CLOCKWISE)

Control Power Functions motors with the infrared functionality of the ColorDistanceSensor.

Parameters:
  • sensor (ColorDistanceSensor) – Sensor object.
  • channel (int) – Channel number of the receiver: 1, 2, 3, or 4.
  • color (Color) – Color marker on the receiver: Color.BLUE or Color.RED
  • positive_direction (Direction) – Which direction the motor should turn when you give a positive duty cycle value.
dc(duty)

Rotates the motor at a given duty cycle (also known as “power”).

Parameters:duty (percentage: %) – The duty cycle (-100.0 to 100).
stop()

Stops the motor and lets it spin freely.

The motor gradually stops due to friction.

brake()

Passively brakes the motor.

The motor stops due to friction, plus the voltage that is generated while the motor is still moving.

Color Sensor

_images/sensor_color_lights_label.png

Show/hide examples

Example 1: Measuring color and reflection

from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorSensor(Port.A)

while True:
    # Read the color and reflection
    color = sensor.color()
    reflection = sensor.reflection()

    # Print the measured color and reflection.
    print(color, reflection)

    # Move the sensor around and see how
    # well you can detect colors.

    # Wait so we can read the value.
    wait(100)

Example 2: Waiting for a color

from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorSensor(Port.A)


# This is a function that waits for a desired color.
def wait_for_color(desired_color):
    # While the color is not the desired color, we keep waiting.
    while sensor.color() != desired_color:
        wait(20)


# Now we use the function we just created above.
while True:

    # Here you can make your train/vehicle go forward.

    print("Waiting for red ...")
    wait_for_color(Color.RED)

    # Here you can make your train/vehicle go backward.

    print("Waiting for blue ...")
    wait_for_color(Color.BLUE)
class ColorSensor(port)

LEGO® SPIKE Color Sensor.

Parameters:port (Port) – Port to which the sensor is connected.
color(surface=True)

Scans the color of a surface or an external light source.

You choose which colors are detected using the detectable_colors() method. By default, it detects Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.WHITE, or None.

Parameters:surface (bool) – Choose true to scan the color of objects and surfaces. Choose false to scan the color of screens and other external light sources.
Returns:Detected color.
Return type:Color
reflection()

Measures the reflection of a surface.

Returns:Reflection, ranging from 0.0 (no reflection) to 100.0 (high reflection).
Return type:percentage: %
ambient()

Measures the ambient light intensity.

Returns:Ambient light intensity, ranging from 0 (dark) to 100 (bright).
Return type:percentage: %

Advanced color sensing

Show/hide examples

Example 1: Reading hue, saturation, and value

from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorSensor(Port.A)

while True:
    # The standard color() method always "rounds" the
    # measurement to the nearest "whole" color.
    # That's useful for most applications.

    # But you can get the original hue, saturation,
    # and value without "rounding", as follows:
    color = sensor.hsv()

    # Print the results.
    print(color)

    # Wait so we can read the value.
    wait(500)

Example 2: Changing the detectable colors

By default, the sensor is configured to detect red, yellow, green, blue, white, or None, which suits many applications.

For better results in your application, you can measure your desired colors in advance, and tell the sensor to look only for those colors. Be sure to measure them at the same distance and light conditions as in your final application. Then you’ll get very accurate results even for colors that are otherwise hard to detect.

from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorSensor(Port.A)

# First, decide which objects you want to detect.
# Then measure their color with the hsv() method,
# as shown in the previous example. Write them down
# as shown below. The name is optional, but it is
# useful when you print the color value.
green = Color(h=132, s=94, v=26, name='GREEN_BRICK')
magenta = Color(h=348, s=96, v=40, name='MAGENTA_BRICK')
brown = Color(h=17, s=78, v=15, name='BROWN_BRICK')
red = Color(h=359, s=97, v=39, name='RED_BRICK')

# Put your colors in a list or tuple.
# Including None is optional. Just omit it if
# you always want to get one of your colors.
my_colors = (green, magenta, brown, red, None)

# Save your colors.
sensor.detectable_colors(my_colors)

# color() works as usual, but it only
# returns one of your specified colors.
while True:
    color = sensor.color()

    # Print the color.
    print(color)

    # Check which one it is.
    if color == magenta:
        print("It works!")

    # Wait so we can read it.
    wait(100)

Example 3: Reading ambient hue, saturation, value, and color

from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorSensor(Port.A)

# Repeat forever.
while True:

    # Get the ambient color values. Instead of scanning the color of a surface,
    # this lets you scan the color of light sources like lamps or screens.
    hsv = sensor.hsv(surface=False)
    color = sensor.color(surface=False)

    # Get the ambient light intensity.
    ambient = sensor.ambient()

    # Print the measurements.
    print(hsv, color, ambient)

    # Point the sensor at a computer screen or colored light. Watch the color.
    # Also, cover the sensor with your hands and watch the ambient value.

    # Wait so we can read the printed line
    wait(100)
hsv(surface=True)

Scans the color of a surface or an external light source.

This method is similar to color(), but it gives the full range of hue, saturation and brightness values, instead of rounding it to the nearest detectable color.

Parameters:surface (bool) – Choose true to scan the color of objects and surfaces. Choose false to scan the color of screens and other external light sources.
Returns:Measured color. The color is described by a hue (0–359), a saturation (0–100), and a brightness value (0–100).
Return type:Color
detectable_colors(colors)

Configures which colors the color() method should detect.

Specify only colors that you wish to detect in your application. This way, the full-color measurements are rounded to the nearest desired color, and other colors are ignored. This improves reliability.

If you give no arguments, the currently chosen colors will be returned as a tuple.

Parameters:colors (list) – List of Color objects: the colors that you want to detect. You can pick standard colors such as Color.MAGENTA, or provide your own colors like Color(h=348, s=96, v=40, name='MY_MAGENTA_BRICK') for even better results. You measure your own colors with the hsv() method.

Built-in lights

This sensor has 3 built-in lights. You can adjust the brightness of each light. If you use the sensor to measure something, the lights will be turned on or off as needed for the measurement.

Show/hide examples

Example: Blinking the built-in lights

from pybricks.pupdevices import ColorSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
sensor = ColorSensor(Port.A)

# Repeat forever.
while True:

    # Turn on one light at a time, at half the brightness.
    # Do this for all 3 lights and repeat that 5 times.
    for i in range(5):
        sensor.lights.on(50, 0, 0)
        wait(100)
        sensor.lights.on(0, 50, 0)
        wait(100)
        sensor.lights.on(0, 0, 50)
        wait(100)

    # Turn all lights on at maximum brightness.
    sensor.lights.on(100)
    wait(500)

    # Turn all lights off.
    sensor.lights.off()
    wait(500)
lights.on(brightness)

Turns on the lights at the specified brightness.

Parameters:brightness (tuple of brightness: %) – Brightness of each light, in the order shown above. If you give one brightness value instead of a tuple, all lights get the same brightness.
lights.off()

Turns off all the lights.

Ultrasonic Sensor

_images/sensor_ultrasonic_lights_label.png

Show/hide examples

Example 1: Measuring distance and switching on the lights

from pybricks.pupdevices import UltrasonicSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
eyes = UltrasonicSensor(Port.A)

while True:
    # Print the measured distance.
    print(eyes.distance())

    # If an object is detected closer than 500mm:
    if eyes.distance() < 500:
        # Turn the lights on.
        eyes.lights.on(100)
    else:
        # Turn the lights off.
        eyes.lights.off()

    # Wait some time so we can read what is printed.
    wait(100)

Example 2: Using math to gradually change the brightness of the lights

from pybricks.pupdevices import UltrasonicSensor
from pybricks.parameters import Port
from pybricks.tools import wait, StopWatch

# The math module is part of standard MicroPython:
# https://docs.micropython.org/en/latest/library/math.html
from math import pi, sin

# Initialize the sensor.
eyes = UltrasonicSensor(Port.A)

# Initialize a timer.
watch = StopWatch()

# We want one full light cycle to last three seconds.
PERIOD = 3000

while True:
    # The phase is where we are in the unit circle now.
    phase = watch.time()/PERIOD*2*pi

    # Each light follows a sine wave with a mean of 50, with an amplitude of 50.
    # We offset this sine wave by 90 degrees for each light, so that all the
    # lights do something different.
    brightness = [sin(phase + offset*pi/2) * 50 + 50 for offset in range(4)]

    # Set the brightness values for all lights. The * symbol unpacks the list
    # of brightness values into separate arguments.
    eyes.lights.on(*brightness)

    # Wait some time.
    wait(50)
class UltrasonicSensor(port)

LEGO® SPIKE Color Sensor.

Parameters:port (Port) – Port to which the sensor is connected.
distance()

Measures the distance between the sensor and an object using ultrasonic sound waves.

Returns:Measured distance. If no valid distance was measured, it returns 2000 mm.
Return type:distance: mm
presence()

Checks for the presence of other ultrasonic sensors by detecting ultrasonic sounds.

Returns:True if ultrasonic sounds are detected, False if not.
Return type:bool

Built-in lights

This sensor has 4 built-in lights. You can adjust the brightness of each light.

lights.on(brightness)

Turns on the lights at the specified brightness.

Parameters:brightness (tuple of brightness: %) – Brightness of each light, in the order shown above. If you give one brightness value instead of a tuple, all lights get the same brightness.
lights.off()

Turns off all the lights.

Force Sensor

_images/sensor_force.png

Show/hide examples

Example 1: Measuring force and movement

from pybricks.pupdevices import ForceSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
button = ForceSensor(Port.A)

while True:
    # Read all the information we can get from this sensor.
    force = button.force()
    dist = button.distance()
    press = button.pressed()
    touch = button.touched()

    # Print the values
    print("Force", force, "Dist:", dist, "Pressed:", press, "Touched:", touch)

    # Push the sensor button see what happens to the values.

    # Wait some time so we can read what is printed.
    wait(200)

Example 2: Measuring peak force

from pybricks.pupdevices import ForceSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
button = ForceSensor(Port.A)


# This function waits until the button is pushed. It keeps track of the maximum
# detected force until the button is released. Then it returns the maximum.
def wait_for_force():

    # Wait for a force, by doing nothing for as long the force is nearly zero.
    print("Waiting for force.")
    while button.force() <= 0.1:
        wait(10)

    # Now we wait for the release, by waiting for the force to be zero again.
    print("Waiting for release.")

    # While we wait for that to happen, we keep reading the force and remember
    # the maximum force. We do this by initializing the maximum at 0, and
    # updating it each time we detect a bigger force.
    maximum = 0
    force = 10
    while force > 0.1:
        # Read the force.
        force = button.force()

        # Update the maximum if the measured force is larger.
        if force > maximum:
            maximum = force

        # Wait and then measure again.
        wait(10)

    # Return the maximum force.
    return maximum


# Keep waiting for the sensor button to be pushed. When it is, display
# the peak force and repeat.
while True:
    peak = wait_for_force()
    print("Released. Peak force: {0} N\n".format(peak))
class ForceSensor(port)

LEGO® SPIKE Force Sensor.

Parameters:port (Port) – Port to which the sensor is connected.
force()

Measures the force exerted on the sensor.

Returns:Measured force (up to approximately 10.00 N).
Return type:force: N
distance()

Measures by how much the sensor button has moved.

Returns:How much the sensor button has moved (up to approximately 8.00 mm).
Return type:distance: mm
pressed(force=3)

Checks if the sensor button is pressed.

Parameters:force (force: N) – Minimum force to be considered pressed.
Returns:True if the sensor is pressed, False if it is not.
Return type:bool
touched()

Checks if the sensor is touched.

This is similar to pressed(), but it detects slight movements of the button even when the measured force is still considered zero.

Returns:True if the sensor is touched or pressed, False if it is not.
Return type:bool

Infrared Sensor

_images/sensor_proximity.png

Show/hide example

Example: Measuring distance, object count, and reflection

from pybricks.pupdevices import InfraredSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
ir = InfraredSensor(Port.A)

while True:
    # Read all the information we can get from this sensor.
    dist = ir.distance()
    count = ir.count()
    ref = ir.reflection()

    # Print the values
    print("Distance:", dist, "Count:", count, "Reflection:", ref)

    # Move the sensor around and move your hands in front
    # of it to see what happens to the values.

    # Wait some time so we can read what is printed.
    wait(200)
class InfraredSensor(port)

LEGO® Powered Up Infrared Sensor.

Parameters:port (Port) – Port to which the sensor is connected.
distance()

Measures the relative distance between the sensor and an object using infrared light.

Returns:Relative distance ranging from 0 (closest) to 100 (farthest).
Return type:relative distance: %
reflection()

Measures the reflection of a surface using an infrared light.

Returns:Reflection, ranging from 0.0 (no reflection) to 100.0 (high reflection).
Return type:percentage: %
count()

Counts the number of objects that have passed by the sensor.

Returns:Number of objects counted.
Return type:int

Tilt Sensor

_images/sensor_tilt.png

Show/hide example

Example: Measuring pitch and roll

from pybricks.pupdevices import TiltSensor
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the sensor.
accel = TiltSensor(Port.A)

while True:
    # Read the tilt angles relative to the horizontal plane.
    pitch, roll = accel.tilt()

    # Print the values
    print("Pitch:", pitch, "Roll:", roll)

    # Wait some time so we can read what is printed.
    wait(100)
class TiltSensor(port)

LEGO® Powered Up Tilt Sensor.

Parameters:port (Port) – Port to which the sensor is connected.
tilt()

Measures the tilt relative to the horizontal plane.

Returns:Tuple of pitch and roll angles.
Return type:(angle: deg, angle: deg)

Light

_images/light.png

Show/hide examples

Example 1: Making the light blink

from pybricks.pupdevices import Light
from pybricks.parameters import Port
from pybricks.tools import wait

# Initialize the light.
light = Light(Port.A)

# Blink the light forever.
while True:
    # Turn the light on at 100% brightness.
    light.on(100)
    wait(500)

    # Turn the light off.
    light.off()
    wait(500)

Example 2: Using math to gradually change the brightness of the light

from pybricks.pupdevices import Light
from pybricks.parameters import Port
from pybricks.tools import wait, StopWatch

# The math module is part of standard MicroPython:
# https://docs.micropython.org/en/latest/library/math.html
from math import pi, cos

# Initialize the light and a StopWatch.
light = Light(Port.A)
watch = StopWatch()

# Cosine pattern properties.
PERIOD = 2000
MAX = 100

# Make the brightness fade in and out.
while True:
    # Get phase of the cosine.
    phase = watch.time()/PERIOD*2*pi

    # Evaluate the brightness.
    brightness = (0.5 - 0.5*cos(phase))*MAX

    # Set light brightness and wait a bit.
    light.on(brightness)
    wait(10)
class Light(port)

LEGO® Powered Up Light.

Parameters:port (Port) – Port to which the device is connected.
on(brightness=100)

Turns on the light at the specified brightness.

Parameters:brightness (brightness: %) – Brightness of the light.
off()

Turns off the light.