2021年1月1日金曜日

PICのADC2格闘 その2

(1)データー出力レジスタの間違いの話

 前回の話の続き、バースト平均化モードでは目的達成不可と判明したので、
今度は平均化モードで挑戦することに。

平均化モードでは個々のサンプリングのトリガーがこちら側で制御可能。
ならば一定間隔を空けてトリガーを掛け、全体で20msになる様、調整してやれば良いはず。
とは言え、20msをソフト的に設定することは出来ないので、
PICのI/Oピンからタイミング信号を出し、オシロスコープで時間を測ります。

この目論見は成功。
トリガー間隔を微調整することで目標の20msに合わせることが出来ました。
と・こ・ろ・が・・・・・・・・・・・あくまで感覚的な話なのですが
なんとなく平均化されていないような感触がするんです。
というのも、データー値の変動が平均化前と一緒っぽい。

改めてマニュアルを調べてて私の勘違いに気が付きました。
単発のデーターと平均化処理したデーターが出てくるレジスタは別物だった!!

平均化処理も何もしていない素のデーターというのはADRESというレジスタに入ります。
このレジスタ名は従来のADCの出力データーレジスタと同一。
なので、ADC2の出力データーレジスタも てっきりADRESだと思い込んでました。

しかし実際には平均化処理データーが出てくるのはADFLTRというレジスタでした。
なんと紛らわしいことやら。
平均化処理を使っててもADRESからデーターを読むことが可能ですが、
そんな使い方する人は ほぼ皆無でしょう。
ならばデーター出力のレジスタは統一して欲しかったところです。
この辺りからADC2のインテリジェンス性に疑問を感じ始めたところ。

(2)ADRPTとADCRSの謎

出力レジスタの間違いに気付き、早速修正を行いまして、いざ再実行。
すると・・・・・・・やっぱり値が変。 orz

あれこれ試して、やっと原因が判明しました。
それはマニュアルに記載されている下の式。

ADRPT = 2^ADCRS

これだけ見ると、ADRPTを設定すればADCRSにも値がセットされる様に思われます。
しかし両方とも読み書き可能なレジスタだし、そもそも2^ADCRSは2のべき乗値。
ADRPTからADCRSへの変換は不可能でしょうから、
ADCRSを設定するとADRPTに値が入るという解釈かと。

と、このように漠然と解釈していたのですが、全く違いました。
この2つのレジスタは目的が異なるもので、
それぞれ設定してやる必要がありました。

ADRPTは平均化処理の際のサンプリング回数を設定するもの。
それに対しADCRSはサンプリングにて積算されたデーターを
ADFLTRレジスタに出力する際に割り算する値を設定するのでした。

だから上の式の意味は、「ADRPT」と「2^ADCRS」が同じ値の時に、
平均化処理が成り立つんだよ、という意味なのでした。
なんという紛らわしい記載や。 orz

そもそもですよ、平均化するという動作モードならば、
常にこの2つの値は同一になっていなければならないじゃないですか。
ならばこれをユーザーがレジスタ設定で合わせるという仕様はおかしいわけです。
この時点で確信しました。
ADC2はインテリジェントなユニットではないと。

上に書いた様に、2^ADCRSは2のべき乗値ですから、
ADRPTの値も好きな値を使うわけにいきません。
ADCRSは3bit長なので、設定可能値は0~7。
2^0 = 0
2^1 = 2
2~2 = 4
2^3 = 8
2^4 = 16
2^5 = 32
2^6 = 64
2^7 = 128
具体的に2^ADCRSの値は上記8つしか選べないわけです。
で、ADRPTもこれに合わせる必要があるわけですから、
ADRPTの値も8種類しか選べません。

もう、最初のADC2への期待がボロボロと音とを立てて崩れてます。(;;

気を取り直して、サンプリング回数128回の設定で試してみることに。
ADCRS = 7、ADRPT = 128 という設定ですね。

いざ動かしてみると平均値データーが明らかに変!!

予想されるデーター値はだいたい判っていたのですが、とんでもなく値が異なっていました。
今度は何や。(;;

これですが、ADC2の内部構成に問題が有りました。
サンプリングデーターが積算されていくレジスタはADACCなのですが、
このレジスタ、16bit長しかありません。
今回使っているA/Dコンバーターは10bitなので、
10bit長のデーターを128回積算するとADACCが溢れてしまうのです。
なんという設計仕様。orz

なので今回の場合は64回までしか積算してはいけないというオチだったのです。
こんなのユーザーが考えて設定値に制限加えなければならないなんて、
ADC2は なんと頭の悪いユニットなのでしょう。(;;
PIC16F18456の場合、A/Dコンバーターは12bitなので、
積算回数は16回が上限ということになるんでしょうねぇ、きっと。

気を取り直して、ADCRSに6、ADRPTに64を設定したら、
それっぽいデーターが出力されるようになりました。
とは言え、こんな罠のような仕様があるならば、ADC2で平均化処理せずに、
ソフトウェアで処理した方が よほど安心な気がします。
積算回数の上限も無くなるし、ソフトで処理してもそんなに重くはないです。
ADC2の平均化モードは 存在価値に かなりの疑問を感じます。

1つ、確実に判明している問題として、平均化処理時の割り算計算についてです。
真っ当な計算ユニットであれば、割り算時に発生する端数の丸め処理も、きちんと行うはず。
しかしADC2の場合、ADCRSの設定値に従ってビットシフトするだけで、
端数の丸め処理を行っていません。
(マニュアルにも記載が無いので、念のために実機確認してみましたが、
やはり丸め処理は行われていませんでした。)
偶数をビットシフトで割る場合は端数が出ないので問題になりませんが、
奇数の場合は端数が出てくるので、ちょっと問題があります。

具体例を挙げますと、10進数で111という値を4で割ります。
単純:計算なら 111 ÷ 4 = 27.75 となりますね。
これをビットシフト方で割り算してみましょう。
10進の111 => 2進で1101111
4で割るというのは、右側に2ビットシフトすることになりますので、
1101111を2ビットシフトすると11011。
11011を10進に戻すと27です。
27.75が27として出力されてしまうわけです。
簡易計算ならともかく、真っ当な計算ユニットとしては、これは問題でしょう。
とりあえず、今回はADC2を利用する前提の話なので、
この問題はスルーいたしますが、後日改めて対策することにします。

余談になりますが、対策するとしたら以下の2つの方法が考えられます。
・1つ目は平均化処理を全てソフトで処理する。
・2つ目は、ADC2を積算モードで動かし、ソフトで割り算処理を行う。
・3つ目として、ADCRSの値を1少ない値に設定し、丸め処理を含めた割り算をソフトで行う。

3つ目の方法は捻り技になるかもしれません。
ADCRSの値を1少なくすると、平均値の2倍の値が出力されます。
上記の計算例なら、2進の1101111を4ではなく2で割ることになるので、
計算結果は110111、つまり55という値が得られます。
これをソフトにて丸めも含めて÷2の処理すると28という値が出るわけです。

ともあれ、とりあえず平均化モードは動くようになったぽいので、
一安心かと思いきや、今度は別な問題が浮かび上がってきました。
それについては次回へ。

(続く)

0 件のコメント:

コメントを投稿