dsPIC33AKシリーズ㉙ ADCモジュールの使い方(2nd Generation)

ADCの使い方
  1. 概要
    1. 記事変更履歴
  2. 関連リンク
    1. 内部リンク
    2. 外部リンク
  3. 変化点の紹介
    1. 変化点1) ADCモジュールが2機→5機に
    2. 変化点2) ADC入力部
    3. 変化点3) ADnRSTATレジスタの追加
    4. 変化点4) ADnCHmRESレジスタの追加
  4. キャリブレーションについて
  5. 開発環境
  6. dsPIC33AKの高速ADCとインターリーブサンプリングの実験構成
    1. 今回の実験構成
      1. トリガ生成の課題と対応策
      2. クロック設定
      3. 注意点
    2. ブロック図
    3. ソースコード
  7. AC特性
    1. 検証1:基本特性
      1. 1.条件
      2. 2.結果
    2. 検証2:サンプリング時間変更
      1. 1.条件
      2. 2.結果
    3. 検証3:fin = 10kHz
      1. 1.条件
      2. 2.結果
    4. 検証4:オーバーサンプリング回数の増加
      1. 1.条件
      2. 2.結果
    5. 検証5:定期キャリブレーションの有効/無効
      1. 1.条件
      2. 2.結果
    6. 検証6:fin = 50kHz,フルレンジ
      1. 1.条件
      2. 2.結果
    7. 検証7:fin = 10kHz,フルレンジ
      1. 1.条件
      2. 2.結果
    8. 検証8:fin = 1kHz,フルレンジ,100ksps
      1. 1.条件
      2. 2.結果
  8. DC特性
    1. 検証1. DC特性計測基本条件
      1. 1. 条件
      2. 2.結果
    2. 検証2. ADCチャンネル毎の誤差
      1. 1.条件
      2. 2. 結果
    3. 検証3. ADC0とADC1の同時サンプリング
      1. 1.条件
      2. 2. 結果
    4. 検証4. ADC0~ADC4まですべて有効
      1. 1. 条件
      2. 2. 結果
    5. 検証5. サンプリングタイミングの調整
      1. 1. 条件
      2. 2. 結果
    6. 検証6. ADCの増加
      1. 1. 条件
      2. 2. 結果
    7. 検証7. サンプリング時間調整
      1. 1. 条件
      2. 2. 結果
    8. 検証8. 再サンプリング時間調整
      1. 1. 条件
      2. 2. 結果
    9. 検証9. サンプリング対象の変更
      1. 1. 条件
      2. 2. 結果
    10. 検証10.. 同時サンプリングの影響再確認
      1. 2. 結果
  9. まとめ
  10. 対応型式
  11. 記事についての注意点

概要

