RoboDoz3r
Python code and building instructions for the LEGO MINDSTORMS EV3 Official Fan Creations (31313).

This robot bulldozer can be controlled using the IR Beacon or it can drive on it’s own, avoiding obstacles while clearing and pushing things with its bulldozer bucket.
This program requires LEGO® MINDSTORMS® EV3 MicroPython v2.0 downloadable at https://education.lego.com/en-us/support/mindstorms-ev3/python-for-ev3.
Control RoboDoz3r as follows:
-
RoboDoz3r starts with the User-Controlled Mode. You can switch between the User-Controlled Mode and the Autonomous Mode by pressing the Touch Sensor.
-
User-Controlled Mode:
- Drive RoboDoz3r around according to instructions from Channel 1 of the IR Remote Control:
- 2 Top/Up Buttons together: drive forward
- 2 Bottom/Down Buttons together: drive backward
- Top-Left/Red-Up and Bottom-Right/Blue-Down together: turn left on the spot
- Top-Right/Blue-Up and Bottom-Left/Red-Down together: turn right on the spot
- Top-Left/Red-Up: turn left forward
- Top-Right/Blue-Up: turn right forward
- Bottom-Left/Red-Down: turn left backward
- Bottom-Right/Blue-Down: turn right backward
- Use Channel 4 of the IR Remote Control to make RoboDoz3r raise the shovel by pressing either Up button, or lower the shovel by pressing either Down button
- Drive RoboDoz3r around according to instructions from Channel 1 of the IR Remote Control:
-
Autonomous Mode: RoboDoz3r drives around on his own to clean up small things but avoids big obstacles by reversing and turning
The code for the RoboDoz3r
class is in robodoz3r.py
as follows:
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor, TouchSensor
from pybricks.parameters import Button, Direction, Port
from rc_tank_util import RemoteControlledTank
class RoboDoz3r(RemoteControlledTank):
WHEEL_DIAMETER = 24 # milimeters
AXLE_TRACK = 100 # milimeters
def __init__(
self,
left_motor_port: Port = Port.C, right_motor_port: Port = Port.B,
shovel_motor_port: Port = Port.A,
touch_sensor_port: Port = Port.S1,
ir_sensor_port: Port = Port.S4,
tank_drive_ir_beacon_channel: int = 1,
shovel_control_ir_beacon_channel: int = 4):
super().__init__(
wheel_diameter=self.WHEEL_DIAMETER, axle_track=self.AXLE_TRACK,
left_motor_port=left_motor_port, right_motor_port=right_motor_port,
polarity='inversed',
ir_sensor_port=ir_sensor_port,
ir_beacon_channel=tank_drive_ir_beacon_channel)
self.ev3_brick = EV3Brick()
self.shovel_motor = Motor(port=shovel_motor_port,
positive_direction=Direction.CLOCKWISE)
self.touch_sensor = TouchSensor(port=touch_sensor_port)
self.shovel_control_ir_beacon_channel = \
shovel_control_ir_beacon_channel
def raise_or_lower_shovel_by_ir_beacon(self):
"""
If the channel 4 is selected on the IR remote
then you can control raising and lowering the shovel on the RoboDoz3r.
- Raise the shovel by either Up button
- Raise the shovel by either Down button
"""
ir_beacon_button_pressed = \
set(self.ir_sensor.buttons(
channel=self.shovel_control_ir_beacon_channel))
# raise the shovel
if ir_beacon_button_pressed.intersection(
{Button.LEFT_UP, Button.RIGHT_UP}):
self.shovel_motor.run(speed=100)
# lower the shovel
elif ir_beacon_button_pressed.intersection(
{Button.LEFT_DOWN, Button.RIGHT_DOWN}):
self.shovel_motor.run(speed=-100)
else:
self.shovel_motor.hold()
RoboDoz3r
uses a remote-controlled tank driving utility whose code is in rc_tank_util.py
as follows:
from pybricks.ev3devices import Motor, InfraredSensor
from pybricks.robotics import DriveBase
from pybricks.parameters import Button, Direction, Port
class RemoteControlledTank:
"""
This reusable mixin provides the capability of driving a robot
with a Driving Base by the IR beacon
"""
def __init__(
self,
wheel_diameter: float, axle_track: float, # both in milimeters
left_motor_port: Port = Port.B, right_motor_port: Port = Port.C,
polarity: str = 'normal',
ir_sensor_port: Port = Port.S4, ir_beacon_channel: int = 1):
if polarity == 'normal':
left_motor = Motor(port=left_motor_port,
positive_direction=Direction.CLOCKWISE)
right_motor = Motor(port=right_motor_port,
positive_direction=Direction.CLOCKWISE)
else:
left_motor = Motor(port=left_motor_port,
positive_direction=Direction.COUNTERCLOCKWISE)
right_motor = Motor(port=right_motor_port,
positive_direction=Direction.COUNTERCLOCKWISE)
self.driver = DriveBase(left_motor=left_motor,
right_motor=right_motor,
wheel_diameter=wheel_diameter,
axle_track=axle_track)
self.ir_sensor = InfraredSensor(port=ir_sensor_port)
self.ir_beacon_channel = ir_beacon_channel
def drive_by_ir_beacon(
self,
speed: float = 1000, # mm/s
turn_rate: float = 90 # rotational speed deg/s
):
ir_beacon_button_pressed = \
set(self.ir_sensor.buttons(channel=self.ir_beacon_channel))
# forward
if ir_beacon_button_pressed == {Button.LEFT_UP, Button.RIGHT_UP}:
self.driver.drive(
speed=speed,
turn_rate=0)
# backward
elif ir_beacon_button_pressed == {Button.LEFT_DOWN, Button.RIGHT_DOWN}:
self.driver.drive(
speed=-speed,
turn_rate=0)
# turn left on the spot
elif ir_beacon_button_pressed == {Button.LEFT_UP, Button.RIGHT_DOWN}:
self.driver.drive(
speed=0,
turn_rate=-turn_rate)
# turn right on the spot
elif ir_beacon_button_pressed == {Button.RIGHT_UP, Button.LEFT_DOWN}:
self.driver.drive(
speed=0,
turn_rate=turn_rate)
# turn left forward
elif ir_beacon_button_pressed == {Button.LEFT_UP}:
self.driver.drive(
speed=speed,
turn_rate=-turn_rate)
# turn right forward
elif ir_beacon_button_pressed == {Button.RIGHT_UP}:
self.driver.drive(
speed=speed,
turn_rate=turn_rate)
# turn left backward
elif ir_beacon_button_pressed == {Button.LEFT_DOWN}:
self.driver.drive(
speed=-speed,
turn_rate=turn_rate)
# turn right backward
elif ir_beacon_button_pressed == {Button.RIGHT_DOWN}:
self.driver.drive(
speed=-speed,
turn_rate=-turn_rate)
# otherwise stop
else:
self.driver.stop()
The code for the main program is in main.py
as follows:
#!/usr/bin/env pybricks-micropython
from pybricks.media.ev3dev import SoundFile
from pybricks.tools import wait
from time import time
from robodoz3r import RoboDoz3r
robodoz3r = RoboDoz3r()
robodoz3r.ev3_brick.screen.print('ROBODOZ3R')
robodoz3r.ev3_brick.speaker.play_file(SoundFile.MOTOR_START)
motor_idle_start_time = time()
while time() - motor_idle_start_time <= 2:
robodoz3r.ev3_brick.speaker.play_file(SoundFile.MOTOR_IDLE)
while True:
while not robodoz3r.touch_sensor.pressed():
robodoz3r.raise_or_lower_shovel_by_ir_beacon()
robodoz3r.drive_by_ir_beacon(speed=1000)
wait(10)
robodoz3r.ev3_brick.speaker.play_file(SoundFile.AIRBRAKE)
while not robodoz3r.touch_sensor.pressed():
if robodoz3r.ir_sensor.distance() < 50:
robodoz3r.driver.stop()
wait(1000)
robodoz3r.driver.straight(distance=-100)
robodoz3r.driver.turn(angle=90)
else:
robodoz3r.driver.drive(
speed=500,
turn_rate=0)
wait(10)
robodoz3r.ev3_brick.speaker.play_file(SoundFile.AIRBRAKE)
This project was submitted by The Lương-Phạm Family.