1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

100円マイコン、A/Dコンバーターの使い方

Last updated at Posted at 2021-11-13

IMG_0142s.jpg

内臓A/Dコンバーターの使い方

R8C_ADC.png

R8C/Mxx は、サンプルホールド付き、10ビットA/Dコンバーターを内蔵しています。

変換時間も2.2マイクロ秒と高速で、最大6チャネルのアナログ入力をサポートしています。

今回は、このデバイスの基本的な使い方を説明します。
※低価格マイコンで、サンプルホールド付10ビットA/Dがあるのは珍しいと思います。

サポートクラス common/adc_io.hpp

R8C/C++ フレームワークでは、A/D 変換を簡単に扱う為、サポートクラスを提供しています。

このクラスを使う事で、簡単にアナログ電圧を変換する事が出来ます。

このクラスは、割り込みに対応していますが、今回は割り込みを使わない方法を示します。

割り込みを使えば、変換時間を有効に使う事が出来ますが、1つのアナログ入力に対して2.2マイクロ秒だと、20MHz で動作する R8C では、44サイクル分です。
このくらいのコストなら、割り込みで変換通知を受け取らなくても、そんなに大きなハンデとならないと思います。
変換を開始してから、何か簡単な処理を行い、変換結果を得るようにすれば、変換に掛かるコストを相殺出来ます。
多数のアナログ入力を連続して変換するような場合には、割り込みを使い連続して変換し、結果を格納すればパフォーマンスが上がります。

ハードウェアー(準備)

  • 実験では、2個のボリュームをアナログ入力端子に接続します。

定義

	// 電源電圧を10倍した整数を設定
//	constexpr int16_t VCC = 50;    ///< 5.0V (1.25)
	constexpr int16_t VCC = 33;    ///< 3.3V (0.825)

	typedef device::adc_io<utils::null_task> ADC;
	ADC		adc_;

※電圧表示用に、マイコンの駆動電圧を設定します。(この例では3.3V)
※今回、割り込みを使わないので、割り込みから呼ばれる変換型には「utils::null_task」を選択しています。

開始

この例では、P1_0(CH0)、P1_1(CH1) をアナログ入力として使います。

	// ADC の設定
	{
		utils::PORT_MAP(utils::port_map::P10::AN0);
		utils::PORT_MAP(utils::port_map::P11::AN1);
		adc_.start(ADC::CH_TYPE::CH0_CH1, ADC::CH_GROUP::AN0_AN1, true);
	}

結果取得と表示

			adc_.scan();
			adc_.sync();
			// 「%3.2:8y」は小数点以下 8 ビットの固定小数点を 3 桁、小数点以下 2 桁表示
			//   5V の場合 1.25  倍して、小数点以下 8 ビットで、1023 で   5V 表示となる。
			// 3.3V の場合 0.825 倍して、小数点以下 8 ビットで、1023 で 3.3V 表示となる。
			{
				auto v = adc_.get_value(0);
				utils::format("(%5d) CH0: %3.2:8y[V], %d\n")
					% nnn
					% static_cast<uint16_t>(((v + 1) * VCC) / (1024 * 10 / 256))
					% v;
			}

			{
				auto v = adc_.get_value(1);
				utils::format("        CH1: %3.2:8y[V], %d\n")
					% static_cast<uint16_t>(((v + 1) * VCC) / (1024 * 10 / 256))
					% v;
			}
			++nnn;

「scan()」で A/D 変換をスタートして、「sync()」で変換終了を待ちます。

		void sync() const {
			while(!get_state()) sleep_();
		}

「sync()」関数の実装は上記のようになっているので、何か別の処理をしながら、変換が終了するまで待つ事も出来ます。

「utils::format」は、固定小数点表示をサポートしており、電圧の表示などに便利です。
※浮動小数点を使う事も出来ますが、オブジェクトが大きくなります。

上記の例では、設定した電源電圧のパラメーターを使い、変換された電圧をX.XXで表示します。
「%3.2:8y」は、format 独自の固定小数点フォームで、小数点以下8ビットとして整数を扱います。

  • 5Vの場合、A/D 変換後のデータに1を加えて、1.25倍しています。
  • 3.3Vの場合、A/D 返還後のデータを0.825倍しています。

ターミナル出力:

        CH1: 1.61[V], 500
(  310) CH0: 2.28[V], 708
        CH1: 1.61[V], 500
(  311) CH0: 2.28[V], 709
        CH1: 1.61[V], 500
(  312) CH0: 2.28[V], 709
        CH1: 1.61[V], 500
(  313) CH0: 2.28[V], 707
        CH1: 1.62[V], 501
(  314) CH0: 2.28[V], 708
        CH1: 1.61[V], 500
(  315) CH0: 2.28[V], 708
        CH1: 1.61[V], 500
(  316) CH0: 2.28[V], 708
        CH1: 1.61[V], 500
(  317) CH0: 2.28[V], 708
        CH1: 1.61[V], 500
(  318) CH0: 2.28[V], 709
        CH1: 1.61[V], 500
(  319) CH0: 2.29[V], 710
        CH1: 1.61[V], 500
(  320) CH0: 2.28[V], 708
        CH1: 1.61[V], 500

サーミスターテンプレートクラスを使った温度測定

IMG_0141s.jpg

サーミスターは、安価で、簡易的に温度を測定するには最適なデバイスです。
但し、直線性が悪く、補正が必要です。
R8C/C++ フレームワークでは、サーミスター用テンプレートクラスを用意してあり、非直線性を補正した温度を取得する事が出来ます。
※対数計算が含まれていて、浮動小数点を扱うので、実行バイナリーはそれなりに大きくなります。

