diff --git a/robots/ROBODOZ3R/README.md b/robots/ROBODOZ3R/README.md new file mode 100644 index 0000000..3ca24f4 --- /dev/null +++ b/robots/ROBODOZ3R/README.md @@ -0,0 +1,27 @@ +# ROBODOZ3R + +> Designed by Mark Crosbie. +> +> 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. + +The build instructions may be found at the official LEGO MINDSTROMS site [here](https://www.lego.com/cdn/cs/set/assets/bltfef825595f55768c/ROBODOZ3R.pdf) + +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 + +- Autonomous Mode: ROBODOZ3R drives around on his own to clean up small things but avoids big obstacles by reversing and turning diff --git a/robots/ROBODOZ3R/media/Airbrake.wav b/robots/ROBODOZ3R/media/Airbrake.wav new file mode 100644 index 0000000..9558ef2 Binary files /dev/null and b/robots/ROBODOZ3R/media/Airbrake.wav differ diff --git a/robots/ROBODOZ3R/media/Motor idle.wav b/robots/ROBODOZ3R/media/Motor idle.wav new file mode 100644 index 0000000..26c21f5 Binary files /dev/null and b/robots/ROBODOZ3R/media/Motor idle.wav differ diff --git a/robots/ROBODOZ3R/media/Motor start.wav b/robots/ROBODOZ3R/media/Motor start.wav new file mode 100644 index 0000000..d9df5a5 Binary files /dev/null and b/robots/ROBODOZ3R/media/Motor start.wav differ diff --git a/robots/ROBODOZ3R/media/Motor stop.wav b/robots/ROBODOZ3R/media/Motor stop.wav new file mode 100644 index 0000000..2021cb4 Binary files /dev/null and b/robots/ROBODOZ3R/media/Motor stop.wav differ diff --git a/robots/ROBODOZ3R/media/Start up.wav b/robots/ROBODOZ3R/media/Start up.wav new file mode 100644 index 0000000..1964566 Binary files /dev/null and b/robots/ROBODOZ3R/media/Start up.wav differ diff --git a/robots/ROBODOZ3R/rc_tank_util.py b/robots/ROBODOZ3R/rc_tank_util.py new file mode 100644 index 0000000..900f500 --- /dev/null +++ b/robots/ROBODOZ3R/rc_tank_util.py @@ -0,0 +1,105 @@ +from ev3dev2.motor import \ + Motor, LargeMotor, MoveSteering, MoveTank, \ + OUTPUT_B, OUTPUT_C +from ev3dev2.sensor import INPUT_4 +from ev3dev2.sensor.lego import InfraredSensor + + +class RemoteControlledTank: + """ + This reusable mixin provides the capability of driving a robot + with a Driving Base by the IR beacon + """ + def __init__( + self, + left_motor_port: str = OUTPUT_B, right_motor_port: str = OUTPUT_C, + motor_class=LargeMotor, polarity: str = Motor.POLARITY_NORMAL, + ir_sensor_port: str = INPUT_4, ir_beacon_channel: int = 1): + self.tank_driver = \ + MoveTank( + left_motor_port=left_motor_port, + right_motor_port=right_motor_port, + motor_class=motor_class) + + self.steer_driver = \ + MoveSteering( + left_motor_port=left_motor_port, + right_motor_port=right_motor_port, + motor_class=motor_class) + + self.tank_driver.left_motor.polarity = \ + self.tank_driver.right_motor.polarity = \ + self.steer_driver.left_motor.polarity = \ + self.steer_driver.right_motor.polarity = polarity + + self.ir_sensor = InfraredSensor(address=ir_sensor_port) + self.tank_drive_ir_beacon_channel = ir_beacon_channel + + def drive_by_ir_beacon(self, speed: float = 100): + # forward + if self.ir_sensor.top_left( + channel=self.tank_drive_ir_beacon_channel) and \ + self.ir_sensor.top_right( + channel=self.tank_drive_ir_beacon_channel): + self.tank_driver.on( + left_speed=speed, + right_speed=speed) + + # backward + elif self.ir_sensor.bottom_left( + channel=self.tank_drive_ir_beacon_channel) and \ + self.ir_sensor.bottom_right( + channel=self.tank_drive_ir_beacon_channel): + self.tank_driver.on( + left_speed=-speed, + right_speed=-speed) + + # turn left on the spot + elif self.ir_sensor.top_left( + channel=self.tank_drive_ir_beacon_channel) and \ + self.ir_sensor.bottom_right( + channel=self.tank_drive_ir_beacon_channel): + self.steer_driver.on( + steering=-100, + speed=speed) + + # turn right on the spot + elif self.ir_sensor.top_right( + channel=self.tank_drive_ir_beacon_channel) and \ + self.ir_sensor.bottom_left( + channel=self.tank_drive_ir_beacon_channel): + self.steer_driver.on( + steering=100, + speed=speed) + + # turn left forward + elif self.ir_sensor.top_left( + channel=self.tank_drive_ir_beacon_channel): + self.steer_driver.on( + steering=-50, + speed=speed) + + # turn right forward + elif self.ir_sensor.top_right( + channel=self.tank_drive_ir_beacon_channel): + self.steer_driver.on( + steering=50, + speed=speed) + + # turn left backward + elif self.ir_sensor.bottom_left( + channel=self.tank_drive_ir_beacon_channel): + self.tank_driver.on( + left_speed=0, + right_speed=-speed) + + # turn right backward + elif self.ir_sensor.bottom_right( + channel=self.tank_drive_ir_beacon_channel): + self.tank_driver.on( + left_speed=-speed, + right_speed=0) + + # otherwise stop + else: + self.tank_driver.off(brake=False) diff --git a/robots/ROBODOZ3R/robodoz3r.py b/robots/ROBODOZ3R/robodoz3r.py new file mode 100644 index 0000000..1323f08 --- /dev/null +++ b/robots/ROBODOZ3R/robodoz3r.py @@ -0,0 +1,139 @@ +#!/usr/bin/env micropython + + +from ev3dev2.motor import \ + Motor, LargeMotor, MediumMotor, \ + OUTPUT_A, OUTPUT_B, OUTPUT_C +from ev3dev2.sensor import INPUT_1, INPUT_4 +from ev3dev2.sensor.lego import TouchSensor +from ev3dev2.console import Console +from ev3dev2.sound import Sound + +from time import sleep, time + +from rc_tank_util import RemoteControlledTank + + +class RoboDoz3r(RemoteControlledTank): + def __init__( + self, + left_motor_port: str = OUTPUT_C, right_motor_port: str = OUTPUT_B, + shovel_motor_port: str = OUTPUT_A, + touch_sensor_port: str = INPUT_1, + ir_sensor_port: str = INPUT_4, + tank_drive_ir_beacon_channel: int = 1, + shovel_control_ir_beacon_channel: int = 4): + super().__init__( + left_motor_port=left_motor_port, right_motor_port=right_motor_port, + motor_class=LargeMotor, polarity=Motor.POLARITY_INVERSED, + ir_sensor_port=ir_sensor_port, + ir_beacon_channel=tank_drive_ir_beacon_channel) + + self.shovel_motor = MediumMotor(address=shovel_motor_port) + + self.touch_sensor = TouchSensor(address=touch_sensor_port) + + self.shovel_control_ir_beacon_channel = \ + shovel_control_ir_beacon_channel + + self.console = Console() + self.speaker = Sound() + + def raise_or_lower_shovel_once_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 + """ + # raise the shovel + if self.ir_sensor.top_left( + channel=self.shovel_control_ir_beacon_channel) or \ + self.ir_sensor.top_right( + channel=self.shovel_control_ir_beacon_channel): + self.shovel_motor.on( + speed=10, + brake=False, + block=False) + + # lower the shovel + elif self.ir_sensor.bottom_left( + channel=self.shovel_control_ir_beacon_channel) or \ + self.ir_sensor.bottom_right( + channel=self.shovel_control_ir_beacon_channel): + self.shovel_motor.on( + speed=-10, + brake=False, + block=False) + + else: + self.shovel_motor.off(brake=True) + + def main(self, driving_speed: float = 100): + self.console.text_at( + text='ROBODOZ3R', + column=2, + row=2, + reset_console=False, + inverse=False, + alignment='L') + + self.speaker.play_file( + wav_file='media/Motor start.wav', + volume=56, + play_type=Sound.PLAY_WAIT_FOR_COMPLETE) + + motor_idle_start_time = time() + while time() - motor_idle_start_time <= 2: + self.speaker.play_file( + wav_file='media/Motor idle.wav', + volume=51, + play_type=Sound.PLAY_WAIT_FOR_COMPLETE) + + while True: + while self.touch_sensor.is_released: + self.raise_or_lower_shovel_once_by_ir_beacon() + self.drive_by_ir_beacon(speed=driving_speed) + sleep(0.01) + + self.speaker.play_file( + wav_file='media/Airbrake.wav', + volume=100, + play_type=Sound.PLAY_WAIT_FOR_COMPLETE) + + while self.touch_sensor.is_released: + if self.ir_sensor.proximity < 50: + self.tank_driver.off(brake=True) + + sleep(1) + + self.tank_driver.on_for_seconds( + left_speed=-30, + right_speed=-30, + seconds=1, + brake=True, + block=True) + + self.tank_driver.on_for_seconds( + left_speed=50, + right_speed=-50, + seconds=1, + brake=True, + block=True) + + else: + self.tank_driver.on( + left_speed=50, + right_speed=50) + + sleep(0.01) + + self.speaker.play_file( + wav_file='media/Airbrake.wav', + volume=100, + play_type=Sound.PLAY_WAIT_FOR_COMPLETE) + + +if __name__ == '__main__': + ROBODOZ3R = RoboDoz3r() + ROBODOZ3R.main()