概要
今回は、dsPIC33AKシリーズの第2世代(2nd Generation)に搭載されているADC(Analog-to-Digital Converter)モジュールの使い方についてご紹介します。
前回の記事でも触れたとおり、dsPIC33AKのADCはサンプリングスピード最大40MSPS(メガサンプル毎秒)と、汎用マイコンとしては非常に高速な変換性能を持っています。
本記事では、特に初代(dsPIC33AK MCシリーズ)と第2世代目(dsPIC33AK MPSシリーズ)の違いに焦点を当て、それぞれの特徴や使い分けについて詳しく解説していきます。
記事変更履歴
| 公開/ 変更日 | 特記 |
| 25/5/24 | 初版公開。 |
| 25/5/26 | 対応型式の追加 |
| 25/6/22 | (修正)内部リンク修正、 (追加)開発環境、動作説明 |
| 25/6/28~25/7/3 | (追加)AC特性、DC特性について |
| 25/11/15 | ソースコード内のコメント修正 |

ADの精度に関する注意点について(調査中)
現在、ADコンバータの精度に関して、何らかの注意すべき点が存在する可能性があります。詳細については、2025年7月1日現在、調査を進めている段階です。新たな情報が判明次第、随時更新いたします。
関連リンク
内部リンク
外部リンク
変化点の紹介
変化点1) ADCモジュールが2機→5機に
まず、dsPIC33AKシリーズの第2世代での大きな変更点として挙げられるのは、ADCモジュールの搭載数が2基から5基に増加したことです。
これにより、複数チャンネルの同時変換や並列処理がより柔軟に行えるようになり、アナログ信号を多く扱う用途での使い勝手が大幅に向上しています。
さらに、5基のADCをインターリーブ構成で動作させることで、理論上は最大200MSPS(40MSPS × 5)という非常に高速なサンプリングも可能だと思われます。
これは、dsPICクラスのマイコンとしては非常に魅力的な性能です。
ただし注意点として、変換データを内蔵メモリに保存する場合は最大容量が64kBに限られているため、長時間の記録には不向きで、ごく短時間の波形取得などに用途が限られます。
将来的には、より大容量のRAMを搭載したモデル、もしくは外部メモリに保存できる高速な外部バスを有したモデルの登場にも期待したいところです。
変化点2) ADC入力部
第2世代では各ADCに割り当てられるピンにある程度の制限が生じています。
具体的には、PINSELレジスタは3ビット幅となっているものの、各ADCモジュールが接続可能な外部ピンは5〜6本程度に限られています。そのため、ピン選択の自由度はやや低下しています。
若干の不便さはあるかもしれませんが、実際の使用においては大きな制約とはならないケースがほとんどだと思われます。


変化点3) ADnRSTATレジスタの追加
このレジスタ内の各ビットは、対応するチャネルxの変換結果が ADnRESx レジスタ もしくはに書き込まれたときにハードウェアによってセットされます。
このビットは、ADnRESx レジスタ がソフトウェアによって読み取られたときにハードウェアによってクリアされます。
変化点4) ADnCHmRESレジスタの追加
マニュアル「DS70005591A」には明確な記載は見当たりませんでしたが、該当のレジスタはAD変換結果を直接格納するレジスタであり、さらに前回の変換結果も保持してくれる機能を持っているようです。
この挙動から推測するに、現在の変換値と直前の値の比較や、ジッタ評価などの用途にも活用できる可能性があります。
つまり、「ADnCHmRES」レジスタにはAD変換の生の結果が格納され、
「ADnCHmDATA」レジスタにはその変換結果を演算処理した値が格納されるようです。
特に、サンプリングモードを「Single Conversion」に設定した場合は、ADnCHmRESbits.RES の値が ADnCHmDATA と同じになると予想されます。
キャリブレーションについて
キャリブレーションについて、データシートには以下のように記載されています。
ただし、これ以上の詳細な説明はなく、仕様上は不明な点も残されています。
記載されているのは「オフセットキャリブレーションが必要」と書かれており、キャリブレーションシーケンスで「ゲインキャリブレーション」が行われているかどうかは明記されていません。
一方で、データシート内の「ADC Module Specifications」セクションには、ゲイン補正に関する数値が示されており、
補正なしの場合: -130 ~ +50 LSB
補正ありの場合: -15 ~ +5 LSB
と記載されています。
このことから、実際には何らかのゲイン補正が内部で行われている可能性もありますが、確実とは言い切れず、はっきりとした結論は出せません。
このADCはオフセットキャリブレーションが必要です。ハードウェアによるキャリブレーション手順は以下のいずれかのタイミングで実行されます:
- ADCが有効になったとき(
ADnCON[15]のONビットが ‘1’ に設定されたとき)- ソフトウェアで
CALREQビット(ADnCON[29])をセットしたとき- 定期的に(
ACALENビット(ADnCON[28])がセットされている場合)。
定期キャリブレーションの周期はCALRATE[1:0]ビットで設定でき、1秒〜1時間の範囲で選択可能です。キャリブレーションの状態は
CALRDYビット(ADnCON[30])によって示されます。
このビットは、キャリブレーションが完了するとハードウェアによってセットされ、キャリブレーション中はクリアされます。キャリブレーションは最も低い優先度で実行され、変換中であれば遅延されます。
ADCがキャリブレーションを開始するためには、数クロック分アイドル状態である必要があります。
このアイドル時間はCALCNT[1:0]ビットで設定されます。なお、電源投入直後の初回キャリブレーションには約5,000クロックサイクルかかりますが、
dsPIC33AK512MPS512 Family Data Sheet p.1397 16.4.6.Offset Calibrationを日本語翻訳したもの
ソフトウェアからCALREQビットで再キャリブレーションを要求した場合や、ACALENビットで有効化された定期キャリブレーションは、およそ10クロックサイクルで完了します。