今回は、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回dsPIC33AKシリーズについてdsPIC33Aシリーズに関して – ぴくおの電子工作的な何かWP (electricpico.com)
第2回開発ボード、コンフィグレーション設定、クロック設定についてdsPIC33AKシリーズ②開発ボード,コンフィグレーション設定,クロック設定について – ぴくおの電子工作的な何かWP (electricpico.com)
第3回CPU性能についてdsPIC33AKシリーズ③CPU性能について – ぴくおの電子工作的な何かWP (electricpico.com)
第4回FPU性能についてdsPIC33AKシリーズ④FPU性能について – ぴくおの電子工作的な何かWP (electricpico.com)
第5回DSPについてdsPIC33AKシリーズ⑤DSPについて – ぴくおの電子工作的な何かWP (electricpico.com)
第6回タイマー1割り込みの使い方dsPIC33AKシリーズ⑥Timer1割り込みの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第7回PMUの使い方dsPIC33AKシリーズ⑦PMUの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第8回高速ADCの使い方dsPIC33AKシリーズ⑧高速ADCの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第9回高速OPAMPの使い方dsPIC33AKシリーズ⑨高速OPAMPの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第10回DMAモジュールの使い方dsPIC33AKシリーズ⑩DMAモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第11回WDTモジュールの使い方dsPIC33AKシリーズ⑪WDTモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第12回DMTモジュールの使い方dsPIC33AKシリーズ⑫DMTモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第13回I/Oインテグリティモニタモジュールの使い方dsPIC33AKシリーズ⑬I/Oインテグリティモニターモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第14回QEIモジュールの使い方dsPIC33AKシリーズ⑭QEIモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第15回UARTモジュールの使い方dsPIC33AKシリーズ⑮UARTモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第16回DSPの使い方1 (デジタルフィルタ)dsPIC33AKシリーズ⑯ DSPの使い方1(デジタルフィルタ) – ぴくおの電子工作的な何かWP (electricpico.com)
第17回DSPの使い方2 (FFT)dsPIC33AKシリーズ⑰ DSPの使い方2(FFT) – ぴくおの電子工作的な何かWP (electricpico.com)
第18回DSPの使い方3 (自己相関アルゴリズム)dsPIC33AKシリーズ⑱ DSPの使い方3(自己相関アルゴリズム) – ぴくおの電子工作的な何かWP (electricpico.com)
第19回DSPの使い方4(LMSアルゴリズム)dsPIC33AKシリーズ⑲ DSPの使い方4(LMSアルゴリズム) – ぴくおの電子工作的な何かWP (electricpico.com)
第20回SPIモジュールの使い方dsPIC33AKシリーズ⑳ SPIモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第21回高速コンパレータモジュールの使い方1dsPIC33AKシリーズ㉑ 高速コンパレータモジュールの使い方1 – ぴくおの電子工作的な何かWP (electricpico.com)
第22回CBGモジュールの使い方dsPIC33AKシリーズ㉒ CBGモジュールの使い方 – ぴくおの電子工作的な何かWP (electricpico.com)
第23回高速PWMの使い方dsPIC33AKシリーズ㉓ 高速PWMについて – ぴくおの電子工作的な何かWP
第24回SENTモジュールの使い方dsPIC33AKシリーズ㉔ SENTモジュールの使い方 – ぴくおの電子工作的な何かWP
第25回①AC負荷アナライザの製作①
~設計、ハードウエア編~
dsPIC33AKシリーズ㉕ AC負荷アナライザの製作①設計、ハードウェア編 – ぴくおの電子工作的な何かWP
第25回②AC負荷アナライザの製作②
~マイコンソフトウェア編~
dsPIC33AKシリーズ㉕ AC負荷アナライザの製作②マイコンソフトウェア編 – ぴくおの電子工作的な何かWP
第25回③AC負荷アナライザの製作③
~Windowsアプリ編~
dsPIC33AKシリーズ㉕ AC負荷アナライザの製作③Windowsアプリ編 – ぴくおの電子工作的な何かWP
第26回dsPIC33AKシリーズ㉖ MBISTの使い方dsPIC33AKシリーズ㉖ MBISTの使い方 – ぴくおの電子工作的な何かWP
第27回DSPの使い方5(行列)dsPIC33AKシリーズ㉗ DSPの使い方5(行列) – ぴくおの電子工作的な何かWP
第28回CLCの使い方(2nd Generation)dsPIC33AKシリーズ㉘ CLCモジュールの使い方(2nd Generation) – ぴくおの電子工作的な何かWP
第29回(本記事)ADCモジュールの使い方
(2nd Generation)
dsPIC33AKシリーズ㉙ ADCモジュールの使い方(2nd Generation) – ぴくおの電子工作的な何かWP
第30回dsPIC33AKシリーズ㉚ 超高分解能PWMモジュールの使い方(2nd Generation)dsPIC33AKシリーズ㉚ 超高分解能PWMモジュールの使い方(2nd Generation) – ぴくおの電子工作的な何かWP
第31回dsPIC33AKシリーズ㉛ 暗号化アクセラレータの使い方(2nd Generation)dsPIC33AKシリーズ㉛ 暗号化アクセラレータの使い方(2nd Generation) – ぴくおの電子工作的な何かWP
第32回dsPIC33AKシリーズ㉜ CAN-FDモジュールの使い方(2nd Generation)dsPIC33AKシリーズ㉜ CAN-FDモジュールの使い方(2nd Generation) – ぴくおの電子工作的な何かWP
(fig.1-1)各関連記事リンク

外部リンク

サイト      リンク先
プロダクトページdsPIC33AK512MPS512 | Microchip Technology
データシートww1.microchip.com/downloads/aemDocuments/documents/MCU16/ProductDocuments/DataSheets/dsPIC33AK512MPS512-Family-Data-Sheet-DS70005591.pdf
エラッタdsPIC33AK512MPS512 Family Silicon Errata and Data Sheet Clarification
プログラミングdsPIC33AK512MC510 and dsPIC33AK512MPS512 Family Programming Specification
リファレンスマニュアルdsPIC33A Programmer’s Reference Manual
(fig.1-2)外部リンク