定義

サーミスターは、品種により直線性が異なり、対数計算のパラメーターを選ぶ必要があります。

このテンプレートクラスでは、現在3つの品種を扱えるようにしてあります。
※他の品種を使いたい場合、パラーメーターを追加して下さい、ソースコードを観れば、比較的簡単に品種を増やす事が出来ると思います。

標準で用意されている品種:

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  サーミスタ型
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	enum class thermistor {
		NT103_34G,	///< THB:3435, TR25:10K
		NT103_41G,	///< THB:4126, TR25:10K
		HX103_3380,	///< THB:3380, TR25:10K (25C to 50C)
	};

3つのサーミスター型のうち適切な型を選択して、typedef します。
又、分圧抵抗(通常10キロオーム)を直列に接続し、サーミスターを電源のどちらかに接続します。

  • VCC側、又は、GND側
  • A/D 変換の分解能は10ビットで、0~1023の値が返るので、1023 (1024-1) を指定しています。
  • 「TH_OUT」は AN0/P1_0(20) に接続します。

Thermister_circuit.png

	// サーミスタ定義:
	// A/D: 10 bits (1023), HX103_3380, 分圧抵抗: 10K (10000) オーム、サーミスタ: VCC側
	typedef chip::NTCTH<1023, chip::thermistor::HX103_3380, 10000, true> THMISTER;
	THMISTER thmister_;

開始

サーミスターを利用する A/D 変換ポートに接続し、A/D 変換を開始します。
※この例では、P1_0 に接続しています。

	// ADC の設定
	{
		utils::PORT_MAP(utils::port_map::P10::AN0);
		adc_.start(ADC::CH_TYPE::CH0, ADC::CH_GROUP::AN0_AN1, true);
	}

結果表示

A/D 変換された値をサーミスターテンプレートに入れて、補正された温度を取得します。
※温度は、float 型で返ります。

			adc_.scan();
			adc_.sync();
			{
				auto v = adc_.get_value(0);
				utils::format("(%5d) CH0: %3.2:8y[V], %d\n")
					% nnn
					% static_cast<uint16_t>(((v + 1) * VCC) / (1024 * 10 / 256))
					% v;

				utils::format("温度: %5.2f [度]\n") % thmister_(v);
			}

テンプレートクラスを使うと簡単に扱えます。

ターミナル出力:

Start R8C THERMISTOR sample
(    0) CH0: 2.53[V], 517
温度: 25.57 [度]
(    1) CH0: 2.53[V], 517
温度: 25.57 [度]
(    2) CH0: 2.53[V], 517
温度: 25.57 [度]
(    3) CH0: 2.52[V], 516
温度: 25.46 [度]
(    4) CH0: 2.52[V], 515
温度: 25.36 [度]
(    5) CH0: 2.51[V], 514
温度: 25.26 [度]
(    6) CH0: 2.53[V], 517
温度: 25.57 [度]
(    7) CH0: 2.56[V], 523
温度: 26.19 [度]
(    8) CH0: 2.56[V], 523
温度: 26.19 [度]
(    9) CH0: 2.55[V], 522
温度: 26.08 [度]
(   10) CH0: 2.55[V], 522
温度: 26.08 [度]
(   11) CH0: 2.57[V], 525
温度: 26.40 [度]
(   12) CH0: 2.58[V], 528
温度: 26.71 [度]
(   13) CH0: 2.57[V], 525
温度: 26.40 [度]
(   14) CH0: 2.57[V], 526
温度: 26.50 [度]
(   15) CH0: 2.57[V], 526
温度: 26.50 [度]
(   16) CH0: 2.58[V], 527
温度: 26.60 [度]
(   17) CH0: 2.59[V], 530
温度: 26.92 [度]
(   18) CH0: 2.59[V], 530
温度: 26.92 [度]
(   19) CH0: 2.60[V], 532
温度: 27.12 [度]
(   20) CH0: 2.58[V], 528
温度: 26.71 [度]
(   21) CH0: 2.60[V], 531
温度: 27.02 [度]
(   22) CH0: 2.60[V], 532
温度: 27.12 [度]
(   23) CH0: 2.58[V], 528
温度: 26.71 [度]
(   24) CH0: 2.57[V], 526
温度: 26.50 [度]
(   25) CH0: 2.57[V], 525
温度: 26.40 [度]
(   26) CH0: 2.56[V], 524
温度: 26.29 [度]
(   27) CH0: 2.55[V], 522
温度: 26.08 [度]
(   28) CH0: 2.55[V], 522
温度: 26.08 [度]
(   29) CH0: 2.55[V], 522
温度: 26.08 [度]
(   30) CH0: 2.55[V], 521
温度: 25.98 [度]
(   31) CH0: 2.54[V], 520
温度: 25.88 [度]

まとめ

A/D 変換の場合、アナログ電圧を扱うので、ノイズや、A/D 変換に係る色々な事象が発生し、実用的に利用するには、色々なノウハウがあります。
R8C/Mxx の場合、マイコンの電源と、A/D 変換で使われるリファレンス電圧が共通になっているので、マイコン側のノイズが変換結果に影響を与えます。
精密な変換を行いたい場合、色々な工夫が必要と思いますが、R8C/Mxx の内蔵 A/D 変換は、ノイズも少なく、かなり良く出来ています。

サンプルホールドがあり、変換時間が短く、分解能も10ビットあるので、応用次第で、色々なアプリケーションに活用できるものと思えます。

参考リンク

次の記事:

前の記事:

開発環境の構築など:

format テンプレートクラス:

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?