開発環境
開発環境を以下に示します。
今回はCPUボード(EV80L65A)で動作確認を行います。
| 項目 | 値 | リンク |
| ベースボード | dsPIC33A CURIOSITY PLATFORM DEVELOPMENT BOARD | dsPIC33A Curiosity Platform Development Board User’s Guide (microchip.com) |
| CPUボード(EV80L65A) | dsPIC33AK512MPS512 General Purpose Dual In-Line Module (DIM) | dsPIC33AK512MPS512 General Purpose Dual In-Line Module (DIM) | Microchip Technology |
| 統合開発環境 | MPLAB X IDE v6.25 | MPLAB® X IDE | Microchip Technology |
| コンパイラ | MPLAB XC DSC v3.21 | MPLAB® XC DSC Compiler | Microchip Technology |

dsPIC33AKの高速ADCとインターリーブサンプリングの実験構成
dsPIC33AKシリーズでは、従来から大きく進化した点として、最大40Msps(メガサンプル/秒)という非常に高速なADC変換性能が挙げられます。さらに、第2世代となる本シリーズでは5基のADCモジュールが搭載され、並列処理が可能になりました。
しかし、このような高速変換で得られるデータをCPU割り込みで逐次処理するのは現実的ではありません。そのため、効率的なデータ取得にはDMA(Direct Memory Access)を活用することが不可欠となります。
以前の記事では、dsPIC33CKを用いたインターリーブサンプリングの活用例や、dsPIC33AKでのDMAを使ったADC制御について紹介しました。
今回の実験構成
今回はブロック図のような構成で、dsPIC33AKの高速ADC性能を活かしたインターリーブサンプリングを試みます。
その前にADCの基本的な性能も試してみます。
- 外部からのサイン波信号をオペアンプ1(OpAmp1)に入力
- オペアンプの出力を、ADC1〜ADC5の各チャンネルに接続
- 各ADCチャンネルは40Mspsでサンプリング
- サンプリングタイミングを5nsずつずらしてインターリーブ化
- サンプリング結果は、DMAを用いて個別のバッファへ転送
トリガ生成の課題と対応策
このような高速・多チャンネルADC制御で課題となるのが、各ADCに対して精密にタイミングをずらしたトリガを生成する方法です。
当初はPTG(Peripheral Trigger Generator)モジュールでの制御を検討しましたが、残念ながら5個のADCに対して個別のトリガを設定することはできないようでした。
そのため、今回は代替策として、PWMモジュールを3基使用し、各PWMのTRIG信号を用いてADCのサンプリングタイミングを制御する方法を採用しました。
クロック設定
PWMの入力クロックは800MHz、ADCの入力クロックは320MHzに設定しています。
PWMクロックは内部で16倍に逓倍され、ADCクロックは1/4(0.25倍)に分周される仕様です。
そのため、最終的なADCの動作クロックは80MHzとなり、これが1TAD(アナログコアクロック)に相当します。
注意点
今回は機能確認を簡易的に行うため、以下の写真のようにベースボードとブレッドボード間を比較的長めのジャンパワイヤーで配線し、計測を実施しています。
その結果、一部に特性の乱れが見られる箇所も確認されました。ただし、これは配線の長さや接続環境に起因している可能性もあり、最終的に基板化した際には誤差が小さくなることも考えられます。
したがって、今回ご紹介する結果は、あくまでもこのような簡易的な測定環境で得られたものであり、マイコンそのものの性能を評価する材料としては限定的であることをご理解ください。

ブロック図