変化点の紹介

変化点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本程度に限られています。そのため、ピン選択の自由度はやや低下しています。

若干の不便さはあるかもしれませんが、実際の使用においては大きな制約とはならないケースがほとんどだと思われます。

(fig.2-1)dsPIC33AKシリーズの第2世代目のADC
(fig.2-2)dsPIC33AKシリーズの第1世代目のADC

変化点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クロックサイクルかかりますが、
ソフトウェアから CALREQ ビットで再キャリブレーションを要求した場合や、ACALEN ビットで有効化された定期キャリブレーションは、およそ10クロックサイクルで完了します。

dsPIC33AK512MPS512 Family Data Sheet p.1397 16.4.6.Offset Calibrationを日本語翻訳したもの
dsPIC33AK512MPS512 Family Data Sheet  p.2099 Table 40-38 ADC Modue Specificationsより抜粋

開発環境

開発環境を以下に示します。
今回は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.25MPLAB® X IDE | Microchip Technology
コンパイラMPLAB XC DSC v3.21MPLAB® XC DSC Compiler | Microchip Technology
(fig.3-1)本記事の動作確認環境
(fig.3-2)ベースボード+CPUボード

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(アナログコアクロック)に相当します。

注意点

注意点

今回は機能確認を簡易的に行うため、以下の写真のようにベースボードとブレッドボード間を比較的長めのジャンパワイヤーで配線し、計測を実施しています。

その結果、一部に特性の乱れが見られる箇所も確認されました。ただし、これは配線の長さや接続環境に起因している可能性もあり、最終的に基板化した際には誤差が小さくなることも考えられます

したがって、今回ご紹介する結果は、あくまでもこのような簡易的な測定環境で得られたものであり、マイコンそのものの性能を評価する材料としては限定的であることをご理解ください。

ブロック図

(fig.4-1)200MHzインターサンプリング構成
(fig.4-2)PWMモジュールによるサンプリングトリガ

ソースコード

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
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC0サンプリング時間 = 0.5TAD
ADnCH0CON1bits.ACCNUM04回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション無し無し

2.結果

サイン波のピークあたりでチャンネル間の誤差が大きいように見受けられます。

検証2:サンプリング時間変更

1.条件

サンプリングホールドコンデンサに十分な電荷を蓄えられるよう、サンプリング時間を0.5TADから10.5TADへ延長しました。これにより、入力信号の精度やチャンネル間の一致性に与える影響を確認します。

項目(n = 1~5)設定値備考
信号周波数50kHz/1V±1V
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC4サンプリング時間 = 10.5TAD
ADnCH0CON1bits.ACCNUM04回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション無し無し

2.結果

若干の改善は見られましたが、依然としてズレが確認されました。

検証3:fin = 10kHz

1.条件

検証条件を変更し、入力周波数を10kHzに設定して再度計測を行いました。これにより、より低速な信号に対するADCの応答特性を確認します。

項目(n = 1~5)設定値備考
信号周波数10kHz/1V±1V
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC4サンプリング時間 = 10.5TAD
ADnCH0CON1bits.ACCNUM04回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション無し無し

2.結果

全体としてはほとんど誤差は見られませんが、波形のピーク付近でわずかな歪みが確認されました。

検証4:オーバーサンプリング回数の増加

1.条件

今回の検証では、サンプリング時間(SAMC)を0.5TADに設定し、短時間でのサンプリングを実現しています。その分、オーバーサンプリングによるノイズ低減を図るため、平均回数を4回から16回へと増やしました。

項目(n = 1~5)設定値備考
信号周波数50kHz/1V±1V
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC0サンプリング時間 = 0.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション無し無し

2.結果

ADC2とADC4の出力に約200LSBのずれが見られました。
16回のオーバーサンプリングを行っているため、分解能は14bitとなり、基準電圧が3.3Vの場合、このずれは40mV前後の電圧差に相当します。
このレベルの誤差は、用途によっては無視できない可能性があるため、今後の調整やキャリブレーションが検討されます。

検証5:定期キャリブレーションの有効/無効

1.条件

従来はADCのキャリブレーションをシステム起動時のみ行っていましたが、温度変化やドリフトの影響を考慮し、1秒間隔で自動的にキャリブレーションを実行する機能を新たに有効化しました。これにより、測定精度の安定性が向上することが期待されます。

