Rubyと一緒(4) GR-CITRUSでDAコンバータを使ってみる、やっぱ10ビットだわ

Joseph Halfmoon

特価品(見切り品?)のGR-CITRUSボードで組み込みRuby(mruby)してます。前回はデジタル出力とはいえ、LPFなど通せばアナログ出力的に使えるPWMでした。今回はそのものズバリのアナログ、DAC出力を実験してみます。でもね、ちょいと文書の辻褄が合わないんです。どゆこと?

いつもお世話になっておりますルネサス様の以下のページを拝見すると

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

analogDac(value)メソッドの項に

DACピンからアナログ値を出力 0 ~ 4096(3.3V)

と書いてあります。ここにちょいと引っかかりましたです。同じくルネサス様の以下のマニュアルを拝見いたしますと

RX63Nグループ、RX631グループ ユーザーズマニュアル ハードウェア編

GR-CITRUSボードに搭載のRX631のDAコンバータは10bitとかかれてます。多分まあ、マニュアルどおりハードウエアは 10bit のDAなんだけれども何か「大人の事情」でRubyから見える出力値指定は12ビットになっているのであろう、と想像いたしました。今回はそれを実際に動かして確認してみた、の回です。

なおマニュアル上はDAC2チャンネル搭載ですが、GR-CITRUS上では9番ピンのみがDAC出力対応であるようなので、そこを使ってます。

Rubyとmrubyの違い1点

Ruby素人な上、GR-CITRUSに搭載されているmruby処理系についてもほとんど調べもせぬまま実行しとります。まあ mruby は Ruby のサブセットなんだろうから、Rubyとの違いはあるだろな~。あったらその時(に泥縄対応)くらいの勢いです。すみません。

今回そんな差を1つ発見。範囲を表す範囲オブジェクトについてです。Ruby処理系の場合、範囲オブジェクトの.step()というメソッドを使えば、以下の例のように「一つ飛ばし」などでループを回すことができます。

for i in (0..10).step(2) do puts i end

ところが、mrubyの場合、以下のようなコードを書いたらエラーになりました。

for dacout in (0 .. dacmax).step(dacstep) do

受け取ったエラーは以下のようなランタイムエラーです。NoMethodError

エラーメッセージをそのまま解釈すると、step()メソッドは無い、と言われているみたい。なお上記のように転送成功しているので、ビルドは成功、実行したらエラーというランタイム・エラーです。前回、ビルドでエラーの場合、エラーが発生したことだけ教えてくれて、場所や理由にまったく言及なかったことに比べれば、上記のランタイム・エラーの方がよっぽど親切。しかしメソッドが無いとかいうのはビルド時に分からんのか?不思議ね。

まあ、step()は避けてコードを書き直しました。

今回実験に使用した mruby のコード

実際にGR-CITRUS上で実行したコードは以下のようです。

#!mruby
usb = Serial.new(0, 9600)
usb.println("DAC, Pin.9")
tpin = 9
dacmax = 4096
dacstep = 1
initDac()
while true do
    dacout = 0
    while dacout < dacmax do
        analogDac(dacout)
        dacout += dacstep
    end
end

上記コードであると、ソフトウエアループの成り行きの速度で、0から4095まで1ずつプラスしながら舐めてます。これにて想定できるDAC出力波形は0から3.3Vまでのノコギリ波であります。

実験結果

データシートを拝見するにDAC出力の測定時には負荷抵抗に2MΩとりつけているみたいでした。そこで9番には2MΩとりつけてます。特にキャパシタンスはとりつけてません。まずは上記の dacstep=1 の場合の時間波形が以下に。DAC_OUT_TIM

期待通りのノコギリ波が生成できた?感じがします。Minimum値がマイナスになっているのは、測定精度も多少ありますが、最大出力から最小出力へ一気に遷移したためにアンダーシュートしてるのが大きい感じです。知らんけど。

繰り返しの周期の測定結果からすると1ビット出力あたりの経過時間は以下のように推定できます。

周期23.562ms / 4096 = 約5.8 μsec/bit

あれれ、以前にデジタル出力したときのビットバンギングよりも速いんでないかい。

ノコギリ波の下限付近を拡大してカーソルを置いてみました。ちょっと見ずらいですが、時間軸、電圧軸とも「階段状に見える段の4段分」とってます。DAC_OUT_STEP

まず時間軸方向から。

4段分のΔT = 91.825us、つまり = 1段 ΔT = 23.0 μsec

「遠くからみたときに」1ビット分の時間=約5.8 μsecでした。

5.8*4=23.2

であるので、上記の1段ΔTは4ビット相当の時間です。つまりソフトウエア上は4回DACに書き込んでいる筈なのだけれど、連続する4回分が同じ値の出力になってる、ということね。なんだ10ビットじゃん。予想通り。

次は電圧軸方向。

4段分の ΔV = 13.361mV、つまり1段ΔV = 3.34 mV

ざっくりしたところ、

3.34 * 1024 = 3.42V

で3.34mVステップで10ビットであればほぼほぼ辻褄があうので、やっぱり10ビットですな。

現在は無駄に4回も「同じ出力になる」値を連続して書き込んでいるので、dacstep=4にすれば、今と同じ電圧レゾリューションでもっと速い波形が可能では?やってみました。こんな感じ。step4tim

ソフトウエアループだけれども非常に安定しています。1周期16点とかで電圧出力したら、そこそこの速さで波形出力できるんでは?

16 * 5.75 = 92usec 約10870Hz

振幅控えめにしてローパス通せば数kHzくらいの結構綺麗な正弦波を発生できるんでないの?やってみる?

Rubyと一緒(4) GR-CITRUSでパッシブ・ブザーを鳴らしてみる へ戻る

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