ソースコード
MPER
AD1CH0CON1bits.MODE
AD1CH0CON1bits.SAMC
AD1CH0CON1bits.ACCNUM
AD3CONbits.ACALEN
AD3CONbits.BUFEN
int u4g_AdcData[5][256];
int main()
{
/*-----------------------------------------------------------------------*/
/*初期化*/
/*-----------------------------------------------------------------------*/
vdg_Clock_Set_Register();
/*-----------------------------------------------------------------------*/
/*ピン設定*/
/*-----------------------------------------------------------------------*/
ANSELA = 0xFFFFFFFF;
ANSELB = 0xFFFFFFFF;
TRISA = 0xFFFFFFFF;
TRISB = 0xFFFFFFFF;
/*-----------------------------------------------------------------------*/
/*PWM設定*/
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* PCLKCONレジスタ */
/*-----------------------------------------------------------------------*/
PCLKCON = 0x00000000u;
PCLKCONbits.MCLKSEL = 1u;
PCLKCONbits.DIVSEL = 0;
/*-----------------------------------------------------------------------*
/* PWMレジスタ */
/*-----------------------------------------------------------------------*/
FSCL = 0x00000000u;
FSMINPER = 0x00000000u;
MPHASE = 0x00000000u;
MDC = 0x00000000u;
MPER = 12800u;
LFSR = 0x00000000u;
/*-----------------------------------------------------------------------*/
/* PG1レジスタ */
/*-----------------------------------------------------------------------*/
PG1CON = 0x00000000u;
PG1CONbits.MPERSEL = 1u;
PG1CONbits.CLKSEL = 1u;
PG1STAT = 0x00000000u;
PG1IOCON1 = 0x00000000u;
PG1IOCON1bits.PENH = 1u;
PG1PHASE = 0x00000000u;
// PG1PER = 100u;
PG1DC = MPER >> 1;
PG1DCA = 0x00000000u;
PG1TRIGA = 0x00000001u;
PG1TRIGB = 0x00000001u;
PG1EVT1 = 0x00000000u;
PG1EVT1bits.ADTR1EN1 = 1;
PG1EVT2 = 0x00000000u;
PG1EVT2bits.ADTR2EN2 = 1;
/*-----------------------------------------------------------------------*/
/* PG2レジスタ */
/*-----------------------------------------------------------------------*/
PG2CON = 0x00000000u;
PG2CONbits.MPERSEL = 1u;
PG2CONbits.CLKSEL = 1u;
PG2STAT = 0x00000000u;
PG2IOCON1 = 0x00000000u;
PG2IOCON1bits.PENH = 1u;
PG2PHASE = 0x00000000u;
PG2DC = MPER >> 1;
PG2DCA = 0x00000000u;
PG2PER = 0x00000000u;
PG2TRIGA = 0x00000001u;
PG2TRIGB = 0x00000001u;
PG2EVT1 = 0x00000000u;
PG2EVT1bits.ADTR1EN1 = 1;
PG2EVT2 = 0x00000000u;
PG2EVT2bits.ADTR2EN2 = 1;
/*-----------------------------------------------------------------------*/
/* PG3レジスタ */
/*-----------------------------------------------------------------------*/
PG3CON = 0x00000000u;
PG3CONbits.MPERSEL = 1u;
PG3CONbits.CLKSEL = 1u;
PG3STAT = 0x00000000u;
PG3IOCON1 = 0x00000000u;
PG3IOCON1bits.PENH = 1u;
PG3PHASE = 0x00000000u;
PG3DC = MPER >> 1;
PG3DCA = 0x00000000u;
PG3PER = 0x00000000u;
PG3TRIGA = 0x00000001u;
PG3TRIGB = 0x00000001u;
PG3EVT1 = 0x00000000u;
PG3EVT1bits.ADTR1EN1 = 1;
/*-----------------------------------------------------------------------*/
/* DMACONレジスタ */
/*-----------------------------------------------------------------------*/
DMACONbits.ON = 1u;
DMACONbits.PRIORITY = 0U;
DMACONbits.SIDL = 0UL;
DMABUF = 0x00000000u;
DMALOW = 0x4000U;
DMAHIGH = 0x7FFFU;
/*-----------------------------------------------------------------------*/
/* DMA0CHレジスタ */
/*-----------------------------------------------------------------------*/
DMA0CH = 0x00000000U;
DMA0CHbits.CHEN = 0U;
DMA0CHbits.HALFEN = 0U;
DMA0CHbits.MATCHEN = 0U;
DMA0CHbits.DONEEN = 0U;
DMA0CHbits.CHREQ = 0U;
DMA0CHbits.SIZE = 2U; //32Bit
DMA0CHbits.FLWCON = 0U;
DMA0CHbits.TRMODE = 1U; //One-Shot
DMA0CHbits.DAMODE = 1U; //インクリメント
DMA0CHbits.SAMODE = 0U; //変更無
DMA0CHbits.RETEN = 0U;
DMA0CHbits.RELOADS = 0U;
DMA0CHbits.RELOADD = 1U;
DMA0CHbits.RELOADC = 1U;
DMA0CHbits.PCHEN = 0U;
DMA0CHbits.PPEN = 0U;
DMA0SEL = 0x2Fu;
DMA0STAT = 0x00000000U;
DMA0SRC = (unsigned int)& AD1CH0DATA;
DMA0DST = (unsigned int)& u4g_AdcData[0][0];
DMA0CNT = 256u;
DMA0CLR = 0x00000000U;
DMA0SET = 0x00000000U;
DMA0INV = 0x00000000U;
DMA0MSK = 0x00000000U;
DMA0PAT = 0x00000000U;
DMA0CHbits.CHEN = 1U;
/*-----------------------------------------------------------------------*/
/* DMA1CHレジスタ */
/*-----------------------------------------------------------------------*/
DMA1CH = 0x00000000U;
DMA1CHbits.CHEN = 0U;
DMA1CHbits.HALFEN = 0U;
DMA1CHbits.MATCHEN = 0U;
DMA1CHbits.DONEEN = 0U;
DMA1CHbits.CHREQ = 0U;
DMA1CHbits.SIZE = 2U; //32Bit
DMA1CHbits.FLWCON = 0U;
DMA1CHbits.TRMODE = 1U; //One-Shot
DMA1CHbits.DAMODE = 1U; //インクリメント
DMA1CHbits.SAMODE = 0U; //変更無
DMA1CHbits.RETEN = 0U;
DMA1CHbits.RELOADS = 0U;
DMA1CHbits.RELOADD = 1U;
DMA1CHbits.RELOADC = 1U;
DMA1CHbits.PCHEN = 0U;
DMA1CHbits.PPEN = 0U;
DMA1SEL = 0x35u;
DMA1STAT = 0x00000000U;
DMA1SRC = (unsigned int)& AD2CH0DATA;
DMA1DST = (unsigned int)& u4g_AdcData[1][0];
DMA1CNT = 256u;
DMA1CLR = 0x00000000U;
DMA1SET = 0x00000000U;
DMA1INV = 0x00000000U;
DMA1MSK = 0x00000000U;
DMA1PAT = 0x00000000U;
DMA1CHbits.CHEN = 1U;
/*-----------------------------------------------------------------------*/
/* DMA2CHレジスタ */
/*-----------------------------------------------------------------------*/
DMA2CH = 0x00000000U;
DMA2CHbits.CHEN = 0U;
DMA2CHbits.HALFEN = 0U;
DMA2CHbits.MATCHEN = 0U;
DMA2CHbits.DONEEN = 0U;
DMA2CHbits.CHREQ = 0U;
DMA2CHbits.SIZE = 2U; //32Bit
DMA2CHbits.FLWCON = 0U;
DMA2CHbits.TRMODE = 1U; //One-Shot
DMA2CHbits.DAMODE = 1U; //インクリメント
DMA2CHbits.SAMODE = 0U; //変更無
DMA2CHbits.RETEN = 0U;
DMA2CHbits.RELOADS = 0U;
DMA2CHbits.RELOADD = 1U;
DMA2CHbits.RELOADC = 1U;
DMA2CHbits.PCHEN = 0U;
DMA2CHbits.PPEN = 0U;
DMA2SEL = 0x3Bu;
DMA2STAT = 0x00000000U;
DMA2SRC = (unsigned int)& AD3CH0DATA;
DMA2DST = (unsigned int)& u4g_AdcData[2][0];
DMA2CNT = 256u;
DMA2CLR = 0x00000000U;
DMA2SET = 0x00000000U;
DMA2INV = 0x00000000U;
DMA2MSK = 0x00000000U;
DMA2PAT = 0x00000000U;
DMA2CHbits.CHEN = 1U;
/*-----------------------------------------------------------------------*/
/* DMA3CHレジスタ */
/*-----------------------------------------------------------------------*/
DMA3CH = 0x00000000U;
DMA3CHbits.CHEN = 0U;
DMA3CHbits.HALFEN = 0U;
DMA3CHbits.MATCHEN = 0U;
DMA3CHbits.DONEEN= 0U;
DMA3CHbits.CHREQ = 0U;
DMA3CHbits.SIZE = 2U; //32Bit
DMA3CHbits.FLWCON = 0U;
DMA3CHbits.TRMODE = 1U; //One-Shot
DMA3CHbits.DAMODE = 1U; //インクリメント
DMA3CHbits.SAMODE = 0U; //変更無
DMA3CHbits.RETEN = 0U;
DMA3CHbits.RELOADS = 0U;
DMA3CHbits.RELOADD = 1U;
DMA3CHbits.RELOADC = 1U;
DMA3CHbits.PCHEN = 0U;
DMA3CHbits.PPEN = 0U;
DMA3SEL = 0x41u;
DMA3STAT = 0x00000000U;
DMA3SRC = (unsigned int)& AD4CH0DATA;
DMA3DST = (unsigned int)& u4g_AdcData[3][0];
DMA3CNT = 256u;
DMA3CLR = 0x00000000U;
DMA3SET = 0x00000000U;
DMA3INV = 0x00000000U;
DMA3MSK = 0x00000000U;
DMA3PAT = 0x00000000U;
DMA3CHbits.CHEN = 1U;
/*-----------------------------------------------------------------------*/
/* DMA4CHレジスタ */
/*-----------------------------------------------------------------------*/
DMA4CH = 0x00000000U;
DMA4CHbits.CHEN = 0U;
DMA4CHbits.HALFEN = 0U;
DMA4CHbits.MATCHEN = 0U;
DMA4CHbits.DONEEN = 0U;
DMA4CHbits.CHREQ = 0U;
DMA4CHbits.SIZE = 2U; //32Bit
DMA4CHbits.FLWCON = 0U;
DMA4CHbits.TRMODE = 1U; //One-Shot
DMA4CHbits.DAMODE = 1U; //インクリメント
DMA4CHbits.SAMODE = 0U; //変更無
DMA4CHbits.RETEN = 0U;
DMA4CHbits.RELOADS = 0U;
DMA4CHbits.RELOADD = 1U;
DMA4CHbits.RELOADC = 1U;
DMA4CHbits.PCHEN = 0U;
DMA4CHbits.PPEN = 0U;
DMA4SEL = 0x48u;
DMA4STAT = 0x00000000U;
DMA4SRC = (unsigned int)& AD5CH0DATA;
DMA4DST = (unsigned int)& u4g_AdcData[4][0];
DMA4CNT = 256u;
DMA4CLR = 0x00000000U;
DMA4SET = 0x00000000U;
DMA4INV = 0x00000000U;
DMA4MSK = 0x00000000U;
DMA4PAT = 0x00000000U;
DMA4CHbits.CHEN = 1U;
/*-----------------------------------------------------------------------*/
/*OPAMP設定*/
/*-----------------------------------------------------------------------*/
AMP1CON1bits.UGE = 1;
AMP1CON1bits.HPEN = 1;
AMP1CON1bits.AMPEN = 1;
/*-----------------------------------------------------------------------*/
/*AD設定*/
/*-----------------------------------------------------------------------*/
AD1CH0CON1bits.TRG1SRC = 4; //PWM1A Trig
AD1CH0CON1bits.TRG2SRC = 2; //即時再トリガ
AD1CH0CON1bits.PINSEL = 0u; //AD1CH0+入力はAD1AN0
AD1CH0CON1bits.NINSEL = 0u;
AD1CH0CON1bits.IRQSEL = 1;
AD1CH0CON1bits.MODE = 3u; //オーバサンプリング変換モード
AD1CH0CON1bits.SAMC = 0u;
AD1CH0CON1bits.ACCNUM = 1;
AD1CON = 0x00000000U;
AD1CONbits.ACALEN = 1U;
AD1CONbits.BUFEN = 1U;
AD1CONbits.ON = 1U;
while(AD1CONbits.ADRDY == 0U)
{
;
}
AD1CONbits.CALREQ = 1U;
while(AD1CONbits.CALRDY == 0U)
{
;
}
AD2CH0CON1bits.TRG1SRC = 4; //PWM1B Trig
AD2CH0CON1bits.TRG2SRC = 2; //即時再トリガ
AD2CH0CON1bits.PINSEL = 0u; //AD2CH0+入力はAD2AN0
AD2CH0CON1bits.NINSEL = 0u;
AD2CH0CON1bits.IRQSEL = 1;
AD2CH0CON1bits.MODE = 3u; //オーバサンプリング変換モード
AD2CH0CON1bits.SAMC = 0u;
AD2CH0CON1bits.ACCNUM = 1;
AD2CON = 0x00000000U;
AD2CONbits.ACALEN = 1U;
AD2CONbits.BUFEN = 1U;
AD2CONbits.ON = 1U;
while(AD2CONbits.ADRDY == 0U)
{
;
}
AD2CONbits.CALREQ = 1U;
while(AD2CONbits.CALRDY == 0U)
{
;
}
AD3CH0CON1bits.TRG1SRC = 4; //PWM2A Trig
AD3CH0CON1bits.TRG2SRC = 2; //即時再トリガ
AD3CH0CON1bits.PINSEL = 0u; //AD3CH0+入力はAD3AN0
AD3CH0CON1bits.NINSEL = 0u;
AD3CH0CON1bits.IRQSEL = 1;
AD3CH0CON1bits.MODE = 3u; //オーバサンプリング変換モード
AD3CH0CON1bits.SAMC = 0u;
AD3CH0CON1bits.ACCNUM = 1;
AD3CON = 0x00000000U;
AD3CONbits.ACALEN = 1U;
AD3CONbits.BUFEN = 1U;
AD3CONbits.ON = 1U;
while(AD3CONbits.ADRDY == 0U)
{
;
}
AD3CONbits.CALREQ = 1U;
while(AD3CONbits.CALRDY == 0U)
{
;
}
AD4CH0CON1bits.TRG1SRC = 4; //PWM2B Trig
AD4CH0CON1bits.TRG2SRC = 2; //PWM2B Trig
AD4CH0CON1bits.PINSEL = 4u; //AD4CH0+入力はAD4AN2
AD4CH0CON1bits.NINSEL = 0u;
AD4CH0CON1bits.IRQSEL = 1;
AD4CH0CON1bits.MODE = 3u; //オーバサンプリング変換モード
AD4CH0CON1bits.SAMC = 0u;
AD4CH0CON1bits.ACCNUM = 1;
AD4CONbits.BUFEN = 1U;
AD4CON = 0x00000000U;
AD4CONbits.ACALEN = 1U;
AD4CONbits.ON = 1U;
while(AD4CONbits.ADRDY == 0U)
{
;
}
AD4CONbits.CALREQ = 1U;
while(AD4CONbits.CALRDY == 0U)
{
;
}
AD5CH0CON1bits.TRG1SRC = 4; //PWM3A Trig
AD5CH0CON1bits.TRG2SRC = 2; //即時再トリガ
AD5CH0CON1bits.PINSEL = 1u; //AD5CH0+入力はAD5AN1
AD5CH0CON1bits.NINSEL = 0u;
AD5CH0CON1bits.IRQSEL = 1;
AD5CH0CON1bits.MODE = 3u; //オーバサンプリング変換モード
AD5CH0CON1bits.SAMC = 0u;
AD5CH0CON1bits.ACCNUM =1;
AD5CON = 0x00000000U;
AD5CONbits.ACALEN = 1U;
AD5CONbits.BUFEN = 1U;
AD5CONbits.ON = 1U;
while(AD5CONbits.ADRDY == 0U)
{
;
}
AD5CONbits.CALREQ = 1U;
while(AD5CONbits.CALRDY == 0U)
{
;
}
PG1CONbits.ON = 1;
PG2CONbits.ON = 1;
PG3CONbits.ON = 1;
while(1)
{
}
}
AC特性
検証1:基本特性
1.条件
まずは以下の条件で、チャンネル間の誤差を計測します。
もし全チャンネルが同一のADC特性を持っているのであれば、全チャンネルをPG1_TRIGAを基準トリガとして同時にサンプリングすることで、同じデータが取得されるはずです。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 50kHz/1V±1V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 0 | サンプリング時間 = 0.5TAD |
| ADnCH0CON1bits.ACCNUM | 0 | 4回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | 無し |
2.結果
サイン波のピークあたりでチャンネル間の誤差が大きいように見受けられます。

