MicroPython的午睡(84) STM32版、Timer1入力キャプチャで周波数測定

Joseph Halfmoon

MicroPythonの場合、タイマのPWM出力機能をサポートしている処理系は多いですが、タイマの外部入力機能をサポートしている処理系は少ないように思います。しかしSTM32用の処理系の場合、入力機能もいくらかサポートされています。今回は入力キャプチャ機能を使って外部から与える信号の周波数を測ってみたいと思います。

※「MicroPython的午睡」投稿順 Indexはこちら

参照ドキュメント

実験は第77回でインストールしたSTマイクロエレクトロニクス社製、Nucleo-F401REボード用のMicroPythonで行っています。しかしpyboard版のTimerに関する以下のページがそのまま適用可能なようです。

class Timer — control internal timers

上記のTimerのチャネル機能の下の方にひっそりとInput Capture関係の定数などが記されています。

インプットキャプチャ

インプットキャプチャは、外部信号の立ち上がり/立下りエッジなどのイベントが発生したことを検出し、そのときのタイマ・カウンタの値を専用のレジスタに保存するためのモードです。通常カウンタは「フリーラン」状態としておきます。これによってイベント発生のときのカウンタ値がわかるので、そこから所望の時間が経過した後に外部に信号を出力する(アウトプットコンペア)など制御などに使えるモードです。今回は以下の方法で外部から入力される周期的な信号の周波数を求めたいと思います。

    1. 立ち上がりエッジのときに入力キャプチャを行い値を保存しておく
    2. 再び立ち上がりエッジのときに入力キャプチャを行う。
    3. 2回目の値と1回目の値の差(カウント値)が時間差であるので、1カウントの時間がわかれば周期もしくは周波数が計算できる。

いつ発生するかわからない入力キャプチャのイベントを割り込み駆動で検出するのが普通だと思うのですが、今回は簡単のため「ポーリング」にしています。その他もいろいろ手抜き。まあ、入力キャプチャ動作が確認できればという程度。

実験に使用したソースコード

実験に使用したMicroPythonソースが以下に。例によって前回のコードのチョイ変です。前回と同じTimer1のチャネル1を使用しています。

#STM32: Timer 1 IC Test
#Timer1 CH1 ... PA8(D7)
import pyb
import machine
import time

def main():
    print("STM32F401RE Timer 1 IC Test.")      
    tim = pyb.Timer(1, prescaler=1023, period=0xffff)
    icCH = tim.channel(1, pyb.Timer.IC, polarity=pyb.Timer.RISING, pin=machine.Pin.board.D7)
    print("Source  Freq: {0} Hz".format(tim.source_freq()))
    print("Timer 1 Freq: {0} Hz".format(tim.freq()))
    while True:
        oldV = icCH.capture()
        nV = icCH.capture()
        while oldV == nV:
            nV = icCH.capture()
        itvl = nV-oldV
        if itvl > 0:
            print("Diff: {} Freq: {} [Hz]".format(itvl, (0x10000/itvl)*tim.freq()))
        time.sleep(1)

if __name__ == "__main__":
    main()
実験結果

インプット・キャプチャモードに設定すると該当のチャネルに対応した端子は入力に設定されます。今回は前回同様なので、Nucleo-F401REボードのArduino互換ピンソケットのD7端子がキャプチャ入力になります。

冒頭のアイキャッチ画像に掲げましたが、D7端子の先に念のため(万が一出力がぶつかっても大電流流れないように)抵抗をつけてDigilent Analog Discovery2のAWG1端子から入力波形を与えてます。

同じ端子を黄色のC1のオシロで見たところが以下に。最初は5Hzの入力波形。WAV5Hz

上記信号をMicroPythonのスクリプトで測定したものが以下に。MicroPython上では若干遅い4.92Hzくらいの信号として見えてます。上記のスクリプト設定ですとこのくらい遅いクロックであるとほぼほぼ一定値。IC5Hz

続いて入力を10Hzにしてみました。

WAV10Hz

結果が以下に。まあ測定できとりますな。

IC10Hz

今度は一気に1kHzに周波数を上げてみました。こんな感じ。

WAV1kHz

測定結果が以下に。

IC1kHz

まあまあかね。前回のクロックソースの表を見ながらプリスケーラの値をいろいろ調整すれば、もっと速い信号にも対応可能じゃないかと思います。知らんけど。

MicroPython的午睡(83) STM32F401RE版、Timer1、クロック周波数 へ戻る

MicroPython的午睡(85) STM32版、入力キャプチャから出力コンペア へ進む