項目(n = 1~5)設定値備考
信号周波数50kHz/1V±1V
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC0サンプリング時間 = 2.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション有り1秒ごと

2.結果

チャンネル間で、約250LSBの誤差が生じていることが確認されました。
今回は、定期キャリブレーション(1秒ごと)を有効化していましたが、この誤差に対する有意な改善効果は確認されませんでした

検証6:fin = 50kHz,フルレンジ

1.条件

これまでは入力電圧を1Vを中心とした±1Vの範囲で測定していましたが、今回は中心電圧を1.6Vに、振幅を±1.6V程度に拡大し、ADCのダイナミックレンジをより広く活用した条件での測定を実施しました。

項目(n = 1~5)設定値備考
信号周波数50kHz/1.6V±1.6V
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC0サンプリング時間 = 2.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション有り1秒ごと

2.結果

この条件においても、約300LSB程度の誤差が生じていることが確認されました。

全サンプル
(fig.*-7-2)ピーク部拡大
(fig.*-7-2)ピーク部拡大(電圧換算値)

検証7:fin = 10kHz,フルレンジ

1.条件

周波数を10kHzまで下げて再測定を行いました。
この際、出力側のDACにオフセットずれがある可能性が見えたため、オフセット値を微調整しています。

項目(n = 1~5)設定値備考
信号周波数10kHz/1.5V±1.6V
MPER128001MHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC0サンプリング時間 = 2.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション有り1秒ごと

2.結果

その結果、ADC1、ADC2、ADC3の各チャンネルは非常に近い値を示した一方で、ADC4チャンネルのみ約500LSBの誤差が依然として残っており、大きな改善は見られませんでした。

検証8:fin = 1kHz,フルレンジ,100ksps

1.条件

さらに、入力信号の周波数やサンプリング周波数を下げ、サンプリングホールドコンデンサへのチャージ時間であるサンプリング時間を20.5TADまで延長する設定に変更しました。

項目(n = 1~5)設定値備考
信号周波数1kHz/1.5V±1.6V
MPER128000100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE3オーバーサンプリングモード
ADnCH0CON1bits.SAMC10サンプリング時間 = 20.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ有効
初期キャリブレーション有り有り
定期キャリブレーション有り1秒ごと

2.結果

検証の結果、各チャンネル間の誤差はおおよそ 100LSB程度まで縮小する傾向が確認されました。
データシート上では、キャリブレーション後のADC誤差は-15~5LSBとされており、今回はさらに16回のオーバーサンプリングを行っているため、誤差が100LSB程度に収まっているのは、ある意味納得のいく結果と言えます。

DC特性

次にADCのDC特性の計測を行います。回路構成は先ほどとほぼ同じですが、今回は外部信号を計測するのではなく、内部基準信号を用いて測定を行っていきます。

検証1. DC特性計測基本条件

1. 条件

項目(n = 1~5)設定値備考
有効ADCADC0
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
ADC0トリガPG1TRIGA

2.結果

非常に安定しており、理想的とも言える測定結果が得られています

検証2. ADCチャンネル毎の誤差

ADCモジュールごとの特性差が測定結果に影響しているかを確認するため、ADC0を無効にし、ADC1を単独で有効化して同様の条件下で測定を実施します。

1.条件

項目(n = 1~5)設定値備考
有効ADCADC1
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
ADC2トリガPG1TRIGA

2. 結果

検証1と同じく非常に綺麗で理想の値が計測できています。

検証3. ADC0とADC1の同時サンプリング

次のステップとして、ADC0とADC1の両方を同時に有効にし、同一のトリガ条件でサンプリングを行った際の挙動を観察しました。

1.条件

項目(n = 1~5)設定値備考
有効ADCADC0,ADC1
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
ADC0トリガ、
ADC1トリガ
PG1TRIGA

2. 結果

サンプリング中、定期的に電圧のドロップが発生していることが確認されました。また、DCレベルも理想値より低下しており、全体的に信号の安定性に影響が出ている様子が見られます。

検証4. ADC0~ADC4まですべて有効

次に、ADC0〜ADC4の5チャネルすべてを同時に有効化し、同一のトリガ条件でサンプリングを実施します。これにより、複数ADCを並列動作させた際の動作安定性や誤差傾向を確認します。

1. 条件

項目(n = 1~5)設定値備考
有効ADCADC0,ADC1,ADC2,ADC3,ADC4
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
ADC0トリガ、
ADC1トリガ、
ADC2トリガ、
ADC3トリガ、
ADC4トリガ、
PG1TRIGA