検証2:サンプリング時間変更
1.条件
サンプリングホールドコンデンサに十分な電荷を蓄えられるよう、サンプリング時間を0.5TADから10.5TADへ延長しました。これにより、入力信号の精度やチャンネル間の一致性に与える影響を確認します。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 50kHz/1V±1V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 4 | サンプリング時間 = 10.5TAD |
| ADnCH0CON1bits.ACCNUM | 0 | 4回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | 無し |
2.結果
若干の改善は見られましたが、依然としてズレが確認されました。

検証3:fin = 10kHz
1.条件
検証条件を変更し、入力周波数を10kHzに設定して再度計測を行いました。これにより、より低速な信号に対するADCの応答特性を確認します。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 10kHz/1V±1V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 4 | サンプリング時間 = 10.5TAD |
| ADnCH0CON1bits.ACCNUM | 0 | 4回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | 無し |
2.結果
全体としてはほとんど誤差は見られませんが、波形のピーク付近でわずかな歪みが確認されました。


検証4:オーバーサンプリング回数の増加
1.条件
今回の検証では、サンプリング時間(SAMC)を0.5TADに設定し、短時間でのサンプリングを実現しています。その分、オーバーサンプリングによるノイズ低減を図るため、平均回数を4回から16回へと増やしました。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 50kHz/1V±1V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 0 | サンプリング時間 = 0.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | 無し |
2.結果
ADC2とADC4の出力に約200LSBのずれが見られました。
16回のオーバーサンプリングを行っているため、分解能は14bitとなり、基準電圧が3.3Vの場合、このずれは40mV前後の電圧差に相当します。
このレベルの誤差は、用途によっては無視できない可能性があるため、今後の調整やキャリブレーションが検討されます。


