Raspberry Pi Pico(s_26)uasyncio の動作例 ThreadSafeFlag
uasyncio.ThreadSafeFlag()
Raspberry Pi PicoのMicroPythonにはmodule’uasyncio’があります。
uasyncioを使うと非同期動作するそうです。並行処理ができるようです。
module’uasyncio’にclass ‘ThreadSafeFlagがあります。
ThreadSafeFlagの使い方を他サイトなど調べて見ましたがよくわかりませんでした。
記事s_23で使ったフラグの代わり、記事s_24で使ったclass ‘Event’と同じように使うと動作しました。
(注意)本当に正しい使い方なのかは不明ですが記載しておきます。
素人なので詳しくはわかりません。わかる範囲で動作を確認しています。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。
class ‘ThreadSafeFlag
class ‘ThreadSafeFlagにはset、waitのメソッドがあります。
tsf = uasyncio.ThreadSafeFlag()で初期化した場合の例になります。
■tsf.set()
フラグを設定します。フラグセット待ちのタスクが実行されます。
■tsf.wait()
フラグが設定されるのを待ちます。
すでに設定されていればすぐに戻ります。wait から戻ったときに自動的にフラグはリセットされます。
ThreadSafeFlag動作
ThreadSafeFlagの動作の雰囲気だけ確認します。
単純に以下の時間毎に経過時間を印字するだけの関数test1、test2とします。
test1 0.5sec間隔、経過時間を3回印字
test2 0.2sec間隔、経過時間を5回印字
test1はtsf.wait()でフラグセットまで待機。
test2は3回目にtsf.set()でフラグをセット、test1が実行される。
図にすると以下のような感じです。
0.4sec + αくらいでtest2がフラグをセット、test1が実行されます。
以下のスクリプトで動作を確認しました
#ThreadSafeFlag_test_01b.py
import uasyncio
async def test1(tsf):
global st
print('tsf.wait---')
await tsf.wait() # フラグセット待ち
print('from wait--')
for i in range(3):
et=uasyncio.ticks() # et-st 経過時間
print(f'task1 ({i})s--- {et-st}')
await uasyncio.sleep(0.5)
async def test2(tsf):
for i in range(5):
et=uasyncio.ticks()
print(f'task2 ({i})s--- {et-st}')
if i==2:
print('tsf.set----')
tsf.set() # 3回目にセット
await uasyncio.sleep(0.2)
async def main():
global st
st=uasyncio.ticks() #開始時間
#ThreadSafeFlag オブジェクトを作成
tsf=uasyncio.ThreadSafeFlag()
task1 = uasyncio.create_task(test1(tsf)) #tsf設定
task2 = uasyncio.create_task(test2(tsf)) #tsf設定
await task1
await task2
et=uasyncio.ticks()
print('end',et-st)
uasyncio.run(main())
実行すると以下のようになりました。
フラグセットされるまで待機しているのがわかります。
>>> %Run -c $EDITOR_CONTENT
tsf.wait---
task2 (0)s--- 29
task2 (1)s--- 230
task2 (2)s--- 432
tsf.set----
from wait--
task1 (0)s--- 434
task2 (3)s--- 634
task2 (4)s--- 835
task1 (1)s--- 935
task1 (2)s--- 1436
end 1937
>>>
スクリプト
ThreadSafeFlagの動作が少しわかったので、LED1の点滅とIRセンサーの検出を常時行いながら、物体検出後に5回LED2を点滅をさせようと思います。(記事s_23、記事s_24と同じ動作を確認します。)
IRセンサー FC51の外観、接続例は記事d_28を参照ください。
ほぼhttps://www.route55go.com/self-study/pico/class/s024_event/のEventの部分を置き換えた形になります。ThreadSafeFlagにはevent.clear()に応じたメソッドがありませんが、wait から戻ったときに自動的にフラグがリセットされるので問題ないようです。結果的には物体検出フラグを使った記事s_23と同じような動きになります。
スクリプトは以下のようにしました。
#ThreadSafeFlag_01b_event.py
from machine import Pin
import time
import uasyncio
#OUT Pin
led1=Pin(22, Pin.OUT, value=0) #Y-LED
led2=Pin(26, Pin.OUT, value=0) #R-LED
#FC-51 IR Detector IRsens Pin
dpin=Pin(27, Pin.IN, Pin.PULL_DOWN) # 検知 dpin='L'
#LED1は常時点滅
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(tsf):
print('------Sens ')
while True:
if dpin.value()==0:
print('detect-----')
#event.set()
tsf.set()
await uasyncio.sleep(0.5)
print('------Check')
#検出まで待機、検出後 led2点滅 5回、event.clear()
async def LED2(tsf):
while True:
print('LED2 waiting ...')
#await event.wait()
await tsf.wait()
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()
print('clear------')
#非同期処理
async def main():
# Create an Event object.
#event=uasyncio.Event() #オブジェクトを作成
tsf=uasyncio.ThreadSafeFlag()
task1 = uasyncio.create_task(LED1())
task2=uasyncio.create_task(LED2(tsf))
task3=uasyncio.create_task(Sens(tsf))
# Wait until the task is finished.
await task1
await task2
await task3
uasyncio.run(main())
実行結果
結果は以下のようになりました。※Thonnyのshellに表示されます。
出力表示だけなのでわかり難いですがThreadSafeFlag動作でtask1、task2、task3が並行処理されています。
>>> %Run -c $EDITOR_CONTENT
LED1------
LED1 on # LED1点滅
LED2 waiting ... # tsf.wait()
------Sens
LED1 off
LED1 on
------Check # 検出確認
detect----- # IRセンサ検知 > tsf.set()
LED2 blink(0) # LED2点滅開始
LED1 off
LED1 on # LED1点滅
LED2 blink(1)
------Check # 検出確認
LED1 off
LED1 on
LED2 blink(2)
------Check
LED1 off
LED1 on
LED2 blink(3)
------Check
LED1 off
LED1 on
LED2 blink(4)
LED1 off
LED1 on
------Check
clear------
LED2 waiting ...
LED1 off
LED1 on
------Check
detect-----
LED2 blink(0)
LED1 off
LED1 on
LED2 blink(1)
省略
KeyboardInterrupt:
>>>
まとめ
uasyncioのclass ‘ThreadSafeFlagの使い方が少しわかったような気がします。