9. タイマー¶
pyboard には14個のタイマーがあり、それぞれのタイマーはユーザー定義の周波数で動作する独立したカウンターで構成されています。これらは特定の間隔で関数を実行するように設定できます。14個のタイマーは 1 から 14 までの番号が付けられていますが、2 は内部使用のために予約されており、5 と 6 はサーボおよび ADC/DAC 制御に使用されています。できれば、これらのタイマーを使わないでください。
タイマーオブジェクトを作成してみましょう:
>>> tim = pyb.Timer(4)
作成したものを見てみましょう:
>>> tim
Timer(4)
これで tim
にはタイマー番号 4 になっていることがわかりますが、まだ初期化されていません。ですから 10Hz (毎秒10回)でトリガするように初期化しましょう:
>>> tim.init(freq=10)
これで初期化されたので、タイマーに関するいくつかの情報を見ることができます:
>>> tim
Timer(4, prescaler=624, period=13439, mode=UP, div=1)
この情報は、このタイマーがペリフェラルクロック速度を 624+1 で割った値で動作するように設定されていることを意味し、0 から 13439 までカウントし、その時点で割り込みをトリガし、0 から再びカウントを開始します。これはタイマのトリガが 10Hz になるように設定します。タイマのソース周波数は 84MHz (tim.source_freq()
の実行でわかります)なので、84MHz/625/13440 = 10Hz になります。
9.1. タイマーカウンター¶
では、このタイマーで何ができるでしょうか? 最も基本的なことは、カウンタの現在の値を取得することです:
>>> tim.counter()
21504
このカウンタは連続的に変化し、カウントアップしていきます。
9.2. タイマーコールバック¶
次に、タイマーがトリガーするときに実行するコールバック関数を登録します(コールバック関数については スイッチのチュートリアル を参照):
>>> tim.callback(lambda t:pyb.LED(1).toggle())
すぐに赤いLEDが点滅し始めるはずです。5Hzで点滅します(1回のフラッシュに2回のトグルが必要なため、10Hz でトグルすると 5Hz で点滅します)。タイマーを再初期化することによって、周波数を変更できます:
>>> tim.init(freq=20)
コールバックを無効にするには、値を None
を渡します:
>>> tim.callback(None)
コールバックに渡す関数は、トリガーしたタイマーオブジェクトである引数1つを取る必要があります。これにより、コールバック関数内からタイマーを制御できます。
2つのタイマーを作成して、それぞれ独立して実行できます:
>>> tim4 = pyb.Timer(4, freq=10)
>>> tim7 = pyb.Timer(7, freq=20)
>>> tim4.callback(lambda t: pyb.LED(1).toggle())
>>> tim7.callback(lambda t: pyb.LED(2).toggle())
コールバックは適切なハードウェア割り込みであるため、これらのタイマーが実行されている間も、他の処理のために pyboard を使い続けることができます。
9.3. マイクロ秒カウンタを作る¶
タイマーを使用してマイクロ秒カウンタを作成できます。これは、正確なタイミングが必要な作業を行う場合に便利です。このためには、32ビットのカンターを持つタイマー 2 を使います(タイマー 5 も同様ですが、タイマー 5 を使ってしまうと、同時にはサーボドライバーを使えなくなります)。
タイマー 2 は次のように設定します:
>>> micros = pyb.Timer(2, prescaler=83, period=0x3fffffff)
prescaler を 83 に設定するので、このタイマは 1MHz でカウントされます。つまり、168MHz で動作するCPUクロックを2で割った後、prescaler+1 で割ることで、タイマー 2 に 168MHz/2/(83+1)=1MHz の周波数を与えているということです。period を大きな値にしているので、タイマーは大量にカウントアップしないと 0 に戻りません。この場合は、この場合、サイクルが0に戻る前に約17分かかります。
このタイマーを使用するには、最初に0にリセットすることをお勧めします:
>>> micros.counter(0)
では、実行してみてください:
>>> start_micros = micros.counter()
... do some stuff ...
>>> end_micros = micros.counter()