検証5:定期キャリブレーションの有効/無効
1.条件
従来はADCのキャリブレーションをシステム起動時のみ行っていましたが、温度変化やドリフトの影響を考慮し、1秒間隔で自動的にキャリブレーションを実行する機能を新たに有効化しました。これにより、測定精度の安定性が向上することが期待されます。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 50kHz/1V±1V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 0 | サンプリング時間 = 2.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 有り | 1秒ごと |
2.結果
チャンネル間で、約250LSBの誤差が生じていることが確認されました。
今回は、定期キャリブレーション(1秒ごと)を有効化していましたが、この誤差に対する有意な改善効果は確認されませんでした。


検証6:fin = 50kHz,フルレンジ
1.条件
これまでは入力電圧を1Vを中心とした±1Vの範囲で測定していましたが、今回は中心電圧を1.6Vに、振幅を±1.6V程度に拡大し、ADCのダイナミックレンジをより広く活用した条件での測定を実施しました。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 50kHz/1.6V±1.6V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 0 | サンプリング時間 = 2.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 有り | 1秒ごと |
2.結果
この条件においても、約300LSB程度の誤差が生じていることが確認されました。



検証7:fin = 10kHz,フルレンジ
1.条件
周波数を10kHzまで下げて再測定を行いました。
この際、出力側のDACにオフセットずれがある可能性が見えたため、オフセット値を微調整しています。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 10kHz/1.5V±1.6V | |
| MPER | 12800 | 1MHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 0 | サンプリング時間 = 2.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 有り | 1秒ごと |
2.結果
その結果、ADC1、ADC2、ADC3の各チャンネルは非常に近い値を示した一方で、ADC4チャンネルのみ約500LSBの誤差が依然として残っており、大きな改善は見られませんでした。


