dsPIC33CK256MP505では、2個のDedicated(専用)ADCと1個のShared(共用)ADCがあり、どちらもオーバーサンプリングフィルタを設定できます。今回初めて使ってみました。
いつもDedicatedADCは主にPWMトリガで電流検出に使うため、サンプルタイミングがクリティカルなのでオーバーサンプリングをしたことがありません。今回はADC1を1ms周期の普通のアナログ入力にしたので、適用してみました。
応用に使ったボードは20KHzPWMで強烈なスイッチングをしているのでセンサ入力など中・低速サンプリングには結構なノイズが乗ってきます。
dsPIC33CKのオーバーサンプリングフィルタとは
リファレンス・マニュアルによれば
「アナログ入力を要求サンプリング レートよりも高いレートでサンプリングし、これにオーバーサンプリング フィルタを適用する事で、変換スループットは低下するものの、ADC モジュールの実効分解能を向上させる事ができます。」
ということですが、MCUの最速サンプリング速度より早くすることはできないので、中・低速のサンプリング周期の場合に、それよりも早い周期で指定回数繰り返しサンプリングしローパスフィルタリング処理をすることで効果を発揮します。
上のブロック図のように、AD変換出力バッファとは別の系統で出力されており、フィルタを設定しておけば、「ADCBUFn」を読めば通常のシングル変換値、「ADFLnDAT」を読めばオーバーサンプリングした値となります。
当たり前ですがMCU能力以上のオーバーサンプリングはできない
今回の応用の1msサンプリングなど中速サンプリングで効果を発揮します。
平均値フィルタを使う
dsPICのオーバーサンプリングフィルタには、ビット分解能を上げながらLPFを行うモードと、オーバーサンプリング全部を平均化処理するモードがあります。今回は全部平均処理するモードで使いました。
初期化コードを以下に載せます。余計な部分ありますがご容赦ねがいます。ADCクロックは100MHz(Tcoresrc=10ns,Tadcore=20ns)です。合計時間は「SAMC」=0で
Tad = 8*10ns+(12+2.5)*20ns=370ns
256回サンプリングでは、
Toversamp =( (SAMC+2)×Tadcore+Tad)×256 = 104.96usです。
今回の1ms間隔のサンプリングトリガで、最初の104.9usで256回サンプリングして平均化して「ADFLnDAT」に格納します。加算回数は256回が上限なので上記を図にすると1msの最初の105usで処理が終わるので片寄って見えます。もう少し均等化したい場合はSMACを増やして調整します。ただしサンプリング間隔を超えてしまった時の挙動は確認しておりません。
ADCON4Lbits.SAMC1EN = 1; // AN1 Conversion Delay Enable
ADFL1CONbits.MODE = 0x3; // average mode
ADFL1CONbits.OVRSAM = 0x7; // 256x average
ADFL1CONbits.FLCHSEL = 0x1; // inputCH:AN1 select
ADFL1CONbits.FLEN = 1; // Filter ON
ADFL1CONbits.IE = 1; // Filte1 interrupt enable
// Tflc=((SAMP+2)*20ns+Tadconv)*256=104.96us
ADTRIG0Lbits.TRGSRC0 = 1; // AN0:PWM1 trigger -> Soft Common trigger
ADTRIG0Lbits.TRGSRC1 = 1; // AN1:PWM1 trigger -> Soft Common trigger
これで、オーバーサンプリングフィルタ1をAN1に割付けることができます。あとは「ADFLnDAT」を読みだすだけ。遅延時間「SAMC」を最小にすれば最初の104.9usで256サンプルとなります。その様子を図示します。
その実力は
もともと20KHzのPWMトリガで電流検出していたAD1を1msサンプリングに変更し、通常のセンサ入力にしました。下は通常サンプリングとオーバーサンプリングフィルタの違いをボードからUART経由でTeraTermに読み込んだものです。
ほぼ2Lsb以内
これは、かなり有効です。DSPに入れる前にこのぐらいノイズ成分を抑えられていればGood!です。SharedADCにも使えるので、低分解能入力ではチャンネル切り替えを気にせずにフィルタを適用できるのでアナログ入力の負担を軽減できそうです。