diff --git a/examples/ev3/bluetooth_client/.gitignore b/examples/ev3/bluetooth_client/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/bluetooth_client/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/bluetooth_client/.vscode/extensions.json b/examples/ev3/bluetooth_client/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/bluetooth_client/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/bluetooth_client/.vscode/launch.json b/examples/ev3/bluetooth_client/.vscode/launch.json new file mode 100644 index 0000000..4b8308d --- /dev/null +++ b/examples/ev3/bluetooth_client/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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}/client.py" + } + ] +} diff --git a/examples/ev3/bluetooth_client/.vscode/settings.json b/examples/ev3/bluetooth_client/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/bluetooth_client/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/bluetooth_client/client.py b/examples/ev3/bluetooth_client/client.py new file mode 100644 index 0000000..f90ab06 --- /dev/null +++ b/examples/ev3/bluetooth_client/client.py @@ -0,0 +1,25 @@ +#!/usr/bin/env pybricks-micropython + +# Before running this program, make sure the client and server EV3 bricks are +# paired using Bluetooth, but do NOT connect them. The program will take care +# of establishing the connection. + +# The server must be started before the client! + +from pybricks.messaging import BluetoothMailboxClient, TextMailbox + +# This is the name of the remote EV3 or PC we are connecting to. +SERVER = 'ev3dev' + +client = BluetoothMailboxClient() +mbox = TextMailbox('greeting', client) + +print('establishing connection...') +client.connect(SERVER) +print('connected!') + +# In this program, the client sends the first message and then waits for the +# server to reply. +mbox.send('hello!') +mbox.wait() +print(mbox.read()) diff --git a/examples/ev3/bluetooth_pc/.vscode/launch.json b/examples/ev3/bluetooth_pc/.vscode/launch.json new file mode 100644 index 0000000..2c05c3c --- /dev/null +++ b/examples/ev3/bluetooth_pc/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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": "PC Bluetooth Example", + "type": "python", + "request": "launch", + "program": "pcclient.py", + "console": "integratedTerminal" + } + ] +} diff --git a/examples/ev3/bluetooth_pc/pcclient.py b/examples/ev3/bluetooth_pc/pcclient.py new file mode 100644 index 0000000..ffc1ee2 --- /dev/null +++ b/examples/ev3/bluetooth_pc/pcclient.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +from pybricks.messaging import BluetoothMailboxClient, TextMailbox + +# This demo makes your PC talk to an EV3 over Bluetooth. +# +# This is identical to the EV3 client example in ../bluetooth_client +# +# The only difference is that it runs in Python3 on your computer, thanks to +# the Python3 implementation of the messaging module that is included here. +# As far as the EV3 is concerned, it thinks it just talks to an EV3 client. +# +# So, the EV3 server example needs no further modifications. The connection +# procedure is also the same as documented in the messaging module docs: +# https://docs.pybricks.com/en/latest/messaging.html +# +# So, turn Bluetooth on on your PC and the EV3. You may need to make Bluetooth +# visible on the EV3. You can skip pairing if you already know the EV3 address. + +# This is the address of the server EV3 we are connecting to. +SERVER = 'CC:78:AB:D8:4E:F6' + +client = BluetoothMailboxClient() +mbox = TextMailbox('greeting', client) + +print('establishing connection...') +client.connect(SERVER) +print('connected!') + +# In this program, the client sends the first message and then waits for the +# server to reply. +mbox.send('hello!') +mbox.wait() +print(mbox.read()) diff --git a/examples/ev3/bluetooth_pc/pybricks/README.md b/examples/ev3/bluetooth_pc/pybricks/README.md new file mode 100644 index 0000000..0d854b1 --- /dev/null +++ b/examples/ev3/bluetooth_pc/pybricks/README.md @@ -0,0 +1,9 @@ +This is a partial implementation of the pybricks package that is normally +included in Pybricks MicroPython for EV3. It makes the PC look like an EV3 so +other EV3 bricks can connect to it and vice versa. + +It has the same end user API, so the same documentation applies: +https://docs.pybricks.com/en/latest/messaging.html + +This is a Python3 modification of the original Pybricks MicroPython version: +https://github.com/pybricks/pybricks-micropython/tree/master/bricks/ev3dev diff --git a/examples/ev3/bluetooth_pc/pybricks/bluetooth.py b/examples/ev3/bluetooth_pc/pybricks/bluetooth.py new file mode 100644 index 0000000..f7904bd --- /dev/null +++ b/examples/ev3/bluetooth_pc/pybricks/bluetooth.py @@ -0,0 +1,145 @@ +# SPDX-License-Identifier: MIT +# Copyright (C) 2020 The Pybricks Authors + +""" +:class:`RFCOMMServer` can be used to communicate with other Bluetooth RFCOMM +devices that don't support the EV3 mailbox protocol. + +It is based on the standard library ``socketserver`` module and attempts to +remain a strict subset of that implementation when it comes to low-level +implementation details. +""" + +from bluetooth import BluetoothSocket, RFCOMM +from socketserver import ThreadingMixIn + +BDADDR_ANY = "" + + +def str2ba(string, ba): + """Convert string to Bluetooth address""" + for i, v in enumerate(string.split(':')): + ba.b[5-i] = int(v, 16) + + +def ba2str(ba): + """Convert Bluetooth address to string""" + string = [] + for b in ba.b: + string.append('{:02X}'.format(b)) + string.reverse() + return ':'.join(string).upper() + + +class RFCOMMServer: + """Object that simplifies setting up an RFCOMM socket server. + + This is based on the ``socketserver.SocketServer`` class in the Python + standard library. + """ + request_queue_size = 1 + + def __init__(self, server_address, RequestHandlerClass): + self.server_address = server_address + self.RequestHandlerClass = RequestHandlerClass + + self.socket = BluetoothSocket(RFCOMM) + + try: + self.socket.bind((server_address[0], server_address[1])) + # self.server_address = self.socket.getsockname() + self.socket.listen(self.request_queue_size) + except Exception: + self.server_close() + raise + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.server_close() + + def handle_request(self): + try: + request, addr_data = self.socket.accept() + except OSError: + return + + try: + self.process_request(request, addr_data) + except Exception: + request.close() + raise + + def process_request(self, request, client_address): + self.finish_request(request, client_address) + request.close() + + def finish_request(self, request, client_address): + self.RequestHandlerClass(request, client_address, self) + + def server_close(self): + self.socket.close() + + +class StreamRequestHandler: + """Class that handles incoming requests. + + This is based on ``socketserver.StreamRequestHandler`` from the Python + standard library. + """ + def __init__(self, request, client_address, server): + self.request = request + self.client_address = client_address + self.server = server + self.setup() + try: + self.handle() + finally: + self.finish() + + def setup(self): + self.wfile = self.request + self.rfile = self.request + + def handle(self): + pass + + def finish(self): + pass + + +class ThreadingRFCOMMServer(ThreadingMixIn, RFCOMMServer): + """Version of :class:`RFCOMMServer` that handles connections in a new + thread. + """ + pass + + +class RFCOMMClient: + def __init__(self, client_address, RequestHandlerClass): + self.client_address = client_address + self.RequestHandlerClass = RequestHandlerClass + self.socket = BluetoothSocket(RFCOMM) + + def handle_request(self): + self.socket.connect((self.client_address[0], self.client_address[1])) + try: + self.process_request(self.socket, self.client_address) + except Exception: + self.socket.close() + raise + + def process_request(self, request, client_address): + self.finish_request(request, client_address) + request.close() + + def finish_request(self, request, client_address): + self.RequestHandlerClass(request, client_address, self) + + def client_close(self): + self.socket.close() + + +class ThreadingRFCOMMClient(ThreadingMixIn, RFCOMMClient): + pass diff --git a/examples/ev3/bluetooth_pc/pybricks/messaging.py b/examples/ev3/bluetooth_pc/pybricks/messaging.py new file mode 100644 index 0000000..0595f81 --- /dev/null +++ b/examples/ev3/bluetooth_pc/pybricks/messaging.py @@ -0,0 +1,340 @@ +# SPDX-License-Identifier: MIT +# Copyright (C) 2020 The Pybricks Authors + +from _thread import allocate_lock +from errno import ECONNRESET +from struct import pack, unpack + +from .bluetooth import (BDADDR_ANY, ThreadingRFCOMMServer, + ThreadingRFCOMMClient, StreamRequestHandler) + + +def resolve(brick): + """Fake resolver to get address from Bluetooth name. + + To connect to an EV3 server, you must specify its full address. + """ + return brick + + +class Mailbox: + def __init__(self, name, connection, encode=None, decode=None): + """Object that represents a mailbox for sending an receiving messages + from other connected devices. + + Arguments: + name (str): + The name of this mailbox. + connection: + A connection object that implements the mailbox connection + interface. + encode: + A function that encodes an object into a bytes-like object. + decode: + A function that decodes an object from a bytes-like object. + """ + self.name = name + self._connection = connection + + if encode: + self.encode = encode + + if decode: + self.decode = decode + + def encode(self, value): + return value + + def decode(self, payload): + return payload + + def read(self): + """Reads the current value of the mailbox. + + Returns: + The decoded value or ``None`` if the mailbox has never received + a value. + """ + data = self._connection.read_from_mailbox(self.name) + if data is None: + return None + return self.decode(data) + + def send(self, value, destination=None): + """Sends a value to remote mailboxes with the same name as this + mailbox. + + Arguments: + value: The value to send. + destination: The name or address of a specific device or ``None`` + to broadcast to all connected devices. + """ + data = self.encode(value) + self._connection.send_to_mailbox(destination, self.name, data) + + def wait(self): + """Waits for the mailbox to receive a message.""" + self._connection.wait_for_mailbox_update(self.name) + + def wait_new(self): + """Waits for the mailbox to receive a message that is different from + the current contents of the mailbox. + + Returns: + The new value. (Same as return value of :meth:`read`.) + """ + old = self.read() + while True: + self.wait() + new = self.read() + if new != old: + return new + + +class LogicMailbox(Mailbox): + """:class:`Mailbox` that holds a logic or boolean value. + + This is compatible with the "logic" message blocks in the standard + EV3 firmware. + """ + + def encode(self, value): + return b'\x01' if value else b'\x00' + + def decode(self, payload): + return bool(payload[0]) + + +class NumericMailbox(Mailbox): + """:class:`Mailbox` that holds a numeric or floating point value. + + This is compatible with the "numeric" message blocks in the standard + EV3 firmware. + """ + + def encode(self, value): + return pack(' Bluetooth > Start Scan. +- Scroll down the list and choose your SPIKE hub. +- No need to pair or connect! Just write down the address you see. diff --git a/examples/ev3/bluetooth_read_spike/connection.py b/examples/ev3/bluetooth_read_spike/connection.py new file mode 100644 index 0000000..d30eb74 --- /dev/null +++ b/examples/ev3/bluetooth_read_spike/connection.py @@ -0,0 +1,80 @@ + +from uctypes import addressof, sizeof, struct +from usocket import socket, SOCK_STREAM + +from _thread import start_new_thread + +from pybricks.bluetooth import ( + str2ba, + sockaddr_rc, + AF_BLUETOOTH, + BTPROTO_RFCOMM +) +from pybricks.tools import wait, StopWatch + + +def get_bluetooth_rfcomm_socket(address, channel): + addr_data = bytearray(sizeof(sockaddr_rc)) + addr = struct(addressof(addr_data), sockaddr_rc) + addr.rc_family = AF_BLUETOOTH + str2ba(address, addr.rc_bdaddr) + addr.rc_channel = channel + + sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) + sock.connect(addr_data) + return sock + + +class SpikePrimeStreamReader(): + def __init__(self, address): + + try: + self.sock = get_bluetooth_rfcomm_socket(address, 1) + except OSError as e: + print("Turn on Bluetooth on the EV3 and on SPIKE.") + raise e + + self._values = None + + start_new_thread(self.reader, ()) + + watch = StopWatch() + while watch.time() < 2000: + if self.values() is not None: + return + wait(100) + raise IOError("No data received") + + def disconnect(self): + self.sock.close() + + def reader(self): + while True: + try: + raw = self.sock.recv(1024) + except OSError: + break + try: + data = eval(raw) + if data['m'] == 0: + self._values = data['p'] + except (SyntaxError, KeyError): + pass + + def values(self): + return self._values + + def device(self, port): + if 'A' <= port <= 'F': + return self.values()[ord(port)-ord('A')][1] + else: + raise ValueError + + def acceleration(self): + return self.values()[6] + + def gyro(self): + return self.values()[7] + + def orientation(self): + return self.values()[8] diff --git a/examples/ev3/bluetooth_read_spike/main.py b/examples/ev3/bluetooth_read_spike/main.py new file mode 100644 index 0000000..901f215 --- /dev/null +++ b/examples/ev3/bluetooth_read_spike/main.py @@ -0,0 +1,17 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.tools import wait + +from connection import SpikePrimeStreamReader + +# Beep! +ev3 = EV3Brick() +ev3.speaker.beep() + +# Create the connection. See README.md to find the address for your SPIKE hub. +spike = SpikePrimeStreamReader('F4:84:4C:AA:C8:A4') + +# Now you can simply read values! +for i in range(100): + print(spike.values()) + wait(100) diff --git a/examples/ev3/bluetooth_read_spike/rover.py b/examples/ev3/bluetooth_read_spike/rover.py new file mode 100644 index 0000000..f6f8dc2 --- /dev/null +++ b/examples/ev3/bluetooth_read_spike/rover.py @@ -0,0 +1,28 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.tools import wait +from pybricks.ev3devices import Motor +from pybricks.robotics import DriveBase +from pybricks.parameters import Port + +from connection import SpikePrimeStreamReader + +# Beep! +ev3 = EV3Brick() +ev3.speaker.beep() + +# Create the connection. See README.md to find the address for your SPIKE hub. +spike = SpikePrimeStreamReader('F4:84:4C:AA:C8:A4') + +# Initialize the motors and drive base +left_motor = Motor(Port.B) +right_motor = Motor(Port.C) +robot = DriveBase(left_motor, right_motor, wheel_diameter=55.5, axle_track=104) + +while True: + # Read the orientation + yaw, pitch, roll = spike.orientation() + + # Set speed and turn rate based on orientation + robot.drive(-pitch*6, roll*2) + wait(20) diff --git a/examples/ev3/bluetooth_server/.gitignore b/examples/ev3/bluetooth_server/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/bluetooth_server/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/bluetooth_server/.vscode/extensions.json b/examples/ev3/bluetooth_server/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/bluetooth_server/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/bluetooth_server/.vscode/launch.json b/examples/ev3/bluetooth_server/.vscode/launch.json new file mode 100644 index 0000000..167c178 --- /dev/null +++ b/examples/ev3/bluetooth_server/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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}/server.py" + } + ] +} diff --git a/examples/ev3/bluetooth_server/.vscode/settings.json b/examples/ev3/bluetooth_server/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/bluetooth_server/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/bluetooth_server/server.py b/examples/ev3/bluetooth_server/server.py new file mode 100644 index 0000000..9f325ee --- /dev/null +++ b/examples/ev3/bluetooth_server/server.py @@ -0,0 +1,23 @@ +#!/usr/bin/env pybricks-micropython + +# Before running this program, make sure the client and server EV3 bricks are +# paired using Bluetooth, but do NOT connect them. The program will take care +# of establishing the connection. + +# The server must be started before the client! + +from pybricks.messaging import BluetoothMailboxServer, TextMailbox + +server = BluetoothMailboxServer() +mbox = TextMailbox('greeting', server) + +# The server must be started before the client! +print('waiting for connection...') +server.wait_for_connection() +print('connected!') + +# In this program, the server waits for the client to send the first message +# and then sends a reply. +mbox.wait() +print(mbox.read()) +mbox.send('hello to you!') diff --git a/examples/ev3/buttons/.gitignore b/examples/ev3/buttons/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/buttons/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/buttons/.vscode/extensions.json b/examples/ev3/buttons/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/buttons/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/buttons/.vscode/launch.json b/examples/ev3/buttons/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/buttons/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/buttons/.vscode/settings.json b/examples/ev3/buttons/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/buttons/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/buttons/main.py b/examples/ev3/buttons/main.py new file mode 100644 index 0000000..5174985 --- /dev/null +++ b/examples/ev3/buttons/main.py @@ -0,0 +1,20 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.tools import wait +from pybricks.parameters import Button + +# Initialize the EV3 +ev3 = EV3Brick() + +# Wait until any of the buttons are pressed +while not any(ev3.buttons.pressed()): + wait(10) + +# Do something if the left button is pressed +if Button.LEFT in ev3.buttons.pressed(): + print("The left button is pressed.") + +# Wait until all buttons are released +while any(ev3.buttons.pressed()): + wait(10) diff --git a/examples/ev3/buttons_quickstart/.gitignore b/examples/ev3/buttons_quickstart/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/buttons_quickstart/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/buttons_quickstart/.vscode/extensions.json b/examples/ev3/buttons_quickstart/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/buttons_quickstart/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/buttons_quickstart/.vscode/launch.json b/examples/ev3/buttons_quickstart/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/buttons_quickstart/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/buttons_quickstart/.vscode/settings.json b/examples/ev3/buttons_quickstart/.vscode/settings.json new file mode 100644 index 0000000..466469b --- /dev/null +++ b/examples/ev3/buttons_quickstart/.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", + "python.linting.enabled": false, + "ev3devBrowser.download.exclude": "{**/.*,**/*.svg}" +} diff --git a/examples/ev3/buttons_quickstart/buttons.png b/examples/ev3/buttons_quickstart/buttons.png new file mode 100644 index 0000000..232026b Binary files /dev/null and b/examples/ev3/buttons_quickstart/buttons.png differ diff --git a/examples/ev3/buttons_quickstart/buttons.svg b/examples/ev3/buttons_quickstart/buttons.svg new file mode 100644 index 0000000..be1478d --- /dev/null +++ b/examples/ev3/buttons_quickstart/buttons.svg @@ -0,0 +1,101 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/examples/ev3/buttons_quickstart/main.py b/examples/ev3/buttons_quickstart/main.py new file mode 100644 index 0000000..23116fe --- /dev/null +++ b/examples/ev3/buttons_quickstart/main.py @@ -0,0 +1,27 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.parameters import Button + +from menu import wait_for_button + +# Initialize the EV3. +ev3 = EV3Brick() + +while True: + # Show the menu and wait for one button to be selected. + button = wait_for_button(ev3) + + # Now you can do something, based on which button was pressed. + + # In this demo, we just play a different sound for each button. + if button == Button.LEFT: + ev3.speaker.beep(200) + elif button == Button.RIGHT: + ev3.speaker.beep(400) + elif button == Button.UP: + ev3.speaker.beep(600) + elif button == Button.DOWN: + ev3.speaker.beep(800) + elif button == Button.CENTER: + ev3.speaker.beep(1000) diff --git a/examples/ev3/buttons_quickstart/menu.py b/examples/ev3/buttons_quickstart/menu.py new file mode 100644 index 0000000..e3789a3 --- /dev/null +++ b/examples/ev3/buttons_quickstart/menu.py @@ -0,0 +1,30 @@ +def wait_for_button(ev3): + """ + This function shows a picture of the buttons on the EV3 screen. + + Then it waits until you press a button. + + It returns which button was pressed. + """ + + # Show a picture of the buttons on the screen. + ev3.screen.load_image('buttons.png') + + # Tip: add text or icons to the image to help you + # remember what each button will do in your program. + + # Wait for a single button to be pressed and save the result. + pressed = [] + while len(pressed) != 1: + pressed = ev3.buttons.pressed() + button = pressed[0] + + # Print which button was pressed + ev3.screen.draw_text(2, 100, button) + + # Now wait for the button to be released. + while any(ev3.buttons.pressed()): + pass + + # Return which button was pressed. + return button diff --git a/examples/ev3/datalog/.gitignore b/examples/ev3/datalog/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/datalog/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/datalog/.vscode/extensions.json b/examples/ev3/datalog/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/datalog/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/datalog/.vscode/launch.json b/examples/ev3/datalog/.vscode/launch.json new file mode 100644 index 0000000..d933aeb --- /dev/null +++ b/examples/ev3/datalog/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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/examples/ev3/datalog/.vscode/settings.json b/examples/ev3/datalog/.vscode/settings.json new file mode 100644 index 0000000..b0968c1 --- /dev/null +++ b/examples/ev3/datalog/.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", + "python.linting.enabled": false, + "python.languageServer": "None" +} diff --git a/examples/ev3/datalog/main.py b/examples/ev3/datalog/main.py new file mode 100644 index 0000000..a35f9b3 --- /dev/null +++ b/examples/ev3/datalog/main.py @@ -0,0 +1,34 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.ev3devices import Motor +from pybricks.parameters import Port +from pybricks.tools import DataLog, StopWatch, wait + +# Create a data log file in the project folder on the EV3 Brick. +# * By default, the file name contains the current date and time, for example: +# log_2020_02_13_10_07_44_431260.csv +# * You can optionally specify the titles of your data columns. For example, +# if you want to record the motor angles at a given time, you could do: +data = DataLog('time', 'angle') + +# Initialize a motor and make it move +wheel = Motor(Port.B) +wheel.run(500) + +# Start a stopwatch to measure elapsed time +watch = StopWatch() + +# Log the time and the motor angle 10 times +for i in range(10): + # Read angle and time + angle = wheel.angle() + time = watch.time() + + # Each time you use the log() method, a new line with data is added to + # the file. You can add as many values as you like. + # In this example, we save the current time and motor angle: + data.log(time, angle) + + # Wait some time so the motor can move a bit + wait(100) + +# You can now upload your file to your computer diff --git a/examples/ev3/datalog_extra/.gitignore b/examples/ev3/datalog_extra/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/datalog_extra/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/datalog_extra/.vscode/extensions.json b/examples/ev3/datalog_extra/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/datalog_extra/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/datalog_extra/.vscode/launch.json b/examples/ev3/datalog_extra/.vscode/launch.json new file mode 100644 index 0000000..d933aeb --- /dev/null +++ b/examples/ev3/datalog_extra/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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/examples/ev3/datalog_extra/.vscode/settings.json b/examples/ev3/datalog_extra/.vscode/settings.json new file mode 100644 index 0000000..b0968c1 --- /dev/null +++ b/examples/ev3/datalog_extra/.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", + "python.linting.enabled": false, + "python.languageServer": "None" +} diff --git a/examples/ev3/datalog_extra/main.py b/examples/ev3/datalog_extra/main.py new file mode 100644 index 0000000..b2b15e0 --- /dev/null +++ b/examples/ev3/datalog_extra/main.py @@ -0,0 +1,15 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.parameters import Color +from pybricks.tools import DataLog + +# Create a data log file called my_file.txt +data = DataLog('time', 'angle', name='my_file', timestamp=False, extension='txt') + +# The log method uses the print() method to add a line of text. +# So, you can do much more than saving numbers. For example: +data.log('Temperature', 25) +data.log('Sunday', 'Monday', 'Tuesday') +data.log({'Kiwi': Color.GREEN}, {'Banana': Color.YELLOW}) + +# You can upload the file to your computer, but you can also print the data: +print(data) diff --git a/examples/ev3/ev3devsensor/.gitignore b/examples/ev3/ev3devsensor/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/ev3devsensor/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/ev3devsensor/.vscode/extensions.json b/examples/ev3/ev3devsensor/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/ev3devsensor/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/ev3devsensor/.vscode/launch.json b/examples/ev3/ev3devsensor/.vscode/launch.json new file mode 100644 index 0000000..7dc1149 --- /dev/null +++ b/examples/ev3/ev3devsensor/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // 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": "Main Example", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/main.py" + }, + { + "name": "Class Example", + "type": "ev3devBrowser", + "request": "launch", + "program": "/home/robot/${workspaceRootFolderName}/class_example.py" + } + ] +} diff --git a/examples/ev3/ev3devsensor/.vscode/settings.json b/examples/ev3/ev3devsensor/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/ev3devsensor/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/ev3devsensor/class_example.py b/examples/ev3/ev3devsensor/class_example.py new file mode 100644 index 0000000..95dfe40 --- /dev/null +++ b/examples/ev3/ev3devsensor/class_example.py @@ -0,0 +1,46 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.parameters import Port +from pybricks.iodevices import Ev3devSensor + + +class MySensor(Ev3devSensor): + """Example of extending the Ev3devSensor class.""" + + def __init__(self, port): + """Initialize the sensor.""" + + # Initialize the parent class. + super().__init__(port) + + # Get the sysfs path. + self.path = '/sys/class/lego-sensor/sensor' + str(self.sensor_index) + + def get_modes(self): + """Get a list of mode strings so we don't have to look them up.""" + + # The path of the modes file. + modes_path = self.path + '/modes' + + # Open the modes file. + with open(modes_path, 'r') as m: + + # Read the contents. + contents = m.read() + + # Strip the newline symbol, and split at every space symbol. + return contents.strip().split(' ') + + +# Initialize the sensor +sensor = MySensor(Port.S3) + +# Show where this sensor can be found +print(sensor.path) + +# Print the available modes +modes = sensor.get_modes() +print(modes) + +# Read mode 0 of this sensor +val = sensor.read(modes[0]) +print(val) diff --git a/examples/ev3/ev3devsensor/main.py b/examples/ev3/ev3devsensor/main.py new file mode 100644 index 0000000..58a6d7c --- /dev/null +++ b/examples/ev3/ev3devsensor/main.py @@ -0,0 +1,19 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.parameters import Port +from pybricks.tools import wait +from pybricks.iodevices import Ev3devSensor + +# Initialize an Ev3devSensor. +# In this example we use the +# LEGO MINDSTORMS EV3 Color Sensor. +sensor = Ev3devSensor(Port.S3) + +while True: + # Read the raw RGB values + r, g, b = sensor.read('RGB-RAW') + + # Print results + print('R: {0}\t G: {1}\t B: {2}'.format(r, g, b)) + + # Wait + wait(200) diff --git a/examples/ev3/getting_started/.gitignore b/examples/ev3/getting_started/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/getting_started/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/getting_started/.vscode/extensions.json b/examples/ev3/getting_started/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/getting_started/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/getting_started/.vscode/launch.json b/examples/ev3/getting_started/.vscode/launch.json new file mode 100644 index 0000000..d933aeb --- /dev/null +++ b/examples/ev3/getting_started/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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/examples/ev3/getting_started/.vscode/settings.json b/examples/ev3/getting_started/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/getting_started/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/getting_started/main.py b/examples/ev3/getting_started/main.py new file mode 100644 index 0000000..05e48c3 --- /dev/null +++ b/examples/ev3/getting_started/main.py @@ -0,0 +1,23 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.ev3devices import Motor +from pybricks.parameters import Port + +# Create your objects here + +# Initialize the EV3 Brick. +ev3 = EV3Brick() + +# Initialize a motor at port B. +test_motor = Motor(Port.B) + +# Write your program here + +# Play a sound. +ev3.speaker.beep() + +# Run the motor up to 500 degrees per second. To a target angle of 90 degrees. +test_motor.run_target(500, 90) + +# Play another beep sound. +ev3.speaker.beep(frequency=1000, duration=500) diff --git a/examples/ev3/i2c_basics/.gitignore b/examples/ev3/i2c_basics/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/i2c_basics/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/i2c_basics/.vscode/extensions.json b/examples/ev3/i2c_basics/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/i2c_basics/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/i2c_basics/.vscode/launch.json b/examples/ev3/i2c_basics/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/i2c_basics/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/i2c_basics/.vscode/settings.json b/examples/ev3/i2c_basics/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/i2c_basics/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/i2c_basics/main.py b/examples/ev3/i2c_basics/main.py new file mode 100644 index 0000000..37d412f --- /dev/null +++ b/examples/ev3/i2c_basics/main.py @@ -0,0 +1,23 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.iodevices import I2CDevice +from pybricks.parameters import Port + +# Initialize the EV3 +ev3 = EV3Brick() + +# Initialize I2C Sensor +device = I2CDevice(Port.S2, 0xD2 >> 1) + +# Read one byte from the device. +# For this device, we can read the Who Am I +# register (0x0F) for the expected value: 211. +if 211 not in device.read(0x0F): + raise OSError("Device is not attached") + +# To write data, create a bytes object of one +# or more bytes. For example: +# data = bytes((1, 2, 3)) + +# Write one byte (value 0x08) to register 0x22 +device.write(0x22, bytes((0x08,))) diff --git a/examples/ev3/i2c_extra/.gitignore b/examples/ev3/i2c_extra/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/i2c_extra/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/i2c_extra/.vscode/extensions.json b/examples/ev3/i2c_extra/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/i2c_extra/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/i2c_extra/.vscode/launch.json b/examples/ev3/i2c_extra/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/i2c_extra/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/i2c_extra/.vscode/settings.json b/examples/ev3/i2c_extra/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/i2c_extra/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/i2c_extra/main.py b/examples/ev3/i2c_extra/main.py new file mode 100644 index 0000000..807ea2f --- /dev/null +++ b/examples/ev3/i2c_extra/main.py @@ -0,0 +1,35 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.iodevices import I2CDevice +from pybricks.parameters import Port + +# Initialize the EV3 +ev3 = EV3Brick() + +# Initialize I2C Sensor +device = I2CDevice(Port.S2, 0xD2 >> 1) + +# Recommended for reading +result, = device.read(reg=0x0F, length=1) + +# Read 1 byte from no particular register: +device.read(reg=None, length=1) + +# Read 0 bytes from no particular register: +device.read(reg=None, length=0) + +# I2C write operations consist of a register byte followed +# by a series of data bytes. Depending on your device, you +# can choose to skip the register or data as follows: + +# Recommended for writing: +device.write(reg=0x22, data=b'\x08') + +# Write 1 byte to no particular register: +device.write(reg=None, data=b'\x08') + +# Write 0 bytes to a particular register: +device.write(reg=0x08, data=None) + +# Write 0 bytes to no particular register: +device.write(reg=None, data=None) diff --git a/examples/ev3/light_color/.gitignore b/examples/ev3/light_color/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/light_color/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/light_color/.vscode/extensions.json b/examples/ev3/light_color/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/light_color/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/light_color/.vscode/launch.json b/examples/ev3/light_color/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/light_color/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/light_color/.vscode/settings.json b/examples/ev3/light_color/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/light_color/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/light_color/main.py b/examples/ev3/light_color/main.py new file mode 100644 index 0000000..69f3351 --- /dev/null +++ b/examples/ev3/light_color/main.py @@ -0,0 +1,17 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.tools import wait +from pybricks.parameters import Color + +# Initialize the EV3 +ev3 = EV3Brick() + +# Turn on a red light +ev3.light.on(Color.RED) + +# Wait +wait(1000) + +# Turn the light off +ev3.light.off() diff --git a/examples/ev3/ps4/.gitignore b/examples/ev3/ps4/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/ps4/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/ps4/.vscode/extensions.json b/examples/ev3/ps4/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/ps4/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/ps4/.vscode/launch.json b/examples/ev3/ps4/.vscode/launch.json new file mode 100644 index 0000000..d933aeb --- /dev/null +++ b/examples/ev3/ps4/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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/examples/ev3/ps4/.vscode/settings.json b/examples/ev3/ps4/.vscode/settings.json new file mode 100644 index 0000000..b0968c1 --- /dev/null +++ b/examples/ev3/ps4/.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", + "python.linting.enabled": false, + "python.languageServer": "None" +} diff --git a/examples/ev3/ps4/main.py b/examples/ev3/ps4/main.py new file mode 100644 index 0000000..fd82bda --- /dev/null +++ b/examples/ev3/ps4/main.py @@ -0,0 +1,145 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.ev3devices import Motor +from pybricks.parameters import Port + +import struct + +# This program uses the two PS4 sticks to control two EV3 Large Servo Motors +# using tank like controls. For a full map of all PS4 buttons, trackpad, and +# motion checkout: https://github.com/codeadamca/python-connect-ps4 + +# Initialize EV3 motors +left_motor = Motor(Port.B) +right_motor = Motor(Port.C) +left_speed = 0 +right_speed = 0 + +# Locate the event file you want to react to, on my setup the PS4 controller +# button events are located in /dev/input/event4 +infile_path = "/dev/input/event4" +in_file = open(infile_path, "rb") + +# Define the format the event data will be read. +# https://docs.python.org/3/library/struct.html#format-characters +FORMAT = 'llHHi' +EVENT_SIZE = struct.calcsize(FORMAT) +event = in_file.read(EVENT_SIZE) + + +# A helper function for converting stick values (0 to 255) to more usable +# numbers (-100 to 100) +def scale(val, src, dst): + + result = (float(val - src[0]) / (src[1] - src[0])) + result = result * (dst[1] - dst[0]) + dst[0] + return result + +# Create a loop to react to events +# This loop reacte to all main PS4 button and stick events. I have left out +# buttons like share and options, but can easily be added in by referring +# to the table at: https://github.com/codeadamca/python-connect-ps4 + + +while event: + + # Place event data into variables + (tv_sec, tv_usec, ev_type, code, value) = struct.unpack(FORMAT, event) + + # If a button was pressed or released + if ev_type == 1: + + # React to the X button + if code == 304 and value == 0: + print("The X button was released") + elif code == 304 and value == 1: + print("The X button was pressed") + + # React to the Circle button + elif code == 305 and value == 0: + print("The Circle button was released") + elif code == 305 and value == 1: + print("The Circle button was pressed") + + # React to the Triangle button + elif code == 307 and value == 0: + print("The Triangle button was released") + elif code == 307 and value == 1: + print("The Triangle button was pressed") + + # React to the Square button + elif code == 308 and value == 0: + print("The Square button was released") + elif code == 308 and value == 1: + print("The Square button was pressed") + + # React to the L1 button + elif code == 310 and value == 0: + print("The L1 button was released") + elif code == 310 and value == 1: + print("The L1 button was pressed") + + # React to the R1 button + elif code == 311 and value == 0: + print("The R1 button was released") + elif code == 311 and value == 1: + print("The R1 button was pressed") + + # React to the L2 button + elif code == 312 and value == 0: + print("The L2 button was released") + elif code == 312 and value == 1: + print("The L2 button was pressed") + + # React to the R2 button + elif code == 313 and value == 0: + print("The R2 button was released") + elif code == 313 and value == 1: + print("The R2 button was pressed") + + elif ev_type == 3: + + # The sticks often trigger non-stop events, comment this out if you are + # not using the sticks as part of your project, or it becomes hard to + # read other data + + # React to the left stick vertical + if code == 1: + print("The left stick vertical is at ", value) + left_speed = scale(value, (0, 255), (100, -100)) + + # React to the left stick horizontal + elif code == 0: + print("The left stick horizontal is at ", value) + + # React to the right stick vertical + elif code == 4: + print("The right stick vertical is at ", value) + right_speed = scale(value, (0, 255), (100, -100)) + + # React to the right stick horizontal + elif code == 3: + print("The right stick horizontal is at ", value) + + # React to the Directional pad + if code == 16 and value == -1: + print("The horizontal directional pad is left") + elif code == 16 and value == 1: + print("The horizontal directional pad is right") + elif code == 16 and value == 0: + print("The horizontal directional pad is released") + + elif code == 17 and value == -1: + print("The vertical directional pad is up") + elif code == 17 and value == 1: + print("The horizontal directional pad is down") + elif code == 17 and value == 0: + print("The horizontal directional pad is released") + + # Set motor speed + left_motor.dc(left_speed) + right_motor.dc(right_speed) + + # Read the next event + event = in_file.read(EVENT_SIZE) + +in_file.close() diff --git a/examples/ev3/rcx_touch/.gitignore b/examples/ev3/rcx_touch/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/rcx_touch/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/rcx_touch/.vscode/extensions.json b/examples/ev3/rcx_touch/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/rcx_touch/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/rcx_touch/.vscode/launch.json b/examples/ev3/rcx_touch/.vscode/launch.json new file mode 100644 index 0000000..d933aeb --- /dev/null +++ b/examples/ev3/rcx_touch/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // 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/examples/ev3/rcx_touch/.vscode/settings.json b/examples/ev3/rcx_touch/.vscode/settings.json new file mode 100644 index 0000000..b0968c1 --- /dev/null +++ b/examples/ev3/rcx_touch/.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", + "python.linting.enabled": false, + "python.languageServer": "None" +} diff --git a/examples/ev3/rcx_touch/main.py b/examples/ev3/rcx_touch/main.py new file mode 100644 index 0000000..d2c512f --- /dev/null +++ b/examples/ev3/rcx_touch/main.py @@ -0,0 +1,21 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.iodevices import AnalogSensor +from pybricks.parameters import Port, Color +from pybricks.tools import wait + + +class RCXTouchSensor(AnalogSensor): + def pressed(self): + return self.resistance() < 50*1000 + + +ev3 = EV3Brick() +btn = RCXTouchSensor(Port.S1) + +while True: + if btn.pressed(): + ev3.light.on(Color.ORANGE) + else: + ev3.light.off() + wait(10) diff --git a/examples/ev3/screen_draw/.gitignore b/examples/ev3/screen_draw/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/screen_draw/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/screen_draw/.vscode/extensions.json b/examples/ev3/screen_draw/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/screen_draw/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/screen_draw/.vscode/launch.json b/examples/ev3/screen_draw/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/screen_draw/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/screen_draw/.vscode/settings.json b/examples/ev3/screen_draw/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/screen_draw/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/screen_draw/main.py b/examples/ev3/screen_draw/main.py new file mode 100644 index 0000000..ab98c0a --- /dev/null +++ b/examples/ev3/screen_draw/main.py @@ -0,0 +1,32 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.tools import wait + + +# Initialize the EV3 +ev3 = EV3Brick() + + +# Draw a rectangle +ev3.screen.draw_box(10, 10, 40, 40) + +# Draw a solid rectangle +ev3.screen.draw_box(20, 20, 30, 30, fill=True) + +# Draw a rectangle with rounded corners +ev3.screen.draw_box(50, 10, 80, 40, 5) + +# Draw a circle +ev3.screen.draw_circle(25, 75, 20) + +# Draw a triangle using lines +x1, y1 = 65, 55 +x2, y2 = 50, 95 +x3, y3 = 80, 95 +ev3.screen.draw_line(x1, y1, x2, y2) +ev3.screen.draw_line(x2, y2, x3, y3) +ev3.screen.draw_line(x3, y3, x1, y1) + +# Wait some time to look at the shapes +wait(5000) diff --git a/examples/ev3/screen_extra/.gitignore b/examples/ev3/screen_extra/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/screen_extra/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/screen_extra/.vscode/extensions.json b/examples/ev3/screen_extra/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/screen_extra/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/screen_extra/.vscode/launch.json b/examples/ev3/screen_extra/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/screen_extra/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/screen_extra/.vscode/settings.json b/examples/ev3/screen_extra/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/screen_extra/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/screen_extra/background.png b/examples/ev3/screen_extra/background.png new file mode 100644 index 0000000..aae8020 Binary files /dev/null and b/examples/ev3/screen_extra/background.png differ diff --git a/examples/ev3/screen_extra/main.py b/examples/ev3/screen_extra/main.py new file mode 100644 index 0000000..b8e6462 --- /dev/null +++ b/examples/ev3/screen_extra/main.py @@ -0,0 +1,104 @@ +#!/usr/bin/env pybricks-micropython + +import math + +from pybricks.hubs import EV3Brick +from pybricks.parameters import Color +from pybricks.tools import wait +from pybricks.media.ev3dev import Font, Image + + +# Initialize the EV3 +ev3 = EV3Brick() + + +# SPLIT SCREEN ################################################################ + +# Make a sub-image for the left half of the screen +left = Image(ev3.screen, sub=True, x1=0, y1=0, + x2=ev3.screen.width // 2 - 1, y2=ev3.screen.height - 1) + +# Make a sub-image for the right half of the screen +right = Image(ev3.screen, sub=True, x1=ev3.screen.width // 2, y1=0, + x2=ev3.screen.width - 1, y2=ev3.screen.height - 1) + +# Use a monospaced font so that text is vertically aligned when we print +right.set_font(Font(size=8, monospace=True)) + + +# Graphing y = sin(x) +def f(x): + return math.sin(x) + + +for t in range(200): + # Graph on left side + + # Scale t to x-axis and compute y values + x0 = (t - 1) * 2 * math.pi / left.width + y0 = f(x0) + x1 = t * 2 * math.pi / left.width + y1 = f(x1) + + # Scale y values to screen coordinates + sy0 = (-y0 + 1) * left.height / 2 + sy1 = (-y1 + 1) * left.height / 2 + + # Shift the current graph to the left one pixel + left.draw_image(-1, 0, left) + # Fill the last column with white to erase the previous plot point + left.draw_line(left.width - 1, 0, left.width - 1, left.height - 1, 1, Color.WHITE) + # Draw the new value of the graph in the last column + left.draw_line(left.width - 2, int(sy0), left.width - 1, int(sy1), 3) + + # Print every 10th value on right side + if t % 10 == 0: + right.print('{:10.2f}{:10.2f}'.format(x1, y1)) + + wait(100) + + +# SPRITE ANIMATION ############################################################ + +# Copy of screen for double-buffering +buf = Image(ev3.screen) + +# Load images from file +bg = Image('background.png') +sprite = Image('sprite.png') + +# Number of cells in each sprite animation +NUM_CELLS = 8 + +# Each cell in the sprite is 75 x 100 pixels +CELL_WIDTH, CELL_HEIGHT = 75, 100 + +# Get sub-images for each individual cell +# This is more efficient that loading individual images +walk_right = [Image(sprite, sub=True, x1=x * CELL_WIDTH, y1=0, + x2=(x + 1) * CELL_WIDTH - 1, y2=CELL_HEIGHT - 1) + for x in range(NUM_CELLS)] +walk_left = [Image(sprite, sub=True, x1=x * CELL_WIDTH, y1=CELL_HEIGHT, + x2=(x + 1) * CELL_WIDTH - 1, y2=2 * CELL_HEIGHT - 1) + for x in range(NUM_CELLS)] + + +# Walk from left to right +for x in range(-100, 200, 2): + # Start with the background image + buf.draw_image(0, 0, bg) + # Draw the current sprite - purple is treated as transparent + buf.draw_image(x, 5, walk_right[x // 5 % NUM_CELLS], Color.PURPLE) + # Copy the double-buffer to the screen + ev3.screen.draw_image(0, 0, buf) + # 20 frames per second + wait(50) + +# Walk from right to left +for x in range(200, -100, -2): + buf.draw_image(0, 0, bg) + buf.draw_image(x, 5, walk_left[x // 5 % NUM_CELLS], Color.PURPLE) + ev3.screen.draw_image(0, 0, buf) + wait(50) + +wait(1000) diff --git a/examples/ev3/screen_extra/sprite.png b/examples/ev3/screen_extra/sprite.png new file mode 100644 index 0000000..33057ed Binary files /dev/null and b/examples/ev3/screen_extra/sprite.png differ diff --git a/examples/ev3/screen_image/.gitignore b/examples/ev3/screen_image/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/screen_image/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/screen_image/.vscode/extensions.json b/examples/ev3/screen_image/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/screen_image/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/screen_image/.vscode/launch.json b/examples/ev3/screen_image/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/screen_image/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/screen_image/.vscode/settings.json b/examples/ev3/screen_image/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/screen_image/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/screen_image/main.py b/examples/ev3/screen_image/main.py new file mode 100644 index 0000000..2d6870c --- /dev/null +++ b/examples/ev3/screen_image/main.py @@ -0,0 +1,20 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.tools import wait +from pybricks.media.ev3dev import Image, ImageFile + +# It takes some time to load images from the SD card, so it is best to load +# them once at the beginning of a program like this: +ev3_img = Image(ImageFile.EV3_ICON) + + +# Initialize the EV3 +ev3 = EV3Brick() + + +# Show an image +ev3.screen.load_image(ev3_img) + +# Wait some time to look at the image +wait(5000) diff --git a/examples/ev3/screen_print/.gitignore b/examples/ev3/screen_print/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/screen_print/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/screen_print/.vscode/extensions.json b/examples/ev3/screen_print/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/screen_print/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/screen_print/.vscode/launch.json b/examples/ev3/screen_print/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/screen_print/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/screen_print/.vscode/settings.json b/examples/ev3/screen_print/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/screen_print/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/screen_print/main.py b/examples/ev3/screen_print/main.py new file mode 100644 index 0000000..1e12bdd --- /dev/null +++ b/examples/ev3/screen_print/main.py @@ -0,0 +1,34 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.tools import wait +from pybricks.media.ev3dev import Font + +# It takes some time for fonts to load from file, so it is best to only +# load them once at the beginning of the program like this: +tiny_font = Font(size=6) +big_font = Font(size=24, bold=True) +chinese_font = Font(size=24, lang='zh-cn') + + +# Initialize the EV3 +ev3 = EV3Brick() + + +# Say hello +ev3.screen.print('Hello!') + +# Say tiny hello +ev3.screen.set_font(tiny_font) +ev3.screen.print('hello') + +# Say big hello +ev3.screen.set_font(big_font) +ev3.screen.print('HELLO') + +# Say Chinese hello +ev3.screen.set_font(chinese_font) +ev3.screen.print('你好') + +# Wait some time to look at the screen +wait(5000) diff --git a/examples/ev3/speaker_basics/.gitignore b/examples/ev3/speaker_basics/.gitignore new file mode 100644 index 0000000..00f2d38 --- /dev/null +++ b/examples/ev3/speaker_basics/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +.venv/ diff --git a/examples/ev3/speaker_basics/.vscode/extensions.json b/examples/ev3/speaker_basics/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/speaker_basics/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/speaker_basics/.vscode/launch.json b/examples/ev3/speaker_basics/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/speaker_basics/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/speaker_basics/.vscode/settings.json b/examples/ev3/speaker_basics/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/speaker_basics/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/speaker_basics/main.py b/examples/ev3/speaker_basics/main.py new file mode 100644 index 0000000..bc7a3b5 --- /dev/null +++ b/examples/ev3/speaker_basics/main.py @@ -0,0 +1,55 @@ +#!/usr/bin/env pybricks-micropython + +from pybricks.hubs import EV3Brick +from pybricks.tools import wait +from pybricks.media.ev3dev import SoundFile + + +# Initialize the EV3 +ev3 = EV3Brick() + + +# BEEP ######################################################################## + +# Simple beep +ev3.speaker.beep() + +wait(1000) + +# Interesting beeps +for f in range(100, 500, 100): + ev3.speaker.beep(f) + +wait(1000) + + +# PLAY NOTES ################################################################## + +# Twinkle, Twinkle Little Star +A = ['C4/4', 'C4/4', 'G4/4', 'G4/4', 'A4/4', 'A4/4', 'G4/2', + 'F4/4', 'F4/4', 'E4/4', 'E4/4', 'D4/4', 'D4/4', 'C4/2'] +B = ['G4/4', 'G4/4', 'F4/4', 'F4/4', 'E4/4', 'E4/4', 'D4/2'] * 2 +TWINKLE = A + B + A + +ev3.speaker.play_notes(TWINKLE) + +wait(1000) + + +# PLAY FILE ################################################################### + +ev3.speaker.play_file(SoundFile.HELLO) + +wait(1000) + + +# TEXT TO SPEECH ############################################################## + +# Say something in English +ev3.speaker.say('I am am E V 3. Pleased to meet you.') + +# Say something in Danish + female +ev3.speaker.set_speech_options(voice='da+f5') +ev3.speaker.say('Leg godt!') + +wait(1000) diff --git a/examples/ev3/uart_basics/.gitignore b/examples/ev3/uart_basics/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/uart_basics/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/uart_basics/.vscode/extensions.json b/examples/ev3/uart_basics/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/uart_basics/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/uart_basics/.vscode/launch.json b/examples/ev3/uart_basics/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/uart_basics/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/uart_basics/.vscode/settings.json b/examples/ev3/uart_basics/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/uart_basics/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/uart_basics/main.py b/examples/ev3/uart_basics/main.py new file mode 100644 index 0000000..b7fedf9 --- /dev/null +++ b/examples/ev3/uart_basics/main.py @@ -0,0 +1,25 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.hubs import EV3Brick +from pybricks.iodevices import UARTDevice +from pybricks.parameters import Port +from pybricks.media.ev3dev import SoundFile + +# Initialize the EV3 +ev3 = EV3Brick() + +# Initialize sensor port 2 as a uart device +ser = UARTDevice(Port.S2, baudrate=115200) + +# Write some data +ser.write(b'\r\nHello, world!\r\n') + +# Play a sound while we wait for some data +for i in range(3): + ev3.speaker.play_file(SoundFile.HELLO) + ev3.speaker.play_file(SoundFile.GOOD) + ev3.speaker.play_file(SoundFile.MORNING) + print("Bytes waiting to be read:", ser.waiting()) + +# Read all data received while the sound was playing +data = ser.read_all() +print(data) diff --git a/examples/ev3/vernier_surface_temperature/.gitignore b/examples/ev3/vernier_surface_temperature/.gitignore new file mode 100644 index 0000000..9b5f630 --- /dev/null +++ b/examples/ev3/vernier_surface_temperature/.gitignore @@ -0,0 +1,3 @@ +__pycache__/ +*.pyc +venv/ diff --git a/examples/ev3/vernier_surface_temperature/.vscode/extensions.json b/examples/ev3/vernier_surface_temperature/.vscode/extensions.json new file mode 100644 index 0000000..f8f1a44 --- /dev/null +++ b/examples/ev3/vernier_surface_temperature/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + // 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" + ] +} \ No newline at end of file diff --git a/examples/ev3/vernier_surface_temperature/.vscode/launch.json b/examples/ev3/vernier_surface_temperature/.vscode/launch.json new file mode 100644 index 0000000..af12883 --- /dev/null +++ b/examples/ev3/vernier_surface_temperature/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + // 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" + } + ] +} diff --git a/examples/ev3/vernier_surface_temperature/.vscode/settings.json b/examples/ev3/vernier_surface_temperature/.vscode/settings.json new file mode 100644 index 0000000..37c9a5d --- /dev/null +++ b/examples/ev3/vernier_surface_temperature/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false +} diff --git a/examples/ev3/vernier_surface_temperature/main.py b/examples/ev3/vernier_surface_temperature/main.py new file mode 100644 index 0000000..4045ff5 --- /dev/null +++ b/examples/ev3/vernier_surface_temperature/main.py @@ -0,0 +1,32 @@ +#!/usr/bin/env pybricks-micropython +from pybricks.parameters import Port +from pybricks.nxtdevices import VernierAdapter + +from math import log + + +# Conversion formula for Surface Temperature Sensor +def convert_raw_to_temperature(voltage): + + # Convert the raw voltage to the NTC resistance + # according to the Vernier Adapter EV3 block. + counts = voltage/5000*4096 + ntc = 15000*(counts)/(4130-counts) + + # Handle log(0) safely: make sure that ntc value is positive. + if ntc <= 0: + ntc = 1 + + # Apply Steinhart-Hart equation as given in the sensor documentation. + K0 = 1.02119e-3 + K1 = 2.22468e-4 + K2 = 1.33342e-7 + return 1/(K0 + K1*log(ntc) + K2*log(ntc)**3) + + +# Initialize the adapter on port 1 +thermometer = VernierAdapter(Port.S1, convert_raw_to_temperature) + +# Get the measured value and print it +temp = thermometer.value() +print(temp) diff --git a/examples/pup/hub_cityhub/light_animate.py b/examples/pup/hub_cityhub/light_animate.py new file mode 100644 index 0000000..db71543 --- /dev/null +++ b/examples/pup/hub_cityhub/light_animate.py @@ -0,0 +1,23 @@ +from pybricks.hubs import CityHub +from pybricks.parameters import Color +from pybricks.tools import wait +from math import sin, pi + +# Initialize the hub. +hub = CityHub() + +# Make an animation with multiple colors. +hub.light.animate([Color.RED, Color.GREEN, None], interval=500) + +wait(10000) + +# Make the color RED grow faint and bright using a sine pattern. +hub.light.animate( + [Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40) + +wait(10000) + +# Cycle through a rainbow of colors. +hub.light.animate([Color(h=i*8) for i in range(45)], interval=40) + +wait(10000) diff --git a/examples/pup/hub_cityhub/light_blink.py b/examples/pup/hub_cityhub/light_blink.py new file mode 100644 index 0000000..e245665 --- /dev/null +++ b/examples/pup/hub_cityhub/light_blink.py @@ -0,0 +1,16 @@ +from pybricks.hubs import CityHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub +hub = CityHub() + +# Keep blinking red on and off. +hub.light.blink(Color.RED, [500, 500]) + +wait(10000) + +# Keep blinking green slowly and then quickly. +hub.light.blink(Color.GREEN, [500, 500, 50, 900]) + +wait(10000) diff --git a/examples/pup/hub_cityhub/light_hsv.py b/examples/pup/hub_cityhub/light_hsv.py new file mode 100644 index 0000000..38d43ed --- /dev/null +++ b/examples/pup/hub_cityhub/light_hsv.py @@ -0,0 +1,21 @@ +from pybricks.hubs import CityHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = CityHub() + +# Show the color at 30% brightness. +hub.light.on(Color.RED * 0.3) + +wait(2000) + +# Use your own custom color. +hub.light.on(Color(h=30, s=100, v=50)) + +wait(2000) + +# Go through all the colors. +for hue in range(360): + hub.light.on(Color(hue)) + wait(10) diff --git a/examples/pup/hub_cityhub/light_off.py b/examples/pup/hub_cityhub/light_off.py new file mode 100644 index 0000000..2ca8f20 --- /dev/null +++ b/examples/pup/hub_cityhub/light_off.py @@ -0,0 +1,15 @@ +from pybricks.hubs import CityHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = CityHub() + +# Turn the light on and off 5 times. +for i in range(5): + + hub.light.on(Color.RED) + wait(1000) + + hub.light.off() + wait(500) diff --git a/examples/pup/hub_inventorhub/light_animate.py b/examples/pup/hub_inventorhub/light_animate.py new file mode 100644 index 0000000..e8d7da9 --- /dev/null +++ b/examples/pup/hub_inventorhub/light_animate.py @@ -0,0 +1,23 @@ +from pybricks.hubs import InventorHub +from pybricks.parameters import Color +from pybricks.tools import wait +from math import sin, pi + +# Initialize the hub. +hub = InventorHub() + +# Make an animation with multiple colors. +hub.light.animate([Color.RED, Color.GREEN, None], interval=500) + +wait(10000) + +# Make the color RED grow faint and bright using a sine pattern. +hub.light.animate( + [Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40) + +wait(10000) + +# Cycle through a rainbow of colors. +hub.light.animate([Color(h=i*8) for i in range(45)], interval=40) + +wait(10000) diff --git a/examples/pup/hub_inventorhub/light_blink.py b/examples/pup/hub_inventorhub/light_blink.py new file mode 100644 index 0000000..d94c94b --- /dev/null +++ b/examples/pup/hub_inventorhub/light_blink.py @@ -0,0 +1,16 @@ +from pybricks.hubs import InventorHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub +hub = InventorHub() + +# Keep blinking red on and off. +hub.light.blink(Color.RED, [500, 500]) + +wait(10000) + +# Keep blinking green slowly and then quickly. +hub.light.blink(Color.GREEN, [500, 500, 50, 900]) + +wait(10000) diff --git a/examples/pup/hub_inventorhub/light_hsv.py b/examples/pup/hub_inventorhub/light_hsv.py new file mode 100644 index 0000000..4420239 --- /dev/null +++ b/examples/pup/hub_inventorhub/light_hsv.py @@ -0,0 +1,21 @@ +from pybricks.hubs import InventorHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = InventorHub() + +# Show the color at 30% brightness. +hub.light.on(Color.RED * 0.3) + +wait(2000) + +# Use your own custom color. +hub.light.on(Color(h=30, s=100, v=50)) + +wait(2000) + +# Go through all the colors. +for hue in range(360): + hub.light.on(Color(hue)) + wait(10) diff --git a/examples/pup/hub_inventorhub/light_off.py b/examples/pup/hub_inventorhub/light_off.py new file mode 100644 index 0000000..1a23440 --- /dev/null +++ b/examples/pup/hub_inventorhub/light_off.py @@ -0,0 +1,15 @@ +from pybricks.hubs import InventorHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = InventorHub() + +# Turn the light on and off 5 times. +for i in range(5): + + hub.light.on(Color.RED) + wait(1000) + + hub.light.off() + wait(500) diff --git a/examples/pup/hub_movehub/light_animate.py b/examples/pup/hub_movehub/light_animate.py new file mode 100644 index 0000000..4de1486 --- /dev/null +++ b/examples/pup/hub_movehub/light_animate.py @@ -0,0 +1,16 @@ +from pybricks.hubs import MoveHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = MoveHub() + +# Make an animation with multiple colors. +hub.light.animate([Color.RED, Color.GREEN, None], interval=500) + +wait(10000) + +# Cycle through a rainbow of colors. +hub.light.animate([Color(h=i*8) for i in range(45)], interval=40) + +wait(10000) diff --git a/examples/pup/hub_movehub/light_blink.py b/examples/pup/hub_movehub/light_blink.py new file mode 100644 index 0000000..0e31f46 --- /dev/null +++ b/examples/pup/hub_movehub/light_blink.py @@ -0,0 +1,16 @@ +from pybricks.hubs import MoveHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub +hub = MoveHub() + +# Keep blinking red on and off. +hub.light.blink(Color.RED, [500, 500]) + +wait(10000) + +# Keep blinking green slowly and then quickly. +hub.light.blink(Color.GREEN, [500, 500, 50, 900]) + +wait(10000) diff --git a/examples/pup/hub_movehub/light_hsv.py b/examples/pup/hub_movehub/light_hsv.py new file mode 100644 index 0000000..50b8522 --- /dev/null +++ b/examples/pup/hub_movehub/light_hsv.py @@ -0,0 +1,16 @@ +from pybricks.hubs import MoveHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = MoveHub() + +# Use your own custom color. +hub.light.on(Color(h=30, s=100, v=50)) + +wait(2000) + +# Go through all the colors. +for hue in range(360): + hub.light.on(Color(hue)) + wait(10) diff --git a/examples/pup/hub_movehub/light_off.py b/examples/pup/hub_movehub/light_off.py new file mode 100644 index 0000000..5de6a43 --- /dev/null +++ b/examples/pup/hub_movehub/light_off.py @@ -0,0 +1,15 @@ +from pybricks.hubs import MoveHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = MoveHub() + +# Turn the light on and off 5 times. +for i in range(5): + + hub.light.on(Color.RED) + wait(1000) + + hub.light.off() + wait(500) diff --git a/examples/pup/hub_primehub/light_animate.py b/examples/pup/hub_primehub/light_animate.py new file mode 100644 index 0000000..1080154 --- /dev/null +++ b/examples/pup/hub_primehub/light_animate.py @@ -0,0 +1,23 @@ +from pybricks.hubs import PrimeHub +from pybricks.parameters import Color +from pybricks.tools import wait +from math import sin, pi + +# Initialize the hub. +hub = PrimeHub() + +# Make an animation with multiple colors. +hub.light.animate([Color.RED, Color.GREEN, None], interval=500) + +wait(10000) + +# Make the color RED grow faint and bright using a sine pattern. +hub.light.animate( + [Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40) + +wait(10000) + +# Cycle through a rainbow of colors. +hub.light.animate([Color(h=i*8) for i in range(45)], interval=40) + +wait(10000) diff --git a/examples/pup/hub_primehub/light_blink.py b/examples/pup/hub_primehub/light_blink.py new file mode 100644 index 0000000..1df0347 --- /dev/null +++ b/examples/pup/hub_primehub/light_blink.py @@ -0,0 +1,16 @@ +from pybricks.hubs import PrimeHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub +hub = PrimeHub() + +# Keep blinking red on and off. +hub.light.blink(Color.RED, [500, 500]) + +wait(10000) + +# Keep blinking green slowly and then quickly. +hub.light.blink(Color.GREEN, [500, 500, 50, 900]) + +wait(10000) diff --git a/examples/pup/hub_primehub/light_hsv.py b/examples/pup/hub_primehub/light_hsv.py new file mode 100644 index 0000000..7812ec5 --- /dev/null +++ b/examples/pup/hub_primehub/light_hsv.py @@ -0,0 +1,21 @@ +from pybricks.hubs import PrimeHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = PrimeHub() + +# Show the color at 30% brightness. +hub.light.on(Color.RED * 0.3) + +wait(2000) + +# Use your own custom color. +hub.light.on(Color(h=30, s=100, v=50)) + +wait(2000) + +# Go through all the colors. +for hue in range(360): + hub.light.on(Color(hue)) + wait(10) diff --git a/examples/pup/hub_primehub/light_off.py b/examples/pup/hub_primehub/light_off.py new file mode 100644 index 0000000..f13eb0d --- /dev/null +++ b/examples/pup/hub_primehub/light_off.py @@ -0,0 +1,15 @@ +from pybricks.hubs import PrimeHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = PrimeHub() + +# Turn the light on and off 5 times. +for i in range(5): + + hub.light.on(Color.RED) + wait(1000) + + hub.light.off() + wait(500) diff --git a/examples/pup/hub_shared/light_animate.py b/examples/pup/hub_shared/light_animate.py new file mode 100644 index 0000000..f6426be --- /dev/null +++ b/examples/pup/hub_shared/light_animate.py @@ -0,0 +1,25 @@ +from pybricks.hubs import ExampleHub +from pybricks.parameters import Color +from pybricks.tools import wait +# MOVEHUB SKIP_NEXT 1 +from math import sin, pi + +# Initialize the hub. +hub = ExampleHub() + +# Make an animation with multiple colors. +hub.light.animate([Color.RED, Color.GREEN, None], interval=500) + +wait(10000) + +# MOVEHUB SKIP_NEXT 6 +# Make the color RED grow faint and bright using a sine pattern. +hub.light.animate( + [Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40) + +wait(10000) + +# Cycle through a rainbow of colors. +hub.light.animate([Color(h=i*8) for i in range(45)], interval=40) + +wait(10000) diff --git a/examples/pup/hub_shared/light_blink.py b/examples/pup/hub_shared/light_blink.py new file mode 100644 index 0000000..5773a76 --- /dev/null +++ b/examples/pup/hub_shared/light_blink.py @@ -0,0 +1,16 @@ +from pybricks.hubs import ExampleHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub +hub = ExampleHub() + +# Keep blinking red on and off. +hub.light.blink(Color.RED, [500, 500]) + +wait(10000) + +# Keep blinking green slowly and then quickly. +hub.light.blink(Color.GREEN, [500, 500, 50, 900]) + +wait(10000) diff --git a/examples/pup/hub_shared/light_hsv.py b/examples/pup/hub_shared/light_hsv.py new file mode 100644 index 0000000..158d7ae --- /dev/null +++ b/examples/pup/hub_shared/light_hsv.py @@ -0,0 +1,22 @@ +from pybricks.hubs import ExampleHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = ExampleHub() + +# MOVEHUB SKIP_NEXT 5 +# Show the color at 30% brightness. +hub.light.on(Color.RED * 0.3) + +wait(2000) + +# Use your own custom color. +hub.light.on(Color(h=30, s=100, v=50)) + +wait(2000) + +# Go through all the colors. +for hue in range(360): + hub.light.on(Color(hue)) + wait(10) diff --git a/examples/pup/hub_shared/light_off.py b/examples/pup/hub_shared/light_off.py new file mode 100644 index 0000000..2d47358 --- /dev/null +++ b/examples/pup/hub_shared/light_off.py @@ -0,0 +1,15 @@ +from pybricks.hubs import ExampleHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = ExampleHub() + +# Turn the light on and off 5 times. +for i in range(5): + + hub.light.on(Color.RED) + wait(1000) + + hub.light.off() + wait(500) diff --git a/examples/pup/hub_shared/make_shared_examples.py b/examples/pup/hub_shared/make_shared_examples.py new file mode 100644 index 0000000..42980d6 --- /dev/null +++ b/examples/pup/hub_shared/make_shared_examples.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""Replaces all instances of ExampleHub in template with actual hub names. + +Optionally skips examples that do not work on a platform. +""" +import os + +# Which instance to replace +EXAMPLE_HUB = 'ExampleHub' + +# Define which hubs to run +HUBS = ['MoveHub', 'CityHub', 'TechnicHub', 'PrimeHub', 'InventorHub'] + +# This flag indicates to skip next X lines in a script +SKIP_FLAG = 'SKIP_NEXT' +skip_remaining = 0 + +# Get list of scripts to be parsed +script_names = [f for f in os.listdir('.') if f != 'make_shared_examples.py'] + +for hub in HUBS: + # Determine path to the hub + hub_path = os.path.join('..', 'hub_' + hub.lower()) + os.makedirs(hub_path, exist_ok=True) + + # Go through all template scripts + for script in (open(f, 'r') for f in script_names): + + # Open destination script: + with open(os.path.join(hub_path, script.name), 'w') as dest_file: + + # Read script line by line + for line in script.readlines(): + + # Replace hub name if present + line = line.replace(EXAMPLE_HUB, hub) + + # If there is a skip flag, parse it + if skip_remaining == 0 and SKIP_FLAG in line: + idx = line.find(SKIP_FLAG) + + # Get hub name and how many lines to skip + _, skip_hub, _, skip_len = line.split() + + # Skip lines if needed, and always skip the flag itself + if hub.lower() == skip_hub.lower(): + skip_remaining = int(skip_len) + 1 + else: + skip_remaining = 1 + + # If there are some lines left to skip, do so + if skip_remaining > 0: + skip_remaining -= 1 + # Otherwise print the line + else: + dest_file.writelines(line) diff --git a/examples/pup/hub_technichub/light_animate.py b/examples/pup/hub_technichub/light_animate.py new file mode 100644 index 0000000..06f68ab --- /dev/null +++ b/examples/pup/hub_technichub/light_animate.py @@ -0,0 +1,23 @@ +from pybricks.hubs import TechnicHub +from pybricks.parameters import Color +from pybricks.tools import wait +from math import sin, pi + +# Initialize the hub. +hub = TechnicHub() + +# Make an animation with multiple colors. +hub.light.animate([Color.RED, Color.GREEN, None], interval=500) + +wait(10000) + +# Make the color RED grow faint and bright using a sine pattern. +hub.light.animate( + [Color.RED * (0.5 * sin(i / 15 * pi) + 0.5) for i in range(30)], 40) + +wait(10000) + +# Cycle through a rainbow of colors. +hub.light.animate([Color(h=i*8) for i in range(45)], interval=40) + +wait(10000) diff --git a/examples/pup/hub_technichub/light_blink.py b/examples/pup/hub_technichub/light_blink.py new file mode 100644 index 0000000..441ad62 --- /dev/null +++ b/examples/pup/hub_technichub/light_blink.py @@ -0,0 +1,16 @@ +from pybricks.hubs import TechnicHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub +hub = TechnicHub() + +# Keep blinking red on and off. +hub.light.blink(Color.RED, [500, 500]) + +wait(10000) + +# Keep blinking green slowly and then quickly. +hub.light.blink(Color.GREEN, [500, 500, 50, 900]) + +wait(10000) diff --git a/examples/pup/hub_technichub/light_hsv.py b/examples/pup/hub_technichub/light_hsv.py new file mode 100644 index 0000000..ae76cf5 --- /dev/null +++ b/examples/pup/hub_technichub/light_hsv.py @@ -0,0 +1,21 @@ +from pybricks.hubs import TechnicHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = TechnicHub() + +# Show the color at 30% brightness. +hub.light.on(Color.RED * 0.3) + +wait(2000) + +# Use your own custom color. +hub.light.on(Color(h=30, s=100, v=50)) + +wait(2000) + +# Go through all the colors. +for hue in range(360): + hub.light.on(Color(hue)) + wait(10) diff --git a/examples/pup/hub_technichub/light_off.py b/examples/pup/hub_technichub/light_off.py new file mode 100644 index 0000000..4227d2f --- /dev/null +++ b/examples/pup/hub_technichub/light_off.py @@ -0,0 +1,15 @@ +from pybricks.hubs import TechnicHub +from pybricks.parameters import Color +from pybricks.tools import wait + +# Initialize the hub. +hub = TechnicHub() + +# Turn the light on and off 5 times. +for i in range(5): + + hub.light.on(Color.RED) + wait(1000) + + hub.light.off() + wait(500) diff --git a/examples/pup/light/basics.py b/examples/pup/light/basics.py new file mode 100644 index 0000000..a659757 --- /dev/null +++ b/examples/pup/light/basics.py @@ -0,0 +1,16 @@ +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) diff --git a/examples/pup/light/math.py b/examples/pup/light/math.py new file mode 100644 index 0000000..459d32e --- /dev/null +++ b/examples/pup/light/math.py @@ -0,0 +1,27 @@ +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) diff --git a/examples/pup/motor/motor_action_basic.py b/examples/pup/motor/motor_action_basic.py new file mode 100644 index 0000000..a7dbdb6 --- /dev/null +++ b/examples/pup/motor/motor_action_basic.py @@ -0,0 +1,46 @@ +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) diff --git a/examples/pup/motor/motor_action_then.py b/examples/pup/motor/motor_action_then.py new file mode 100644 index 0000000..bb06b14 --- /dev/null +++ b/examples/pup/motor/motor_action_then.py @@ -0,0 +1,24 @@ +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) diff --git a/examples/pup/motor/motor_action_wait.py b/examples/pup/motor/motor_action_wait.py new file mode 100644 index 0000000..6f26500 --- /dev/null +++ b/examples/pup/motor/motor_action_wait.py @@ -0,0 +1,14 @@ +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) diff --git a/examples/pup/motor/motor_action_wait_advanced.py b/examples/pup/motor/motor_action_wait_advanced.py new file mode 100644 index 0000000..a2b1e05 --- /dev/null +++ b/examples/pup/motor/motor_action_wait_advanced.py @@ -0,0 +1,18 @@ +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!") diff --git a/examples/pup/motor/motor_init_basic.py b/examples/pup/motor/motor_init_basic.py new file mode 100644 index 0000000..c771045 --- /dev/null +++ b/examples/pup/motor/motor_init_basic.py @@ -0,0 +1,18 @@ +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) diff --git a/examples/pup/motor/motor_init_direction.py b/examples/pup/motor/motor_init_direction.py new file mode 100644 index 0000000..a26f5f4 --- /dev/null +++ b/examples/pup/motor/motor_init_direction.py @@ -0,0 +1,16 @@ +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) diff --git a/examples/pup/motor/motor_init_gears.py b/examples/pup/motor/motor_init_gears.py new file mode 100644 index 0000000..59086ca --- /dev/null +++ b/examples/pup/motor/motor_init_gears.py @@ -0,0 +1,15 @@ +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) diff --git a/examples/pup/motor/motor_init_multiple.py b/examples/pup/motor/motor_init_multiple.py new file mode 100644 index 0000000..c93379c --- /dev/null +++ b/examples/pup/motor/motor_init_multiple.py @@ -0,0 +1,14 @@ +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) diff --git a/examples/pup/motor/motor_measure.py b/examples/pup/motor/motor_measure.py new file mode 100644 index 0000000..e00974a --- /dev/null +++ b/examples/pup/motor/motor_measure.py @@ -0,0 +1,22 @@ +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) diff --git a/examples/pup/motor/motor_reset_angle.py b/examples/pup/motor/motor_reset_angle.py new file mode 100644 index 0000000..ccd8b8e --- /dev/null +++ b/examples/pup/motor/motor_reset_angle.py @@ -0,0 +1,17 @@ +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() diff --git a/examples/pup/motor/motor_stop.py b/examples/pup/motor/motor_stop.py new file mode 100644 index 0000000..a65d0ac --- /dev/null +++ b/examples/pup/motor/motor_stop.py @@ -0,0 +1,30 @@ +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) diff --git a/examples/pup/motor/motor_until_stalled.py b/examples/pup/motor/motor_until_stalled.py new file mode 100644 index 0000000..e39b619 --- /dev/null +++ b/examples/pup/motor/motor_until_stalled.py @@ -0,0 +1,26 @@ +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) diff --git a/examples/pup/motor/motor_until_stalled_center.py b/examples/pup/motor/motor_until_stalled_center.py new file mode 100644 index 0000000..907b10c --- /dev/null +++ b/examples/pup/motor/motor_until_stalled_center.py @@ -0,0 +1,24 @@ +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) + +# Please have a look at the previous example first. This example +# finds two endspoints and then makes the middle the zero point. + +# The run_until_stalled gives us the angle at which it stalled. +# We want to know this value for both endpoints. +left_end = example_motor.run_until_stalled(-200, duty_limit=30) +right_end = example_motor.run_until_stalled(200, duty_limit=30) + +# We have just moved to the rightmost endstop. So, we can reset +# this angle to be half the distance between the two endpoints. +# That way, the middle corresponds to 0 degrees. +example_motor.reset_angle((right_end - left_end) / 2) + +# From now on we can simply run towards zero to reach the middle. +example_motor.run_target(200, 0) + +wait(1000) diff --git a/examples/pup/motor_dc/motor_dc_init_basic.py b/examples/pup/motor_dc/motor_dc_init_basic.py new file mode 100644 index 0000000..693ea54 --- /dev/null +++ b/examples/pup/motor_dc/motor_dc_init_basic.py @@ -0,0 +1,18 @@ +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) diff --git a/examples/pup/motor_dc/motor_dc_init_direction.py b/examples/pup/motor_dc/motor_dc_init_direction.py new file mode 100644 index 0000000..046d0d7 --- /dev/null +++ b/examples/pup/motor_dc/motor_dc_init_direction.py @@ -0,0 +1,17 @@ +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) diff --git a/examples/pup/motor_dc/motor_dc_stop.py b/examples/pup/motor_dc/motor_dc_stop.py new file mode 100644 index 0000000..a73aa31 --- /dev/null +++ b/examples/pup/motor_dc/motor_dc_stop.py @@ -0,0 +1,16 @@ +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) diff --git a/examples/pup/motor_pf/motor_pf_basics.py b/examples/pup/motor_pf/motor_pf_basics.py new file mode 100644 index 0000000..25558d3 --- /dev/null +++ b/examples/pup/motor_pf/motor_pf_basics.py @@ -0,0 +1,20 @@ +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() diff --git a/examples/pup/motor_pf/motor_pf_pwm.py b/examples/pup/motor_pf/motor_pf_pwm.py new file mode 100644 index 0000000..65c5bb0 --- /dev/null +++ b/examples/pup/motor_pf/motor_pf_pwm.py @@ -0,0 +1,25 @@ +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() diff --git a/examples/pup/sensor_color/color_ambient.py b/examples/pup/sensor_color/color_ambient.py new file mode 100644 index 0000000..731982e --- /dev/null +++ b/examples/pup/sensor_color/color_ambient.py @@ -0,0 +1,26 @@ +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) diff --git a/examples/pup/sensor_color/color_print.py b/examples/pup/sensor_color/color_print.py new file mode 100644 index 0000000..5c6f467 --- /dev/null +++ b/examples/pup/sensor_color/color_print.py @@ -0,0 +1,20 @@ +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) diff --git a/examples/pup/sensor_color/detectable_colors.py b/examples/pup/sensor_color/detectable_colors.py new file mode 100644 index 0000000..413c817 --- /dev/null +++ b/examples/pup/sensor_color/detectable_colors.py @@ -0,0 +1,39 @@ +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) diff --git a/examples/pup/sensor_color/hsv.py b/examples/pup/sensor_color/hsv.py new file mode 100644 index 0000000..4c60d15 --- /dev/null +++ b/examples/pup/sensor_color/hsv.py @@ -0,0 +1,21 @@ +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) diff --git a/examples/pup/sensor_color/lights_blink.py b/examples/pup/sensor_color/lights_blink.py new file mode 100644 index 0000000..08c72b3 --- /dev/null +++ b/examples/pup/sensor_color/lights_blink.py @@ -0,0 +1,27 @@ +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) diff --git a/examples/pup/sensor_color/wait_for_color.py b/examples/pup/sensor_color/wait_for_color.py new file mode 100644 index 0000000..aa6b58e --- /dev/null +++ b/examples/pup/sensor_color/wait_for_color.py @@ -0,0 +1,27 @@ +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) diff --git a/examples/pup/sensor_color_distance/color_print.py b/examples/pup/sensor_color_distance/color_print.py new file mode 100644 index 0000000..b744468 --- /dev/null +++ b/examples/pup/sensor_color_distance/color_print.py @@ -0,0 +1,19 @@ +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) diff --git a/examples/pup/sensor_color_distance/detectable_colors.py b/examples/pup/sensor_color_distance/detectable_colors.py new file mode 100644 index 0000000..51f5bd7 --- /dev/null +++ b/examples/pup/sensor_color_distance/detectable_colors.py @@ -0,0 +1,39 @@ +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) diff --git a/examples/pup/sensor_color_distance/distance_blink.py b/examples/pup/sensor_color_distance/distance_blink.py new file mode 100644 index 0000000..ce2f505 --- /dev/null +++ b/examples/pup/sensor_color_distance/distance_blink.py @@ -0,0 +1,23 @@ +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) diff --git a/examples/pup/sensor_color_distance/hsv.py b/examples/pup/sensor_color_distance/hsv.py new file mode 100644 index 0000000..a41a2b9 --- /dev/null +++ b/examples/pup/sensor_color_distance/hsv.py @@ -0,0 +1,21 @@ +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) diff --git a/examples/pup/sensor_color_distance/wait_for_color.py b/examples/pup/sensor_color_distance/wait_for_color.py new file mode 100644 index 0000000..04534b4 --- /dev/null +++ b/examples/pup/sensor_color_distance/wait_for_color.py @@ -0,0 +1,27 @@ +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) diff --git a/examples/pup/sensor_force/basics.py b/examples/pup/sensor_force/basics.py new file mode 100644 index 0000000..b979603 --- /dev/null +++ b/examples/pup/sensor_force/basics.py @@ -0,0 +1,21 @@ +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) diff --git a/examples/pup/sensor_force/peak.py b/examples/pup/sensor_force/peak.py new file mode 100644 index 0000000..026ea25 --- /dev/null +++ b/examples/pup/sensor_force/peak.py @@ -0,0 +1,45 @@ +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)) diff --git a/examples/pup/sensor_infrared/basics.py b/examples/pup/sensor_infrared/basics.py new file mode 100644 index 0000000..0b1bd3c --- /dev/null +++ b/examples/pup/sensor_infrared/basics.py @@ -0,0 +1,21 @@ +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) diff --git a/examples/pup/sensor_tilt/basics.py b/examples/pup/sensor_tilt/basics.py new file mode 100644 index 0000000..6b1f6c7 --- /dev/null +++ b/examples/pup/sensor_tilt/basics.py @@ -0,0 +1,16 @@ +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) diff --git a/examples/pup/sensor_ultrasonic/basics.py b/examples/pup/sensor_ultrasonic/basics.py new file mode 100644 index 0000000..9dd4a9e --- /dev/null +++ b/examples/pup/sensor_ultrasonic/basics.py @@ -0,0 +1,21 @@ +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) diff --git a/examples/pup/sensor_ultrasonic/math.py b/examples/pup/sensor_ultrasonic/math.py new file mode 100644 index 0000000..dde1825 --- /dev/null +++ b/examples/pup/sensor_ultrasonic/math.py @@ -0,0 +1,32 @@ +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)