検証8:fin = 1kHz,フルレンジ,100ksps
1.条件
さらに、入力信号の周波数やサンプリング周波数を下げ、サンプリングホールドコンデンサへのチャージ時間であるサンプリング時間を20.5TADまで延長する設定に変更しました。
| 項目(n = 1~5) | 設定値 | 備考 |
| 信号周波数 | 1kHz/1.5V±1.6V | |
| MPER | 128000 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 3 | オーバーサンプリングモード |
| ADnCH0CON1bits.SAMC | 10 | サンプリング時間 = 20.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ有効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 有り | 1秒ごと |
2.結果
検証の結果、各チャンネル間の誤差はおおよそ 100LSB程度まで縮小する傾向が確認されました。
データシート上では、キャリブレーション後のADC誤差は-15~5LSBとされており、今回はさらに16回のオーバーサンプリングを行っているため、誤差が100LSB程度に収まっているのは、ある意味納得のいく結果と言えます。


DC特性
次にADCのDC特性の計測を行います。回路構成は先ほどとほぼ同じですが、今回は外部信号を計測するのではなく、内部基準信号を用いて測定を行っていきます。
検証1. DC特性計測基本条件
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| ADC0トリガ | PG1TRIGA |
2.結果
非常に安定しており、理想的とも言える測定結果が得られています

