Arduinoのアナログ基準電圧入力
『参照電圧について (要注意! きちんと守らないと故障の恐れ!)』
Arduinoのアナログ・リファレンス電圧設定についてを追いかけてみます。
・調べたのはArduino-UNO。(だけ)
ソースファイルを見たり、現物の信号をオシロで見たり・・・
AREFは入力状態。
つまり、外部基準電圧を受け入れる状態。
analogReference(EXTERNAL)と同じ状態。
INTERNALやDEFAULTではない。
ブートローダのソースを見ると、A/Dのマルチプレクサ
はリセット状態のままでリファレンス電圧入力の設定も
外部基準電圧の状態。
A/Dのクロック設定とADEN(A/D変換許可)を初期化し
ている。
しかし、マルチプレクサ切り替えと基準電圧の設定は
手を付けていない。
の設定:
内部基準電圧あるいはAVCCに切り替えても、A/D入力:
「analogRead() 」を実行するまでは「EXTERNAL」のまま。
analogReference()の実行だけでは、基準電圧の切り替えは
行われない。
analogRead()実行ではじめてanalogReference()の設定が
有効になる。
外部から基準電圧を供給しても問題なし。
衝突は発生しない。
:
Alternatively, you can connect the external reference voltage
to the AREF pin through a 5K resistor, allowing you to switch
between external and internal reference voltages.
Note that the resistor will alter the voltage that gets used
as the reference because there is an internal 32K resistor on
the AREF pin.
The two act as a voltage divider, so, for example, 2.5V
applied through the resistor will yield
2.5 * 32 / (32 + 5) = ~2.2V at the AREF pin.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
外部基準電圧とAREFピンの間に5kΩの抵抗を入れておけば、
内外の切り替えの間の衝突が避けられる。
ところが、AREF入力内部の入力抵抗は32kΩ。
だもんで、5kΩの抵抗を入れるとドロップが生じて、2.5Vの
基準電圧だと実質はざっと2.2Vになる。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
そんなうまいことはいきません。
ブートローダーの処理とユーザープログラムの初期化処理を
見る限り、AREFと外部基準電圧出力が衝突する心配はありま
せん。
抵抗を入れると、せっかくの外部基準電圧の精度が落ちてしま
います。
直列抵抗無しでOKというのが、私の結論です。
analogRead()を1回実行しておくことで、基準電圧の
切り替えがそのタイミングで行われて、以降のA/D変換が
安定するかと考えます。
{
// can't actually set the register here because the default setting
// will connect AVCC and the AREF pin, which would cause a short if
// there's something connected to AREF.
analog_reference = mode; ←ここでも変数を設定しているだけ。
}
ADMUX = (analog_reference << 4) | (pin & 0x07); ←AREFピンとマルチプレクサ確定
#else
ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif
#endif
// delay(1);
// start the conversion
sbi(ADCSRA, ADSC); ←A/D開始
while (bit_is_set(ADCSRA, ADSC)); ←変換終了待ち
high = ADCH;
※記事へのコメント書き込みアドレスをメモ
※さらに追記
上の方に記した
■Arduino Reference:analogReference()
Notes and Warnings
「:」で省略した部分に大事なことが書かれてます。
※5kΩや32kΩに目が奪われちゃって・・・
~~~~~~~~~~~~~~~~~~~~~~~~~~
After changing the analog reference, the first
few readings from analogRead() may not be accurate.
~~~~~~~~~~~~~~~~~~~~~~~~~~
「AREFを変えた後の何回かのanalogRead()は不正確かも。」
これ、外部に基準電圧をつなぐとなれば、
analogReference(EXTERNAL)の実行はsetup内で1回だけ。
何度も変えるものじゃありません。
そして、
~~~~~~~~~~~~~~~~~~~~~~~~~~
Don’t use anything less than 0V or more than 5V
for external reference voltage on the AREF pin!
~~~~~~~~~~~~~~~~~~~~~~~~~~
「AREFピンには0V未満あるいは5V越えの電圧を加えるな。」
※5VというよりAVCC電圧か。Arduinoなら5Vだけど。
~~~~~~~~~~~~~~~~~~~~~~~~~~
If you’re using an external reference on the
AREF pin, you must set the analog reference to
EXTERNAL before calling analogRead().
~~~~~~~~~~~~~~~~~~~~~~~~~~
「AREFピンに外部基準電圧をつなぐ場合は、analogRead()
実行前にEXTERNALに設定せよ。」
これが重要なわけです。
~~~~~~~~~~~~~~~~~~~~~~~~~~
Otherwise, you will short together the active
reference voltage (internally generated)and the
AREF pin, possibly damaging the microcontroller on
your Arduino board.
~~~~~~~~~~~~~~~~~~~~~~~~~~
「さもないと、内部生成された基準電圧とAREFピンが
ショートでArduinoに乗ったマイコンがつぶれるかも。」
そこから短絡防止のための姑息な手段の「5kΩ、32kΩ」の話がくるからややこしい。
| 固定リンク
「電子工作」カテゴリの記事
- ひさしぶりのイベントだったけど・・・「ピコピコ・スイッチ」破損(2021.12.13)
- 顕微鏡用LEDリングライトのLED、そろそろ交換か(2021.09.27)
- 可変抵抗器の「陽極酸化」(2021.09.22)
- 弾帯状になったQIコネクタのコンタクトピンを・・・(2021.08.27)
- AD620を使った計装アンプとシミュレーテッド・インダクタを使ったノッチフィルタ(2021.08.16)
「Arduino」カテゴリの記事
- Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMの例(2025.03.22)
- パルスジェネレータをI2C液晶で動かす(2025.01.28)
- EEPROMを使ったシリアル受信バッファ 512kバイトに増設(2024.12.26)
- 1/nカウント方式とDDS方式の2相パルス発生回路(2024.10.13)
- おっと。map関数の計算桁に注意(2024.10.06)
コメント
こんにちは。AREFのご指摘ありがとうございます。
あのページを書いたのはArduino Duemilanoveのmega168のころだったので、最新ハードでの回路や、ブートローダ、標準ライブラリなどの中身が進化している可能性があるとおもうので、現在のUno rev3などでは当てはまらなくなっているかも知れませんね。
当時から、CPUチップ内部でショートする可能性が…という話は、公式サイトでも会話がされていたので、すでに何らかの改善が行われているかもしれません。
ひとつ気になるのは、現在のADC周りの内部処理を追った結果、analogReference(EXTERNAL)に設定されているというお話です。
もし、参照電圧がADCの入力処理を行う時点でも「EXTERNAL」のままだと、参照電圧が直流的にはオープンのままになってしまう気がします。
(Duemilanove、Uno rev3の回路を見直してみた感じでは、CPUのAREFピンとGNDの間に0.1uFのコンデンサが繋がっているだけのようなので)
ADCのコンバート開始時に内部参照を使っているとすると、その電圧はAVccから持ってきているように思うのですが、するとやはりその時点で内部でショートするような気がします。
5kΩで保護するのは、内部抵抗との兼ね合いになるので、誤差が出そうでどうかなぁ、と当時思っていたんですが、たしか当時は内部の32kΩと外付けの5kΩで分圧って言う表記自体が無かったと記憶しています。多分、あとから追記されたのかなという気がします。やはり、5kΩ抵抗をつけるだけでは、ある程度の範囲で誤差が散らばりそうですね。
投稿: nekosan | 2019年3月23日 (土) 21時52分
えっと。
「analogReference」を使って基準電圧入力の状態を
積極的に設定しない限り、変数「analog_reference」
は「DEFAULT」のまま。
つまり、AVCCにつなぐぞ、です。
しかし、リセット起動後、ハード的にすぐにはつなぎません。
つまり・・・
「analogRead」を実行するまでは、AREFは
「EXTERNAL」(外部基準電圧入力)のままを保持。
だもんで、「analogRead」実行までは、ハード的な
短絡の危険性は無し。
しかし・・・
「analog_reference」で基準電圧の状態を設定せず
に「analogRead」でA/D値を読み取ると、
その時の「基準電圧=AREF」の接続先は「AVCC」。
AVCC=5Vが基準電圧となってしまいます。
この場合、外部基準電圧をつないだらあきません。
短絡が発生します。
だもんで・・・
外部基準電圧をつないでいるのなら・・・
setup内で
「analogReference(EXTERNAL)」を必ず実行しな
くちゃなりません。
これで、変数analog_reference が EXTERNALに変わり
その後の「analogRead」の処理では、外部基準電圧で
A/D変換が実行されます。
ということで・・・
外部基準電圧を使い、A/D入力処理を「analogRead」で行う
のなら、必ずこの手順を経ないと短絡が発生しちゃいます。
昔々のArduinoでの処理、それがどうなってたのかの
追跡はできていません。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2019年3月23日 (土) 23時35分
時系列で動作を説明していただいて、どのようにショートを避けられるかが解りました。ありがとうございます。
「analogReference(EXTERNAL)」で内部変数の設定を変更しておきつつ、実際にADCを動かすときに実際のSFRを変更して、参照電圧を切替えているという手間を考えると、やはりどこかのタイミングで、このように処理内容を変更した匂いがしますね。
そして、5kΩの抵抗を…というのも、もう必要なさそうですね。
投稿: nekosan | 2019年3月25日 (月) 00時58分
Arduinoの古いソースが保存されていたので、どんなふうに変遷があったのか確かめてみました。
結果・・・ 手順を守る限り短絡は発生しません。(昔から)
おそらく・・・ 推測を記事に追記しておきました。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2019年3月25日 (月) 09時11分
AREFに出てくる内部の基準電圧(Arduino-UNOなら1.1V)を外に取り出す方法を模索したことがあります。
http://act-ele.c.ooco.jp/blogroot/igarage/article/3352.html
http://act-ele.c.ooco.jp/blogroot/igarage/article/3366.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2019年3月25日 (月) 11時06分