5. Switches, callbacks and interrupts¶
pyboard には USR と RST の2つの小さなスイッチがあります。RST スイッチはハードリセットのスイッチで、このスイッチを押すと、電源をオフにしてからオンに戻すことと同じように、最初から pyboard を再起動します。
USR スイッチは一般的な用途に使用され、Switch オブジェクトを介して制御されます。Switch オブジェクトを作成するには次のようにします:
>>> sw = pyb.Switch()
名前 pyb
が存在しないというエラーが発生した場合は、 import pyb
を入力してみてください。
Swicth オブジェクトを使うと、次のようにして状態を取得できます:
>>> sw.value()
False
スイッチが押されていなければ False
が表示され、押されていれば True
が表示されます。USR スイッチを押したままで。上記のコマンドを実行してみてください。
Switch オブジェクトを「呼び出す」ことによって、スイッチの状態を取得する省略記法もあります:
>>> sw()
False
5.1. スイッチのコールバック¶
Switch オブジェクトは非常に簡単なものですが、高度な機能が1つあります。それは``sw.callback()`` 関数です。コールバック関数は、スイッチが押されたときに実行するものを設定し、割り込みを使用します。割り込みの仕組みを理解する前に、例をあげるところから始めるのが一番よいでしょう。プロンプトで次のコマンドを実行してください。
>>> sw.callback(lambda:print('press!'))
これは、スイッチが押されるたびに press!
を表示するように Switch オブジェクトに伝えます。これを試してみてください。USR スイッチを押して PC の出力を見てください。これは、入力に割り込み、非同期に実行される割り込みルーチンの例です。
もう一つの例をあげておきます:
>>> sw.callback(lambda:pyb.LED(1).toggle())
これは、スイッチを押すたびに赤色の LED の点灯/消灯を切り替えます。そして、他のコードが実行されている間も動作します。
スイッチのコールバックを無効にするには None
をコールバック関数に渡します:
>>> sw.callback(None)
スイッチのコールバックには、(引数の無い)関数を渡すことができます。上の例では Python の lambda
機能を使って無名関数を作成しました。しかし、次のようにしても同ことができます:
>>> def f():
... pyb.LED(1).toggle()
...
>>> sw.callback(f)
これは f
という関数を作成し、それをスイッチコールバックに割り当てます。機能が lambda
で扱うには複雑である場合は、このようにすることができます。
コールバック関数ではメモリを割り当ててはいけません(たとえば、タプルやリストは作成できません)。コールバック関数は比較的シンプルでなければなりません。リストを作成する必要がある場合は、事前に作成してグローバル変数に格納します(またはローカル変数にして、そのローカル内に閉じるようにしてください)。長くて複雑な計算が必要な場合、コールバックではフラグを設定するようにし、そのフラグに他のコードが応答するようにしてください。
5.2. 割り込みの技術的な詳細¶
スイッチのコールバックで何が起きているのかを詳しく見てみましょう。 sw.callback()
で関数を登録すると、Switch オブジェクトはスイッチが接続されているピンに外部割り込みトリガ(立下りエッジ)を設定します。これにより、マイクロコントローラがピンの変化を監視するようになり、次のことが起きます:
スイッチが押されると、ピンに変化が生じ(ピンがローからハイに変化する)、マイクロコントローラはこの変化を登録します。
マイクロコントローラは、現在の機械命令の実行を終了し、処理を中断し、現在の状態を保存します(レジスタをスタックにプッシュする)。これには、任意のコード、たとえば実行中の Python スクリプトを一時停止するという効果があります。
マイクロコントローラは、スイッチの外部トリガに関連付けられた特別な割り込みハンドラの実行を開始します。この割り込みハンドラは
sw.callback()
で登録した関数を取得して実行します。コールバック関数が終了するまで実行され、スイッチの割り込みハンドラに制御を戻します。
スイッチ割り込みハンドラが復帰し、割り込みが処理されたことがマイクロコントローラに通知されます。
マイクロコントローラは、ステップ2で保存した状態を復元します。
最初に実行されていたコードの実行が継続されます。このコードは割り込まれたことに感づいていません。
上記の一連のイベントは、複数の割り込みが同時に発生した場合には少し複雑になります。その場合、最も優先順位の高い割り込みが優先され、次に優先順位の高い順に割り込みが実行されます。スイッチ割り込みは、最も低い優先度に設定されます。
5.3. 参考文献¶
ハードウェア割り込み利用の詳細については、 writing interrupt handlers の記述を参照してください。