検証2. ADCチャンネル毎の誤差
ADCモジュールごとの特性差が測定結果に影響しているかを確認するため、ADC0を無効にし、ADC1を単独で有効化して同様の条件下で測定を実施します。
1.条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC1 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| ADC2トリガ | PG1TRIGA |
2. 結果
検証1と同じく非常に綺麗で理想の値が計測できています。

検証3. ADC0とADC1の同時サンプリング
次のステップとして、ADC0とADC1の両方を同時に有効にし、同一のトリガ条件でサンプリングを行った際の挙動を観察しました。
1.条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| ADC0トリガ、 ADC1トリガ | PG1TRIGA |
2. 結果
サンプリング中、定期的に電圧のドロップが発生していることが確認されました。また、DCレベルも理想値より低下しており、全体的に信号の安定性に影響が出ている様子が見られます。

検証4. ADC0~ADC4まですべて有効
次に、ADC0〜ADC4の5チャネルすべてを同時に有効化し、同一のトリガ条件でサンプリングを実施します。これにより、複数ADCを並列動作させた際の動作安定性や誤差傾向を確認します。
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1,ADC2,ADC3,ADC4 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| ADC0トリガ、 ADC1トリガ、 ADC2トリガ、 ADC3トリガ、 ADC4トリガ、 | PG1TRIGA |
2. 結果
この構成では、定期的に電圧のドロップが発生しており、DCレベルも前回の検証(検証3)よりさらに低下していることが確認されました。

検証5. サンプリングタイミングの調整
次の検証では、サンプリングタイミングの調整を実施します。従来はすべてのADCを同時にサンプリングしていましたが、今回はそれぞれの開始タイミングを意図的にずらすことで、同時動作による相互影響が発生しているかどうかを評価します。
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| PG1TRIGB | 6000 | |
| ADC0トリガ | PG1TRIGA | |
| ADC1トリガ | PG1TRIGB |
2. 結果
サンプリングタイミングの調整により、ノイズの影響が抑えられ、理想的かつ安定した測定結果が得られました。

検証6. ADCの増加
次に、ADC0〜ADC4の5チャネルすべてを同時に有効化し、別々のトリガタイミングでサンプリングを実施します。これにより、複数ADCを並列動作させた際の動作安定性や誤差傾向を確認します。
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1,ADC2,ADC3,ADC4 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| PG1TRIGB | 2000 | |
| PG2TRIGA | 4000 | |
| PG2TRIGB | 6000 | |
| PG3TRIGA | 8000 | |
| ADC0トリガ | PG1TRIGA | |
| ADC1トリガ | PG1TRIGB | |
| ADC2トリガ | PG2TRIGA | |
| ADC3トリガ | PG2TRIGB | |
| ADC4トリガ | PG3TRIGA |
2. 結果
ADC1~5を有効にし、ADサンプリングのタイミングを設定値のとおり重ならないようにサンプリングすると、非常に安定した結果が得られましたが、計測値は理想の信号レベルから大きく低下しています。

検証7. サンプリング時間調整
次のステップでは検証6がサンプリング時間を調整することで、レベルの改善が図れるかをどうかを検証します。
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1,ADC2,ADC3,ADC4 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 20 | サンプリング時間 = 40.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| PG1TRIGB | 2000 | |
| PG2TRIGA | 4000 | |
| PG2TRIGB | 6000 | |
| PG3TRIGA | 8000 | |
| ADC0トリガ | PG1TRIGA | |
| ADC1トリガ | PG1TRIGB | |
| ADC2トリガ | PG2TRIGA | |
| ADC3トリガ | PG2TRIGB | |
| ADC4トリガ | PG3TRIGA |
2. 結果
各ADCのサンプリング時間(SAMC)を20まで延長すると、あるチャンネルでは非常に安定した結果が得られた一方で、別のチャンネルでは周期的なノイズが重畳するようになりました。
信号レベル自体は改善されたものの、依然として低下しています。

検証8. 再サンプリング時間調整
次のステップでは更にサンプリング時間を調整することで、レベルの改善が図れるかをどうかを検証します。
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1,ADC2,ADC3,ADC4 | |
| 信号周波数 | DC 15/16*VDD | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 50 | サンプリング時間 = 100.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| PG1TRIGB | 2000 | |
| PG2TRIGA | 4000 | |
| PG2TRIGB | 6000 | |
| PG3TRIGA | 8000 | |
| ADC0トリガ | PG1TRIGA | |
| ADC1トリガ | PG1TRIGB | |
| ADC2トリガ | PG2TRIGA | |
| ADC3トリガ | PG2TRIGB | |
| ADC4トリガ | PG3TRIGA |
2. 結果
各ADCのサンプリング時間(SAMC)を50まで延長したところ、全チャンネルで非常に安定した測定結果が得られるようになりました。信号レベルも改善傾向が見られましたが、依然として本来の期待値より低めの状態が続いています。
また、取得されたデータには特徴的な傾向があり、ADC1・ADC2・ADC3と、ADC4・ADC5の2つのグループに分かれて測定値が揃っていることが確認されました。

