Rubyと一緒(6) GR-CITRUS、digitalRead、ポーリングするしかない?

Joseph Halfmoon

特価品(見切り品?)のGR-CITRUSボード(RX631搭載)で組み込みRuby(mruby)してます。見つからないものに「割り込み」と「タイマ」のAPIがあります。しかたがないので今回は端子のデジタル入力をポーリングで監視、外部入力信号の周期を「ソフトループ」で測ってみました。そういうことにRuby使うなと?

Rubyのコードを練習するのに、以下のルネサス様のページにはお世話になっております。

GR-CITRUS 特設:クラス、メソッド早見表

舐めるように眺めていても発見できないのが、以下の3種類のAPIメソッドであります。

    1. 外部入力端子からの割り込み受けの設定
    2. タイマをつかった周期実行、あるいはタイムアウトの設定、もっと言うと入力キャプチャ機能の設定など
    3. メモリアドレスを直接指定しての読み書き

このくらいあると、Rubyちゃんの範囲で大抵のことはなんとかなるわな~と思いつつも、発見できてません。まあね、mrubyからCの関数を呼んだり、逆にCの関数からmrubyを呼び出すようなことを想定しているようなので、上のようなAPIをRubyレベルで用意する必要を認めなかったのかも知れませんな。知らんけど。

でもね、Cへ「エスケープ」してしまうとシリーズ「Rubyと一緒」一巻の終わりであります。なんとかRuby範囲でもうしばらく頑張りたいと思います。

今回の実験

前回アナログ入力がターゲットであったので今回はデジタル入力です。ただね、0だ、1だ、などということは読めて当然。実験になりませぬ。ここは準備されているRubyのAPIメソッドの範囲で以下を試みてみたいと思います。

外部端子をソフトウエアでポーリング、入力された周期信号の周波数の測定

当然Ruby処理系のオーバヘッドなど「もろみえ」なので、どんなもんなんでしょうか。ハシボー?

外部端子としては4番ピンを使いました。同じGR-CITRUSの開発環境でも、Arduino環境では使える筈の割り込みのアサインが無いらしい端子っす。

今回実験のRuby(mruby)ソース

今回実験のソースの目玉は、micros()メソッドです。これは処理系の方で準備してくれているタイマ利用のメソッドみたいです。呼ぶと起動時を0としたマイクロ秒単位の数値を返してくれるもの。オーバフローするのに1週間程度かかるという優れものです。タイマの直接制御はできないけれども、細かいレゾリューションで読めるメソッドは準備しておいてくれたと。これでガンバレってことかい?

ソースが以下に。

#!mruby
usb = Serial.new(0, 9600)
usb.println("digitalRead, Pin.4")
@pin=4
pinMode(@pin,0) #input, no pullup
loop_interval = 2000
while true do
    usb.println("Measure Frequency")
    while digitalRead(@pin) == 0 do
    end
    @start=micros()
    while digitalRead(@pin) == 1 do
    end
    while digitalRead(@pin) == 0 do
    end
    @end=micros()
    microsec = @end - @start
    hz = 1000000 / microsec
    usb.println("Width:    " + microsec.to_s + "[usec]")
    usb.println("Freqency: " + hz.to_s + "[Hz]")
    delay(loop_interval)
end
ハードウエアのセッティング

以下の写真のように、4番ピンに波形ジェネレータの信号を直接印加しとります。digitalReadDUTupd

印加している波形は、オフセット1.5V、振幅1.5V(ピークツーピークで3V)の矩形波です。デューティは50%に設定。

実験結果

まず500Hzの波形を印加した場合の測定結果。時間幅の期待値2000μsecに対して1995とか1997などの値が読めてます。このケースだけみると処理系オーバヘッド(それ以外の誤差もあるケド)は意外と小さいように見えます。measureFreq500Hz

印加波形を1kHzに切り替えました。期間が半分になったら誤差は一桁あがった感じですな。なして?measureFreq1kHz

さて2kHzです。usec単位の絶対値的には1kHzのときと似たり寄ったりの結果ですが、周波数に換算すると誤差が大きく見えますです。measureFreq2kHz

つづいて5kHzです。たまたまピッタンコの値が読めてますな。ビンゴ。ただし1回だけ。誤差はあります。measureFreq5kHz

10kHzの印加波形に対しては、ちょっとのカウント差が大きな変動に見えるので、ちょっとやってられない感じです。measureFreq10kHz

予想どおりとは言え、フラフラしてるな。

しかし、Rubyは整数同士の割り算は整数で商が求まるのではなかった?今回のソースの以下の部分、整数割り算のつもりだったのだけれど上記の結果をみると浮動小数になってますな。これはmrubyの仕様みたいです。

hz = 1000000 / microsec

bignumとか取っ払った分、float化?知らんけど。

Rubyと一緒(5) GR-CITRUSのADCの参照電圧、結局1種類じゃん?多分。へ戻る

Rubyと一緒(7) GR-CITRUS、出力端子(OD)、読み取りも出来るよね、念のため へ進む