2. 結果

この構成では、定期的に電圧のドロップが発生しており、DCレベルも前回の検証(検証3)よりさらに低下していることが確認されました。

検証5. サンプリングタイミングの調整

次の検証では、サンプリングタイミングの調整を実施します。従来はすべてのADCを同時にサンプリングしていましたが、今回はそれぞれの開始タイミングを意図的にずらすことで、同時動作による相互影響が発生しているかどうかを評価します。

1. 条件

項目(n = 1~5)設定値備考
有効ADCADC0,ADC1
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
PG1TRIGB6000
ADC0トリガPG1TRIGA
ADC1トリガPG1TRIGB

2. 結果

サンプリングタイミングの調整により、ノイズの影響が抑えられ、理想的かつ安定した測定結果が得られました。

検証6. ADCの増加

次に、ADC0〜ADC4の5チャネルすべてを同時に有効化し、別々のトリガタイミングでサンプリングを実施します。これにより、複数ADCを並列動作させた際の動作安定性や誤差傾向を確認します。

1. 条件

項目(n = 1~5)設定値備考
有効ADCADC0,ADC1,ADC2,ADC3,ADC4
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
PG1TRIGB2000
PG2TRIGA4000
PG2TRIGB6000
PG3TRIGA8000
ADC0トリガPG1TRIGA
ADC1トリガPG1TRIGB
ADC2トリガPG2TRIGA
ADC3トリガPG2TRIGB
ADC4トリガPG3TRIGA

2. 結果

ADC1~5を有効にし、ADサンプリングのタイミングを設定値のとおり重ならないようにサンプリングすると、非常に安定した結果が得られましたが、計測値は理想の信号レベルから大きく低下しています。

検証7. サンプリング時間調整

次のステップでは検証6がサンプリング時間を調整することで、レベルの改善が図れるかをどうかを検証します。

1. 条件

項目(n = 1~5)設定値備考
有効ADCADC0,ADC1,ADC2,ADC3,ADC4
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC20サンプリング時間 = 40.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
PG1TRIGB2000
PG2TRIGA4000
PG2TRIGB6000
PG3TRIGA8000
ADC0トリガPG1TRIGA
ADC1トリガPG1TRIGB
ADC2トリガPG2TRIGA
ADC3トリガPG2TRIGB
ADC4トリガPG3TRIGA

2. 結果

各ADCのサンプリング時間(SAMC)を20まで延長すると、あるチャンネルでは非常に安定した結果が得られた一方で、別のチャンネルでは周期的なノイズが重畳するようになりました。
信号レベル自体は改善されたものの、依然として低下しています。

検証8. 再サンプリング時間調整

次のステップでは更にサンプリング時間を調整することで、レベルの改善が図れるかをどうかを検証します。

1. 条件

項目(n = 1~5)設定値備考
有効ADCADC0,ADC1,ADC2,ADC3,ADC4
信号周波数DC 15/16*VDD
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC50サンプリング時間 = 100.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
PG1TRIGB2000
PG2TRIGA4000
PG2TRIGB6000
PG3TRIGA8000
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)設定値備考
有効ADCADC0,ADC1,ADC2,ADC3,ADC4
信号周波数DC 1.2V(UREF BandGap)
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC50、2サンプリング時間 = 100.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
PG1TRIGB2000
PG2TRIGA4000
PG2TRIGB6000
PG3TRIGA8000
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)設定値備考
有効ADCADC0,ADC1,ADC2,ADC3,ADC4
信号周波数DC 1.2V(UREF BandGap)
MPER12800100kHz
ADnCH0CON1bits.TRG1SRC4PG1_TRIGA
ADnCH0CON1bits.TRG2SRC2即時再トリガ
ADnCH0CON1bits.IRQSEL1ADDATA更新時
ADnCH0CON1bits.MODE0フィルタなし
ADnCH0CON1bits.SAMC2サンプリング時間 = 4.5TAD
ADnCH0CON1bits.ACCNUM116回
ADnCONbits.BUFEN1バッファ無効
初期キャリブレーション有り有り
定期キャリブレーション無し
PG1TRIGA1
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

記事についての注意点

本記事は慎重に内容を検討し正確さに努めておりますが、内容に誤りがあったとしても、この記事を参考にして生じた損害等については一切の責任を負いません。

コメント

タイトルとURLをコピーしました