Raspberry Pi PicoでPicoMite(MMBasic)を使う〜割込み

PicoMite(MMBasic)でも割り込みを利用できる。

割り込みにはディジタル入出力ピンの状態変化（入力信号の立ち上がり、立ち下がりまたはその両方）を検知しての割り込み、タイマによる周期的な割り込み、通信などさまざまな要因で生成される。

MMBasicでは入力信号の変化に対して最大10個、タイマ割り込みを最大4個設定できる。

2つ以上の割り込みが同時に発生した場合、割り込みの優先順位順に処理されます。
INPUT分や処理に時間のかかるハードウェア関連の操作中には認識されません。

ここでは以前使った人感センサからの信号の立ち上がりを検出する割り込みと、10秒周期にタイマ割り込みを発生させるプログラムを作成した。

# 使用部品

人感センサーSB412A-01-013と赤色LEDを利用した。

# 配線

図のようにGP0に人感センサー、GP1にLEDを接続した。

<!-- 実体配線図 -->
![INterrupy-PICO_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72921/1f425eef-4b39-44d5-9449-cd5cacfe4555.png)

SB412A-01-013のFritzing用のパーツを何とか作ってみた。


# プログラム

人感センサーで人を検出したら赤色LEDを0.5秒点灯させる割り込みと、10秒周期のタイマ割り込みのプログラムを以下に示す。

```BASIC:INTERRUPT.BAS
Dim count% = 0, tickcnt% = 0     ' Define variable
SetPin GP0, INTH, Detect         ' Define GP0 as a interrupt on low to high input
SetTick 10000, TickSub           ' Define priodic interrupt
SetPin GP1, DOUT                 ' Define GP1 as a digital output
Timer = 0                        ' Reset Timer

Do
  Pause 10
Loop

Sub Detect                         ' Define interruput subruoutine
  Local stime$ = Str$(Timer / 1000, 4, 1) + "sec" ' set local variable
  Pin(GP1) = 1                    ' Turn on LED
  Inc count%                      ' Increment counter variable
  Print stime$ + Str$(count%, 4) + " Interrupts"  ' print counter to console
  Pause 500                        ' Wait 500 msec'
  Pin(GP1) = 0                    ' Turn off LED'
End Sub

Sub TickSub                        ' Define priodic interrupt subroutine'
  Local stime$ = Str$(Timer / 1000, 4, 1) + "sec" ' Define local variable
  Inc tickcnt%                     ' Increment counter
  Print stime$ + Str$(tickcnt%, 4) +  " Tick" ' Print counter to console
End Sub

End
```

## プログラム冒頭部

割り込み回数のカウンタ変数(count%とtickcnt%)の定義と初期化を行ない、割り込みの定義を行なっている。

割り込みの定義を以下に示す。

<dl>
<dt>SETPIN GP0, INTH, Detect</dt>
<dd>人感センサーからの信号をトリガとなる信号を入力するピン（GP0）で入力信号の立ち上がり（INTH）を検出したら処理サブルーチン（Detect）で処理する。</dd>
<dt>SETTICK 1000, TickSub</dt><dd>LEDへのディジタル出力のピン（GP1）、タイマ割り込みのそれぞれを定義している。</dd>
</dl>

### タイマについて

PicoMiteは起動時、あるいは再起動時からの時間をミリ秒単位でカウントするタイマが動作している。`TIMER`関数でその値を取得でき、`Timer = 0`でリセットできる。

## DOループ

割り込みとウニ必要な定義を実行した後、DOループによる無限ループを実行してプログラムが停止しないようにしている。プログラムが停止しては

## サブルーチン：Detect

GP0に繋がれた人感センサーが人を検出したときの実行されるサブルーチンで以下の処理を実行する。
- タイマの時間を秒単位に変換した文字列を作り、ローカル変数へ代入
	- `LOCAL`はローカル変数の宣言文
- 赤色LEDを点灯させる
- `Inc`コマンドで割込み回数のカウンタ変数を1増やす
- タイマ、割り込み回数をコンソールに出力
- 500ミリ秒後に赤色LEDを消灯

## サブルーチン：TickSub

10秒ごとにタイマ割り込みで実行されるサブルーチンで以下の処理を実行する。
- 割り込み発生秒数の文字列を作る
- `Inc`コマンドで割込み回数のカウンタ変数を1増やす
- タイマ、割り込み回数をコンソールに出力

# 実行結果



```
> run
   1.4sec   1 Interrupts
   6.6sec   2 Interrupts
  10.0sec   1 Tick
  19.0sec   3 Interrupts
  20.0sec   2 Tick
  29.2sec   4 Interrupts
  30.0sec   3 Tick
  34.8sec   5 Interrupts
  40.0sec   4 Tick
  46.0sec   6 Interrupts
  50.0sec   5 Tick
  60.0sec   6 Tick
  70.0sec   7 Tick
  77.3sec   7 Interrupts
  80.0sec   8 Tick
  90.0sec   9 Tick
...
```

# 割り込みの設定について

## ピン入力による割り込み

MMBasicで入出力ピンへ入力で割り込み処理を実行するには`SETPIN`コマンドでピン番号、割り込みのトリガー、割込み処理サブルーチンを定義する。以下に構文を示す。

```
SETPIN pin, cfg, target [,option]
```

cfgに従ってpinが割り込みを生成するように設定します。デジタル入力可能なI/Oピンは、最大10個の割り込みを一度に設定して、割り込みを生成するように設定できます。

`cfg`は、以下のいずれかのキーワードを指定します。

| キーワード | 動作                                 |
| :---: | ---------------------------------- |
|  OFF  | 未設定または非アクティブ                       |
| INTH  | 入力がLowからHighに変化した際に割り込み            |
| INTL  | 入力がHighからLowに変化した際に割り込み            |
| INTB  | 入力がHighからLowに変化した際に割り込み（つまり、入力の変化） |

`target`は、イベント発生時に呼び出されるユーザー定義のサブルーチンです。割り込みからの復帰は、`END SUB`または`EXIT SUB`コマンドで行います。

`option`は、`SETPIN pin DIN`で使用されているものと同じです。
- 省略した場合、入力はハイインピーダンス
- PULLUPまたはPULLDOWNの場合、約50µAの定電流を使用して入力ピンを3.3Vにプルアップまたはプルダウンします。RP2350チップのバグのため、8.2K以下の抵抗を使用してプルダウンを実装することをお勧めします

このモードでは、ピンがデジタル入力としても設定されるため、関数PIN()を使用していつでもピンの値を取得できます。

## 周期的な割り込みの設定

周期的な割り込みのタイマ割り込みは`SETTICK`コマンドで割り込みの周期、割込み処理サブルーチンを指定します。最大4つのタイマ割り込みを定義できます。

```
SETTICK period, target [, nbr]
```

- periodeは割り込み間隔をミリ秒単位で指定
	- 周期は1～2147483647ミリ秒（約24日）の範囲で設定可能
- targetは時間指定イベント発生時に呼び出される割り込みサブルーチンを指定
- nbrはタイマ番号の指定で1から4まで指定でき、省略するとタイマ番号は1になる

周期的な割り込みは、periodを0に設定することで無効にできます（つまり、SETTICK 0, 0, 3とすると、ティックタイマー番号3が無効になります）。

# 参考サイトなど

- [PicoMite User Manual](https://geoffg.net/Downloads/picomite/PicoMite_User_Manual.pdf)