From 53f292d2abc3c4dcc401d185cea57c7b657da29b Mon Sep 17 00:00:00 2001 From: Antoni Luong Pham Date: Sat, 17 Oct 2020 12:18:32 -0700 Subject: [PATCH] sets/ev3/home_bonus: add Dinor3x program --- sets/ev3/home_bonus/dinor3x/.gitignore | 3 + .../dinor3x/.vscode/extensions.json | 14 ++ .../home_bonus/dinor3x/.vscode/launch.json | 16 ++ .../home_bonus/dinor3x/.vscode/settings.json | 7 + sets/ev3/home_bonus/dinor3x/README.md | 24 ++ sets/ev3/home_bonus/dinor3x/dinor3x.py | 218 ++++++++++++++++++ sets/ev3/home_bonus/dinor3x/main.py | 14 ++ 7 files changed, 296 insertions(+) create mode 100644 sets/ev3/home_bonus/dinor3x/.gitignore create mode 100644 sets/ev3/home_bonus/dinor3x/.vscode/extensions.json create mode 100644 sets/ev3/home_bonus/dinor3x/.vscode/launch.json create mode 100644 sets/ev3/home_bonus/dinor3x/.vscode/settings.json create mode 100644 sets/ev3/home_bonus/dinor3x/README.md create mode 100644 sets/ev3/home_bonus/dinor3x/dinor3x.py create mode 100644 sets/ev3/home_bonus/dinor3x/main.py diff --git a/sets/ev3/home_bonus/dinor3x/.gitignore b/sets/ev3/home_bonus/dinor3x/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/sets/ev3/home_bonus/dinor3x/.vscode/extensions.json b/sets/ev3/home_bonus/dinor3x/.vscode/extensions.json new file mode 100644 index 0000000..bfd14ea --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "lego-education.ev3-micropython" + ], + + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "ms-python.python" + ] +} diff --git a/sets/ev3/home_bonus/dinor3x/.vscode/launch.json b/sets/ev3/home_bonus/dinor3x/.vscode/launch.json new file mode 100644 index 0000000..05a0a78 --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + + "configurations": [ + { + "name": "Download and Run", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/main.py", + "interactiveTerminal": false + } + ] +} diff --git a/sets/ev3/home_bonus/dinor3x/.vscode/settings.json b/sets/ev3/home_bonus/dinor3x/.vscode/settings.json new file mode 100644 index 0000000..42a109f --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/.vscode/settings.json @@ -0,0 +1,7 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "editor.rulers": [79], + "python.linting.enabled": true +} diff --git a/sets/ev3/home_bonus/dinor3x/README.md b/sets/ev3/home_bonus/dinor3x/README.md new file mode 100644 index 0000000..842b957 --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/README.md @@ -0,0 +1,24 @@ +# Example LEGO® MINDSTORMS® EV3 Dinor3x Program + +This program requires LEGO® EV3 MicroPython v2.0 downloadable at https://education.lego.com/en-us/support/mindstorms-ev3/python-for-ev3. + +Building instructions can be found at https://www.lego.com/en-us/themes/mindstorms/buildarobot. + +NOTE: please add a Color Sensor to Dinor3x's back or tail. + +Dinor3x works as follows: + +- Dinor3x roars when the Beacon button is pressed + +- Dinor3x changes its speed when detecting some colors + - Red: walk fast + - Green: walk normally + - White: walk slowly + +- Dinor3x walks or turns according to instructions from the IR Beacon + - 2 top/up buttons together: walk forward + - 2 bottom/down buttons together: walk backward + - Top Left / Red Up: turn left on the spot + - Top Right / Blue Up: turn right on the spot + - Bottom Left / Red Down: stop + - Bottom Right / Blue Down: calibrate to make the legs straight diff --git a/sets/ev3/home_bonus/dinor3x/dinor3x.py b/sets/ev3/home_bonus/dinor3x/dinor3x.py new file mode 100644 index 0000000..9862c27 --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/dinor3x.py @@ -0,0 +1,218 @@ +from pybricks.hubs import EV3Brick +from pybricks.ev3devices import Motor, TouchSensor, ColorSensor, InfraredSensor +from pybricks.media.ev3dev import SoundFile +from pybricks.parameters import Button, Color, Direction, Port, Stop + + +class Dinor3x: + FAST_WALK_SPEED = 800 + NORMAL_WALK_SPEED = 400 + SLOW_WALK_SPEED = 200 + + def __init__( + self, + jaw_motor_port: Port = Port.A, + left_motor_port: Port = Port.B, right_motor_port: Port = Port.C, + touch_sensor_port: Port = Port.S1, + color_sensor_port: Port = Port.S3, + ir_sensor_port: Port = Port.S4, ir_beacon_channel: int = 1): + self.ev3_brick = EV3Brick() + + self.jaw_motor = Motor(port=jaw_motor_port, + positive_direction=Direction.CLOCKWISE) + + self.left_motor = Motor(port=left_motor_port, + positive_direction=Direction.CLOCKWISE) + self.right_motor = Motor(port=right_motor_port, + positive_direction=Direction.CLOCKWISE) + + self.touch_sensor = TouchSensor(port=touch_sensor_port) + + self.color_sensor = ColorSensor(port=color_sensor_port) + + self.ir_sensor = InfraredSensor(port=ir_sensor_port) + self.ir_beacon_channel = ir_beacon_channel + + self.roaring = False + self.walk_speed = self.NORMAL_WALK_SPEED + + def roar_by_ir_beacon(self): + """ + Dinor3x roars when the Beacon button is pressed + """ + if Button.BEACON in \ + self.ir_sensor.buttons(channel=self.ir_beacon_channel): + self.roaring = True + self.open_mouth() + self.roar() + + elif self.roaring: + self.roaring = False + self.close_mouth() + + def change_speed_by_color(self): + """ + Dinor3x changes its speed when detecting some colors + - Red: walk fast + - Green: walk normally + - White: walk slowly + """ + if self.color_sensor.color() == Color.RED: + self.ev3_brick.speaker.say(text='RUN!') + self.walk_speed = self.FAST_WALK_SPEED + self.walk(speed=self.walk_speed) + + elif self.color_sensor.color() == Color.GREEN: + self.ev3_brick.speaker.say(text='Normal') + self.walk_speed = self.NORMAL_WALK_SPEED + self.walk(speed=self.walk_speed) + + elif self.color_sensor.color() == Color.WHITE: + self.ev3_brick.speaker.say(text='slow...') + self.walk_speed = self.SLOW_WALK_SPEED + self.walk(speed=self.walk_speed) + + def walk_by_ir_beacon(self): + """ + Dinor3x walks or turns according to instructions from the IR Beacon + - 2 top/up buttons together: walk forward + - 2 bottom/down buttons together: walk backward + - Top Left / Red Up: turn left on the spot + - Top Right / Blue Up: turn right on the spot + - Bottom Left / Red Down: stop + - Bottom Right / Blue Down: calibrate to make the legs straight + """ + ir_buttons_pressed = \ + set(self.ir_sensor.buttons(channel=self.ir_beacon_channel)) + + # forward + if ir_buttons_pressed == {Button.LEFT_UP, Button.RIGHT_UP}: + self.walk(speed=self.walk_speed) + + # backward + elif ir_buttons_pressed == {Button.LEFT_DOWN, Button.RIGHT_DOWN}: + self.walk(speed=-self.walk_speed) + + # turn left on the spot + elif ir_buttons_pressed == {Button.LEFT_UP}: + self.turn(speed=self.walk_speed) + + # turn right on the spot + elif ir_buttons_pressed == {Button.RIGHT_UP}: + self.turn(speed=-self.walk_speed) + + # stop + elif ir_buttons_pressed == {Button.LEFT_DOWN}: + self.left_motor.hold() + self.right_motor.hold() + + # calibrate legs + elif ir_buttons_pressed == {Button.RIGHT_DOWN}: + self.calibrate_legs() + + def calibrate_legs(self): + self.left_motor.run(speed=100) + self.right_motor.run(speed=200) + + while self.touch_sensor.pressed(): + pass + + self.left_motor.hold() + self.right_motor.hold() + + self.left_motor.run(speed=400) + + while not self.touch_sensor.pressed(): + pass + + self.left_motor.hold() + + self.left_motor.run_angle( + rotation_angle=-0.2 * 360, + speed=500, + then=Stop.HOLD, + wait=True) + + self.right_motor.run(speed=400) + + while not self.touch_sensor.pressed(): + pass + + self.right_motor.hold() + + self.right_motor.run_angle( + rotation_angle=-0.2 * 360, + speed=500, + then=Stop.HOLD, + wait=True) + + self.left_motor.reset_angle(angle=0) + self.right_motor.reset_angle(angle=0) + + def walk(self, speed: float = 400): + self.calibrate_legs() + + self.left_motor.run(speed=-speed) + self.right_motor.run(speed=-speed) + + def turn(self, speed: float = 400): + self.calibrate_legs() + + if speed >= 0: + self.left_motor.run_angle( + rotation_angle=180, + speed=speed, + then=Stop.HOLD, + wait=True) + + else: + self.right_motor.run_angle( + rotation_angle=180, + speed=-speed, + then=Stop.HOLD, + wait=True) + + self.left_motor.run(speed=speed) + self.right_motor.run(speed=-speed) + + def close_mouth(self): + self.jaw_motor.run_time( + speed=-200, + time=1000, + then=Stop.COAST, + wait=False) + + def open_mouth(self): + self.jaw_motor.run_time( + speed=200, + time=1000, + then=Stop.COAST, + wait=False) + + def roar(self): + self.ev3_brick.speaker.play_file(file=SoundFile.T_REX_ROAR) + + self.jaw_motor.run_angle( + speed=400, + rotation_angle=-60, + then=Stop.HOLD, + wait=True) + + for _ in range(12): + self.jaw_motor.run_time( + speed=-400, + time=0.05 * 1000, + then=Stop.HOLD, + wait=True) + + self.jaw_motor.run_time( + speed=400, + time=0.05 * 1000, + then=Stop.HOLD, + wait=True) + + self.jaw_motor.run_time( + speed=200, + time=0.5 * 1000, + then=Stop.COAST, + wait=True) diff --git a/sets/ev3/home_bonus/dinor3x/main.py b/sets/ev3/home_bonus/dinor3x/main.py new file mode 100644 index 0000000..fdec3f2 --- /dev/null +++ b/sets/ev3/home_bonus/dinor3x/main.py @@ -0,0 +1,14 @@ +#!/usr/bin/env pybricks-micropython + + +from dinor3x import Dinor3x + + +dino = Dinor3x() + +dino.close_mouth() + +while True: + dino.roar_by_ir_beacon() + dino.change_speed_by_color() + dino.walk_by_ir_beacon()