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’の使い方が多少わかったような気がします。