稼働中

Raspberry Pi Pico(s_24)uasyncio の動作例 Event

uasyncio.Event()

Raspberry Pi PicoのMicroPythonにはmodule’uasyncio’があります。
uasyncioを使うと非同期動作するそうです。並行処理ができるようです。
uasyncioを使ってIRセンサー FC51の検知動作を確認します。IRセンサー FC51の外観、接続例は記事d_28を参照ください。
記事d_29ではIRセンサーの検出をフラグで認識していました。
module’uasyncio’にあるclass ‘Event’で同じような処理ができそうです。
素人なので詳しくはわかりません。わかる範囲でEvent動作を確認してみようと思います。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。

class ‘Event’

class ‘Event’にはis_set、set、clear、waitのメソッドがあります。
event=uasyncio.Event()で初期化した場合の例になります。
■event.is_set()
イベント設定の有無 True/Falseを返します。
■event.set()
イベントを設定します。
■event.clear()
イベントを非設定にします。
■event.wait()
イベントが設定されるまで待機します。イベントが設定されていれば戻ります。

スクリプト

IRセンサー FC51の外観、接続例は記事d_28を参照ください。
LED1の点滅とIRセンサーの検出を常時行いながら、物体検出後に5回LED2を点滅をさせようと思います。
記事s_23と同じ動作を確認します。)

スクリプトは以下のようにしました。


#led_while_02_event.py
from machine import Pin
import time
import uasyncio

#OUT Pin
led1=Pin(22, Pin.OUT, value=0)  #R-LED(常時点滅)
led2=Pin(26, Pin.OUT, value=0)  #Y-LED(検出点滅)

#FC-51 IR Detector Pin 常時検出
dpin=Pin(27, Pin.IN, Pin.PULL_DOWN)  # 検出 dpin='L'

#LED1は常時点滅 on/off 0.2sec
async def LED1():
    print('LED1------')
    while True:
        led1.high()
        print('LED1  on')
        await uasyncio.sleep(0.2)
        led1.low()
        await uasyncio.sleep(0.2)
        print('LED1  off')

#FC-51常時監視 検出したらevent.set()
async def Sens(event):
    #event.確認 > set
    print('------Sens ',event.is_set())
    while True:
        #検出したらevent.set
        if dpin.value()==0:
            print('detect-----')
            event.set()
        await uasyncio.sleep(0.5)
        print('------Check',event.is_set())
        
#検出まで待機、検出>led2点滅5回>event.clear()
async def LED2(event):
    while True:
        print('LED2  waiting ...',event.is_set())
        await event.wait()  # event set されるまで待機

        for i in range(5):
            print(f'LED2  blink({i})')
            led2.high()
            await uasyncio.sleep(0.2)
            led2.low()
            await uasyncio.sleep(0.2)
        event.clear()       #enent クリア
        print('clear------',event.is_set())

#非同期処理    
async def main():
    # Create an Event object.
    event=uasyncio.Event()  #イベントのオブジェクトを作成。
    task1 = uasyncio.create_task(LED1())
    task2=uasyncio.create_task(LED2(event))
    task3=uasyncio.create_task(Sens(event))
    
    #タスクが終わるまで待機
    await task1
    await task2
    await task3

uasyncio.run(main())

部分説明

task1(async def LED1())はLED1を0.2sec間隔で点滅
task2=uasyncio.create_task(LED2(event))はevent.wait()でイベントセットされるまで待機します。
task3で物体検出されイベントセットになればLED2を0.2sec間隔で5回点滅させます。
点滅後はイベントクリアにします。
task3(async def Sens(event))はIRセンサー(FC-51)の出力を0.5sec間隔で確認します。
検出したらイベントセットします。
task1、task2は常時並行動作しており、検出後はtask1、task2、task3が並行動作している感じです。
task3終了後はtask1、task2は常時並行動作に戻ります。

ちなみに、uasyncio.gather を使えば簡潔になります。
async def main():
# Create an Event object.
event=uasyncio.Event() #イベントのオブジェクトを作成
await uasyncio.gather(LED1(),LED2(event),Sens(event))
で良いのだろうと思います。

実行結果

結果は以下のようになりました。※Thonnyのshellに表示されます。
出力表示だけなのでわかり難いですが、task1、task2、task3が並行処理されています。
検出後にeventをセットするとLED2が点滅動作しています。点滅終了後はeventをクリアして元の動作に戻っています。


>>> %Run -c $EDITOR_CONTENT
LED1------
LED1  on                    #LED1点滅開始
LED2  waiting ... False     #event なし
------Sens  False           #event なし
LED1  off
LED1  on                    #LED1点滅開始
------Check False           #検出確認 なし
LED1  off
LED1  on
------Check False
detect-----                 #検出確認 あり>イベントセット
LED2  blink(0)              #LED2点滅開始
LED1  off
LED1  on
LED2  blink(1)
------Check True            #イベントセット維持
LED1  off
LED1  on
LED2  blink(2)              #イベントセット維持(LED2点滅5回まで)
------Check True
LED1  off
LED1  on
LED2  blink(3)
LED1  off
LED1  on
------Check True
LED2  blink(4)
LED1  off
LED1  on
------Check True
clear------ False               #イベントクリア維持
LED2  waiting ... False         #event なし
LED1  off
LED1  on
------Check False               #検出確認 なし
LED1  off
LED1  on
------Check False
detect-----                 #検出確認 あり>イベントセット
LED2  blink(0)              #LED2点滅開始
LED1  off
LED1  on
(省略)
KeyboardInterrupt: 
>>> 

まとめ

uasyncioのclass ‘Event’の使い方が多少わかったような気がします。