この文書の現在のバージョンと選択したバージョンの差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン | ||
xg_series_devel:use_adc:start [2018/03/20 09:37] admin |
xg_series_devel:use_adc:start [2019/01/07 16:16] (現在) admin |
||
---|---|---|---|
ライン 1: | ライン 1: | ||
+ | ====== AD Converter の利用 ====== | ||
+ | |||
+ | XG-50 の AD Converter には、外部電源(バッテリー[ch1]、ワイド電源[ch2]) を接続しています。\\ | ||
+ | 加えて、SoC 内部の Vref、温度センサーも有効化しています。 | ||
+ | |||
+ | ^ Channel ^ 入力 ^ Note | | ||
+ | | 0| VREFINT |SoC 内部基準電圧源| | ||
+ | | 1| バッテリー電圧 |アッテネータ経由((10/11 にしているため、真の値を求めるには 1.1 倍する必要があります))| | ||
+ | | 2| ワイド電源電圧((5〜36V)) |アッテネータ経由((1/12 にしているため、真の値を求めるには 12倍 する必要があります))| | ||
+ | | 17| 温度センサー |SoC 内蔵温度センサー| | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ===== 設定 ===== | ||
+ | |||
+ | ==== NuttX Configuration ==== | ||
+ | |||
+ | AD Converter を有効化するため、**make menuconfig** で NuttX の構成を変更します。 | ||
+ | |||
+ | * Device Drivers -> Analog Device(ADC/DAC) Support 有効化 | ||
+ | * Device Drivers -> Analog Device(ADC/DAC) Support -> Analog-to-Digital Conversion 有効化 | ||
+ | |||
+ | {{:xg_series_devel:use_adc:adc_menuconfig_01.png?600|}} | ||
+ | |||
+ | * Application Configuration -> Examples -> ADC example 有効化 | ||
+ | * ADC device path -> **"/dev/adc0"** | ||
+ | * Number of Samples per Group -> 4 | ||
+ | * Use software trigger 有効化 | ||
+ | |||
+ | {{:xg_series_devel:use_adc:adc_menuconfig_02.png?600|}} | ||
+ | |||
+ | config を保存し、build します。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ==== ファームウェアの書き込み ==== | ||
+ | |||
+ | [[xg_series_devel:boot_firmware:start]] を参考に、ファームウェアを XG-50 に書き込みます。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ===== 動作テスト ===== | ||
+ | |||
+ | 書き込んだファームウェアを実行すると、下のように **adc** というコマンドが使用できるようになります。 | ||
+ | |||
+ | <code> | ||
+ | NuttShell (NSH) | ||
+ | nsh> help | ||
+ | help usage: help [-v] [<cmd>] | ||
+ | |||
+ | [ dirname false mkfatfs pwd time | ||
+ | ? date free mkfifo reboot true | ||
+ | basename dd help mkrd rm uname | ||
+ | break df hexdump mh rmdir umount | ||
+ | cat dmesg kill mount set unset | ||
+ | cd echo ls mv sh usleep | ||
+ | cp exec mb mw sleep xd | ||
+ | cmp exit mkdir ps test | ||
+ | |||
+ | Builtin Apps: | ||
+ | adc <------- | ||
+ | cu | ||
+ | i2c | ||
+ | sudoku | ||
+ | nsh> | ||
+ | </code> | ||
+ | |||
+ | \\ | ||
+ | |||
+ | さっそく実行してみます。 | ||
+ | |||
+ | <code> | ||
+ | nsh> adc | ||
+ | adc_main: g_adcstate.count: 1 | ||
+ | adc_main: Hardware initialized. Opening the ADC device: /dev/adc0 | ||
+ | Sample: | ||
+ | 1: channel: 0 value: 1498 | ||
+ | 2: channel: 1 value: 3483 | ||
+ | 3: channel: 2 value: 0 | ||
+ | 4: channel: 17 value: 936 | ||
+ | nsh> | ||
+ | </code> | ||
+ | |||
+ | Channel 0, 1, 2, 17 の 4 つの値を取ることができました。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ==== 値の(電圧への)変換 ==== | ||
+ | |||
+ | 上記 AD 変換で取得した値は、アナログ電源(VDDA) を基準にした相対値((12bit ADC なので、0〜4095))となっています。\\ | ||
+ | STM32L4 の Reference Manual にあるとおり、実際の電圧を求めるには計算を行う必要があります。 | ||
+ | |||
+ | 計算式は下記のとおりです。 | ||
+ | |||
+ | $$ V_{CHANNEL_X} = \frac{V_{DDA}}{FULL\_SCALE} \times ADC_X\_DATA $$ | ||
+ | |||
+ | (Reference Manual より) | ||
+ | |||
+ | ここで、VDDA は 3.3[V]、FULL_SCALE は 4095 なのでそれを当てはめて Channel 1 (バッテリー入力電圧) を計算すると、 | ||
+ | |||
+ | $$ V_{CHANNEL1} = \frac{3.3}{4095} \times 3483 \times 1.1 = 3.087 [V] $$ | ||
+ | |||
+ | となります。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | === VREFINT を利用した計算 === | ||
+ | |||
+ | STM32L4 の VREFINT を利用し、VDDA の電圧に依存しない計算方法です。 | ||
+ | |||
+ | $$ V_{CHANNEL_X} = \frac{3.0 V \times VREFINT\_CAL \times ADC_X\_DATA}{VREFINT\_DATA \times FULL\_SCALE} $$ | ||
+ | |||
+ | |||
+ | ここで、各変数は下記の通りです。 | ||
+ | |||
+ | ^ 変数 ^ 内容 | | ||
+ | | VREFINT_CAL |VREFINT calibration value((メーカーにて出荷時にキャリブレーションした結果を不揮発領域に書き込んであります)) (0x1FFF75AA - 0x1FFF75AB)| | ||
+ | | ADC_DATA |AD 変換結果| | ||
+ | | VREFINT_DATA |Channel 0 AD変換結果| | ||
+ | | FULL_SCALE |4095| | ||
+ | |||
+ | \\ | ||
+ | |||
+ | 手元のチップでは、**VREFINT_CAL** の値は 0x0678 でした。 | ||
+ | |||
+ | <code> | ||
+ | nsh> mh 0x1fff75aa | ||
+ | 1fff75aa = 0x0678 | ||
+ | nsh> | ||
+ | </code> | ||
+ | |||
+ | \\ | ||
+ | |||
+ | この値を上記式に当てはめて計算すると、 | ||
+ | |||
+ | <code> | ||
+ | In [8]: ((3 * 0x0678 * 3483) / (1498 * 4095)) * 1.1 | ||
+ | Out[8]: 3.1028589034463536 | ||
+ | </code> | ||
+ | |||
+ | となります。 | ||
+ | |||
+ | 試しに電圧計で電源ピンのところで計測してみると 3.094 [V] でした。\\ | ||
+ | どちらの方法を使用しても 0.3% 程度の誤差((電圧計が正しいかどうかは置いておいて))で計測できるようです。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ==== 値の(温度への)変換 ==== | ||
+ | |||
+ | CH17 の温度センサーの値から温度への変換式は下記のとおりです。 | ||
+ | |||
+ | |||
+ | $$ Temperature\ (in \ ℃) = \frac{110\ ℃ - 30\ ℃}{TS\_CAL2 - TS\_CAL1} \times (TS\_DATA - TS\_CAL1) + 30\ ℃ $$ | ||
+ | |||
+ | ここで、各変数は下記になります。 | ||
+ | |||
+ | ^ 変数 ^ 内容 ^ | ||
+ | | TS_CAL1 |温度センサーキャリブレーション値((VDDA 3.0V)) @30℃ (0x1FFF75A8 - 0x1FFF75A9) | | ||
+ | | TS_CAL2 |温度センサーキャリブレーション値((VDDA 3.0V)) @110℃ (0x1FFF75CA - 0x1FFF75CB) | | ||
+ | | TS_DATA |温度センサー ADC 出力値| | ||
+ | |||
+ | **TS_CAL1**, **TS_CAL2** ともに VDDA が 3.0V のときの値となっていますが、XG-50 の VDDA は 3.3V のため、\\ | ||
+ | **『VREFINT を利用した計算』** を用いて換算する必要があります。 | ||
+ | |||
+ | \begin{align} | ||
+ | Temperature\ (in\ ℃) = \frac{110\ ℃ - 30\ ℃}{TS\_CAL2 - TS\_CAL1} \times \left(\frac{VREFINT\_CAL \times TS\_DATA}{VREFINT\_DATA} - TS\_CAL1 \right) + 30\ ℃ | ||
+ | \end{align} | ||
+ | |||
+ | \\ | ||
+ | |||
+ | 手元のチップで **TS_CAL1**, **TS_CAL2** を確認してみると、 | ||
+ | |||
+ | <code> | ||
+ | nsh> mh 0x1fff75a8 | ||
+ | 1fff75a8 = 0x0410 | ||
+ | nsh> mh 0x1fff75ca | ||
+ | 1fff75ca = 0x051b | ||
+ | </code> | ||
+ | |||
+ | それぞれ 0x0410, 0x051b となっているため、それを用いて計算すると、 | ||
+ | |||
+ | <code> | ||
+ | In [18]: VREFINT_CAL=0x0678 | ||
+ | |||
+ | In [19]: TS_DATA=936 | ||
+ | |||
+ | In [20]: TS_CAL1=0x410 | ||
+ | |||
+ | In [21]: TS_CAL2=0x51b | ||
+ | |||
+ | In [22]: VREFINT_DATA=1498 | ||
+ | |||
+ | In [23]: ((110 - 30) / (TS_CAL2 - TS_CAL1)) * ((VREFINT_CAL * TS_DATA) / VREFINT_DATA - TS_CAL1) + 30 | ||
+ | Out[23]: 28.419065620577733 | ||
+ | </code> | ||
+ | |||
+ | 28.4℃ となりました。 | ||
+ | |||
+ | \\ | ||
+ | |||
+ | ===== プログラミング ===== | ||
+ | |||
+ | ''apps/examples/adc/adc_main.c'' を参照してください。 | ||
+ | |||
+ | |||
+ | \\ | ||
+ | |||