LoginSignup
0
0

Pybricks のマルチタスク

Last updated at Posted at 2023-12-16

はじめに

Pybricks にはサブプロセスやスレッドはありませんが、v3.3よりコルーチンを利用した協調的マルチタスクをサポートしています。

CPython や 通常の MicroPython では asyncio モジュールを使うところでしょうが、Pybricksでは、APIの後方互換性やリソース削減の都合から、独自のマルチタスク機能を提供しています。

マルチタスク用のAPI

マルチタスクのための API は主に次の2つです。

from pybricks.tools import multitask, run_task
  • multitask(coroutine1, coroutine2, ...)
    複数のコルーチンを実行するコルーチンを作成します。これによりマルチタスクが実現されます。
  • run_task(coroutine)
    コルーチンを実行します。これはメインコルーチンの実行に利用します。

コルーチン化可能なAPI

Pybricks v3.3以降のドキュメントで await プレフィックスのついた API はコルーチン化可能です。

たとえば Motor の API にある次のようなものです。

await run_time(speed, time, then=Stop.HOLD, wait=True)

このような API を await つきで呼び出すとコルーチンになり、await なしで呼び出すと従来どおりの呼び出しになります。

簡単な例

「きらきら星」を鳴らしながら、モーターをメトロノーム風に左右に反復させるデモです(あくまでメトロノーム風で厳密な動きはしていません)。スピーカ鳴らすのと、モーター動かすのを、それぞれ独立にコルーチンにし、マルチタスク実行しています。

IMG_7219.JPG

from pybricks.hubs import PrimeHub
from pybricks.pupdevices import Motor
from pybricks.parameters import Port
from pybricks.tools import multitask, run_task

hub = PrimeHub()

notes = [
    "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"
]

tempo = 120
motor_speed = tempo

motor = Motor(Port.A)
motor.reset_angle()

# きらきら星を演奏するコルーチン
async def kirakira():
    await hub.speaker.play_notes(notes, tempo=tempo)

# モーターをメトロノーム風に左右に反復させるコルーチン
async def metronome():
    for _ in range(len(notes)//2):
        await motor.run_angle(motor_speed, 60)
        await motor.run_angle(motor_speed, -60)

# メイン
async def main():
    await motor.run_angle(motor_speed, -30)
    await multitask(kirakira(), metronome())
    await motor.run_angle(motor_speed, 30)

# 開始から終了までメインプログラムを走らせる。
run_task(main())
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0