検証9. サンプリング対象の変更
検証1~検証8では、内部リファレンスとして「15/16 × VDD」をサンプリング対象として使用していました。しかし、内部のブロック図が公開されていないため、このリファレンスにバッファが挿入されていない可能性も考慮し、今回はサンプリング対象を「UREF(BandGap 1.2V)」に変更して再検証を行うことにしました。
1. 条件
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1,ADC2,ADC3,ADC4 | |
| 信号周波数 | DC 1.2V(UREF BandGap) | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 50、2 | サンプリング時間 = 100.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| PG1TRIGB | 2000 | |
| PG2TRIGA | 4000 | |
| PG2TRIGB | 6000 | |
| PG3TRIGA | 8000 | |
| ADC0トリガ | PG1TRIGA | |
| ADC1トリガ | PG1TRIGB | |
| ADC2トリガ | PG2TRIGA | |
| ADC3トリガ | PG2TRIGB | |
| ADC4トリガ | PG3TRIGA |
2. 結果
サンプリング対象を 15/16*VDD から UREF(BandGap 1.2V) に変更すると全チャンネルが非常に理想的な値を出力するようになりました。
理想出力 = 1.2(BAndGap 1.2V) / 3.3V(AVREF) * 4095 = 1489

同じ条件下でサンプリング時間(SAMC)を50から2へと大幅に短縮した場合でも、チャンネル間の誤差はおおよそ10LSB以内に収まっており、十分に良好な結果が得られています。

検証10.. 同時サンプリングの影響再確認
ここで、5チャンネル同時サンプリングに戻した場合にどのような影響が出るかを検証しました。
| 項目(n = 1~5) | 設定値 | 備考 |
| 有効ADC | ADC0,ADC1,ADC2,ADC3,ADC4 | |
| 信号周波数 | DC 1.2V(UREF BandGap) | |
| MPER | 12800 | 100kHz |
| ADnCH0CON1bits.TRG1SRC | 4 | PG1_TRIGA |
| ADnCH0CON1bits.TRG2SRC | 2 | 即時再トリガ |
| ADnCH0CON1bits.IRQSEL | 1 | ADDATA更新時 |
| ADnCH0CON1bits.MODE | 0 | フィルタなし |
| ADnCH0CON1bits.SAMC | 2 | サンプリング時間 = 4.5TAD |
| ADnCH0CON1bits.ACCNUM | 1 | 16回 |
| ADnCONbits.BUFEN | 1 | バッファ無効 |
| 初期キャリブレーション | 有り | 有り |
| 定期キャリブレーション | 無し | |
| PG1TRIGA | 1 | |
| ADC0トリガ、 ADC1トリガ、 ADC2トリガ、 ADC3トリガ、 ADC4トリガ、 | PG1TRIGA |
2. 結果
再び周期的なノイズが重畳する現象が確認されました。しかしながら、検証4.にて15/16×VDDを計測していた際に見られた電圧ドロップよりは、影響が小さいことがわかりました。

まとめ
・内蔵リファレンスとして「15/16 × VDD」を選択してキャリブレーションを行う場合は、5チャンネルを同時にキャリブレーションするよりも、各ADCごとに個別に有効化して実施した方が精度が安定
・内蔵リファレンスを活用するなら、より安定したBandGapリファレンスをUREF経由でキャリブレーションに用いることを推奨。ただし、BandGapの電圧は約1.2Vと低いため、システム電圧3.3Vに対するゲイン誤差が大きくなる可能性がある点には注意が必要
・ADC1からADC5のサンプリングタイミングについては、同期させずにずらす設計のほうがノイズ干渉の軽減や測定の安定化につながる。おそらく同時に動かすと消費電流が増加し、瞬時的に電源電圧が不足するのではと考えています。
・なお、上記の現象は開発ボード上で確認されたものです。オリジナルの基板を設計する際に、電源ラインのインピーダンス設計やノイズ対策をしっかりと行えば、こうした影響は改善される可能性があります。
対応型式
以下の型式には、すべて独立した高速ADCが5チャンネル搭載されています。
・dsPIC33AK256MPS205・dsPIC33AK256MPS206・dsPIC33AK256MPS208・dsPIC33AK256MPS210・dsPIC33AK256MPS212
・dsPIC33AK256MPS505・dsPIC33AK256MPS506・dsPIC33AK256MPS508・dsPIC33AK256MPS510・dsPIC33AK256MPS512
・dsPIC33AK512MPS205・dsPIC33AK512MPS206・dsPIC33AK512MPS208・dsPIC33AK512MPS210・dsPIC33AK512MPS212
・dsPIC33AK512MPS505・dsPIC33AK512MPS506・dsPIC33AK512MPS508・dsPIC33AK512MPS510・dsPIC33AK512MPS512
・dsPIC33AK256MC205・dsPIC33AK256MC206・dsPIC33AK256MC208・dsPIC33AK256MC210・dsPIC33AK256MC505
・dsPIC33AK256MC506・dsPIC33AK256MC508・dsPIC33AK256MC510・dsPIC33AK512MC205・dsPIC33AK512MC206
・dsPIC33AK512MC208・dsPIC33AK512MC210・dsPIC33AK512MC505・dsPIC33AK512MC506・dsPIC33AK512MC508
・dsPIC33AK512MC510
記事についての注意点
本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。

コメント