動作
analogRead関数で端子の電圧を読み取るときの基準電圧(リファレンス電圧)を設定します。ただし、この関数は利用できないボードがありますので注意が必要です(ESP32やRaspberry Pi Picoでは利用できません)。
例えば5V動作のArduino Uno R3では、デフォルトでは5Vが基準電圧になっています。analogRead関数を実行すると、0Vのときに0、5Vのときに1023という数値で読み取ります。
この基準電圧はanalogReference関数で変更することができます。例えば、基準電圧を1.1Vに変更すると、0Vのときに0、1.1Vのときに1023という数値で読み取るようになります。つまり、基準電圧を下げると、狭い電圧範囲をより細かく読み取ることができます。

例えば、1℃あたり6.25mV変化するアナログ温度センサーの電圧を読み取る場合、基準電圧5V・10ビット分解能では、1ステップが約4.89mV(5V÷1023)刻みのため、1ステップ=0.78℃(4.89÷6.25)になります。つまり0.78℃より細かい変化は読み取れないことになります。
基準電圧を1.1Vに変更すると、1ステップが約1.07mV(1.1V÷1023)刻みのため、1ステップ=0.17℃(1.07÷6.25)になります。つまり、0.17℃の変化が読み取れることになります。
このように、低い電圧範囲のセンサーをより細かく測定したいなどの場合に、analogReference関数で基準電圧を変更すると効果的です。
選択できる基準電圧はArduinoボードごと(マイコンごと)に決まっています。具体的には「補足:analogReferenceで指定できる基準電圧」をご参照ください。
なお、ESP32とRaspberry Pi Picoなどのボードでは利用できませんので注意が必要です。ESP32とRaspberry Pi Picoはハードウェア的に基準電圧を変更できないためです。詳細は補足セクションをご確認ください。
書式
analogReference(type);| 引数 | type | 使用する基準電圧の種類を定数で指定します。 指定できる定数はボードによって異なります。代表的なボードの定数は次のとおりです(詳細は「補足:analogReferenceで指定できる基準電圧」を参照) Arduino Uno R3: DEFAULT(5V)INTERNAL(1.1V)EXTERNAL(AREFピン電圧)Arduino Uno R4: AR_DEFAULT(5V)AR_INTERNAL(1.5V)AR_INTERNAL_1_5V(1.5V)AR_EXTERNAL(AREFピン電圧)Arduino Zero: AR_DEFAULT(3.3V)AR_INTERNAL(2.23V)AR_INTERNAL1V0(1.0V)AR_INTERNAL1V65(1.65V)AR_INTERNAL2V23(2.23V)AR_EXTERNAL(AREFピン電圧) |
| 戻り値 | なし | |
主な用途
- 出力電圧範囲が低いアナログセンサー(温度センサー、フォトダイオードなど)を高精度で読み取る
- ボードの電源電圧の変動の影響を受けずに高精度測定を行う
- 外部の高精度基準電圧IC(リファレンスIC)を使用して測定精度を上げる
Arduinoボードの「AREFピン」に外部から電圧を供給する場合、analogRead関数を呼び出す前に必ずanalogReference(EXTERNAL)(またはAR_EXTERNAL)を実行する必要があります。(AREF:Analog Reference)
この設定を行わない状態でAREFピンに外部電圧を供給すると、マイコン内部で生成された基準電圧とAREFピンの外部電圧がショートしてしまい、マイコンを破損する可能性があります。
安全対策として、外部電圧は5kΩ程度の抵抗を介してAREFピンに接続することが推奨されています(詳細は「実践テクニック:外部基準電圧を安全に使用する」を参照)。
analogReference関数は、通常setup関数の中で1回だけ呼び出します。
基準電圧を変更した直後の数回分のanalogReadの読み取り値は、ADC内部回路の基準電圧が安定するまでに少し時間がかかるため正確でない場合があります。安定した値を取得したい場合は、基準電圧変更後にanalogReadを数回実行して、最初の値は捨てる方法が有効です。
ピンの電圧をより細かく読み取る方法には、「基準電圧を下げる(analogReference関数)」方法と、「分解能を上げる(analogReadResolution関数)」方法の2種類があります。それぞれ特徴がありますので、用途に合わせて使い分けてください(詳細は「補足:基準電圧の変更と分解能の変更の使い分け」を参照)。
使用例
次のコードにより、analogRead関数の基準電圧を変更することができます。
// Arduino Uno R3 / Nano / Mega などAVR系ボードの場合
analogReference(DEFAULT); // 動作電圧(5V または 3.3V)を基準電圧に設定(デフォルト)
analogReference(INTERNAL); // 内蔵1.1V基準電圧(ATmega328Pの場合)に設定
analogReference(EXTERNAL); // AREFピンに供給した外部電圧を基準電圧に設定
// Arduino Uno R4 の場合
analogReference(AR_DEFAULT); // 動作電圧(5V)を基準電圧に設定(デフォルト)
analogReference(AR_INTERNAL); // 内蔵1.5V基準電圧に設定
analogReference(AR_EXTERNAL); // AREFピンに供給した外部電圧を基準電圧に設定ボードによって指定できる定数が異なる点に注意してください。
AVR系ボードでは「DEFAULT」「INTERNAL」「EXTERNAL」のように接頭辞なしで指定しますが、Uno R4やZero、MKRシリーズなど新しいボードでは「AR_DEFAULT」「AR_INTERNAL」「AR_EXTERNAL」のように「AR_」が付きます(Analog Referenceの略)。
スケッチを別のボードに移植する際は、analogReferenceに指定する定数の修正が必要になることがあります。
サンプルスケッチ
以下の回路とスケッチは、基準電圧を1.1Vに変更して可変抵抗の値を読み取ります。
本来であれば、低電圧出力のアナログ温度センサーなどを使用した方がわかりやすいですが、シミュレータの部品ラインナップの関係上、次の回路とスケッチをサンプルとしました。
この回路では、ハードウェア的には可変抵抗のツマミが一番左側のとき0V、一番右側のとき5Vの出力になります。この出力電圧をA0端子で読み取ります。
基準電圧がデフォルト設定、つまり5Vの時は、ツマミを一番右側(5V)にするとanalogReadの読み取り値は1023になります。しかしこのスケッチではanalogReferenceで基準電圧を1.1Vに変更しています。そのため、つまみを一番右側から20%程度動かしただけでanalogReadの読み取り値は1023になります。
このようにanalogReferenceを使用すると、小さい電圧範囲を細かく読み取ることができます。
ボタンをクリックするとシミュレーターが動作します。スケッチを変更することもできます。変更した場合、シミュレーションを一度
ボタンをクリックして停止してから再度シミュレーターを開始してください。
このスケッチでは、analogReference関数を呼び出した直後に、念のためanalogRead関数で読み捨てを行っています。これは、基準電圧を切り替えた直後はADCの内部状態を安定化するためです。(シミュレータでは有効な効果はないと思いますが…)
トラブルシューティング
EXTERNAL指定で値が安定しない
EXTERNAL(またはAR_EXTERNAL)を指定した場合、AREFピンに供給する外部電圧の品質が読み取り精度に直接影響します。
外部電圧が不安定の場合、analogReadの読み取り値もばらつきます。基準電圧として使用する電圧源には、専用の高精度リファレンスIC(例:LM385B)を使用するようにします。
また、ノイズの影響が考えられる場合、AREFピン直近に0.1μF程度のセラミックコンデンサと10μF程度の電解コンデンサを並列に接続することで、読み取り値が安定する場合があります。コンデンサはなるべくAREFピンの近くに配置します。

上のイラストのように、コンデンサはAREFピンのなるべく近くに配置します。改善しないようであれば、可能であればノイズ発生源から離したり、電圧リファレンス回路をなるべくAREFピン近くに構成するなど、なるべくノイズの影響を受けないようにします。
また、Arduino Unoなどのピンソケットタイプのものは、AREFピンへの配線をなるべく短くし、コンデンサの接続もなるべくAREFピンの近くになるようにします。ブレッドボードを使用するとどうしても配線が長くなってしまいますので、アイデアとしては「Arduinoユニバーサルシールド」などの名称で回路製作ができるシールドがありますので、それを利用して電圧リファレンス回路を製作します。
設定変更直後の読み取り値がおかしい
analogReference関数で基準電圧を切り替えた直後、最初の数回のanalogRead読み取り値は不正確になることがあります。これはADC内部の基準電圧が完全に安定するまで時間がかかるためです。
対策として、基準電圧を変更した直後に数回読み捨てを行います。
analogReference(INTERNAL); // 基準電圧を変更
// 変更直後の値を読み捨てる
for (int i = 0; i < 5; i++) {
analogRead(A0);
delay(10);
}
// この後の読み取り値を使用する
int value = analogRead(A0);実践テクニック
analogReference関数に関連する実践テクニック集です。
基準電圧の変更と分解能の変更の使い分け
ピンの電圧をより細かく読み取りたい場合、analogReference関数で「基準電圧を下げる」方法と、analogReadResolution関数で「分解能を上げる」方法の2種類があります。それぞれにメリット・デメリットがあります。
実際の選択方法としては、使用するボードがanalogReadResolutionに対応している場合は分解能を上げる方法が手軽です。AVR系の古いボードを使用している場合や、外部の高精度リファレンスICで測定精度を上げたい場合は、analogReferenceで基準電圧を変更する方法を選びます。
基準電圧を下げる方法
- AVR系マイコンのボード(Uno R3、Nano、Megaなど)でも使用できる(これらのボードは
analogReadの読み取りが10ビット固定のため、分解能を上げる方法が使えない) - 分解能を変えないため、
analogReadの読み取り時間に影響しない(分解能のビット数が増えると、その分アナログ電圧をデジタル値に変換する時間が増えます)
- 基準電圧を超える電圧を入力すると、ADCの読み取り値が最大値(1023など)に張り付いてしまうため、測定範囲が管理できる場合に使用できる
- 選択できる内部の基準電圧はボードごとに決められた値のみで、自由な値には設定できない(ATmega328Pでは5Vまたは1.1Vで、その中間の値は選べない)
- 任意の基準電圧を使用したい場合は、ArduinoボードのAREFピンに外部から電圧を供給する必要があり、外付け回路が必要になる
分解能を上げる方法
- 基準電圧を変えていないため、入力電圧の上限を気にせず、5V(または3.3V)の範囲をそのまま使える
- スケッチ側で
analogReadResolution関数を呼び出すだけで設定できる
- 対応していないボードでは使用できない(AVR系のボードはハードウェアが10ビット固定)
- 下位ビットが電気的なノイズの影響を受けやすくなり、読み取り値がばらつきやすくなる
- ビット数が多くなる分、
analogReadの読み取り時間が長くなる
補足
analogReferenceで指定できる定数
ボードごとに指定できる定数と、対応する基準電圧は次のとおりです。
| ボード | 指定できる定数 |
|---|---|
| Arduino Uno R3 Arduino Nano Arduino Mini | DEFAULT:5V(動作電圧)INTERNAL:1.1VEXTERNAL:AREFピンの電圧 |
| Arduino Leonardo Arduino Micro | DEFAULT:5V(動作電圧)INTERNAL:2.56VEXTERNAL:AREFピンの電圧 |
| Arduino Mega | DEFAULT:5V(動作電圧)INTERNAL1V1:1.1VINTERNAL2V56:2.56VEXTERNAL:AREFピンの電圧 |
| Arduino Uno R4 Minima Arduino Uno R4 WiFi | AR_DEFAULT:5V(動作電圧)AR_INTERNAL:1.5VAR_EXTERNAL:AREFピンの電圧 |
| Arduino Zero Arduino MKRシリーズ | AR_DEFAULT:3.3V(動作電圧)AR_INTERNAL:2.23VAR_INTERNAL1V0:1.0VAR_INTERNAL1V65:1.65VAR_INTERNAL2V23:2.23VAR_EXTERNAL:AREFピンの電圧 |
| Arduino Due | AR_DEFAULT:3.3V(動作電圧) |
| ESP32 | analogReference関数は非対応なお、 analogAttenuation関数で読み取り電圧の減衰率設定が可能。詳細は補足セクションを参照。 |
| Raspberry Pi Pico | analogReference関数は非対応基準電圧は3.3V固定。変更する場合は外部から電圧を供給する必要あり。詳細は補足セクションを参照。 |
同じ「INTERNAL」でもマイコンによって電圧が異なる点には注意が必要です。
ATmega328Pを使用したボード(Uno R3、Nanoなど)の「INTERNAL」は内蔵1.1V基準電圧、ATmega32U4を使用したボード(Leonardo、Microなど)の「INTERNAL」は内蔵2.56V基準電圧です。同じスケッチを他のボードで使用する場合、注意が必要です。
AREFピンに接続する抵抗
Arduino公式ページ※では、AREFピンに外部の基準電圧を供給する場合、設定ミスによるマイコン破損を防ぐために、外部基準電圧源は5kΩ程度の抵抗を介して接続することが推奨されています(以下のArduino公式サイトの「Notes and Warnings」セクション)。
(※https://docs.arduino.cc/language-reference/en/functions/analog-io/analogReference/)

この対策は、Arduino Uno R3などのAVRマイコン系のボード用です。
Arduino Uno R4(Renesasマイコン)などの他のマイコンではハードウェア構成が異なりますので適用できない点に注意が必要です。
上のようにAREFピンに5kΩの抵抗を接続する場合は注意が必要です。
AREFピンの内部には約32kΩの抵抗が接続されているため、5kΩの抵抗を直列に入れると、外部電圧が分圧されてAREFピンに到達します。
例えば、外部から2.5Vを5kΩ抵抗を介して供給すると、AREFピンに実際にかかる電圧は次の計算となります。
実際のAREF電圧 = 2.5V × 32kΩ / (32kΩ + 5kΩ) ≒ 2.16V
このため、5kΩ抵抗を介して接続する場合は、実効電圧(分圧後の電圧)を考慮して以下のようにスケッチを記述する必要があります。
ただし、この対策をした場合は精度が悪くなる点にも注意が必要です。内部の抵抗値はおよそ32kΩで、さらにAREFピン外部に接続する5kΩの抵抗も少なからず誤差があります。そのため、実際のAREFの電圧は2.16Vからずれている可能性が高くなります。
// 外部2.5Vを5kΩ抵抗経由でAREFに接続した場合の例
// 実効基準電圧 = 2.16V
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL); // EXTERNAL指定(必ずanalogRead前に実行)
for (int i = 0; i < 5; i++){ // 何度かanalogReadで読み捨て
analogRead(A0);
}
}
void loop() {
int value = analogRead(A0);
// 実効基準電圧2.16Vで電圧計算
float voltage = value * (2.16 / 1023.0);
Serial.println(voltage, 4);
delay(500);
}5kΩ抵抗を介する方法のメリットは、設定ミスでマイコンの破損リスクを抑えられる点です。
抵抗による分圧の影響を受けたくない場合は、AREFピンに直接外部電圧を接続することもできますが、その場合はanalogReference(EXTERNAL)の設定漏れに細心の注意が必要です。
ESP32の基準電圧
ESP32では、analogReference関数は使用できません。
その代わり、ESP32では「入力電圧」(読み取りピンで読み取った電圧)を減衰することにより読み取る電圧範囲を変更することができます(詳細は後述)。
なお、ESP32のADCは内部構成上、精度が低い(線形性が良くない)ため、高精度のADコンバーターが必要な場合は別途ADコンバーターIC(MCP3208やADS1015など)を利用すると良いと思います。
ESP32のADC
ESP32のanalogRead関数で読み取る電圧範囲はデフォルトで0〜3.3Vとなっていますが、内部の基準電圧は1.1Vです(内部基準電圧を変更する手段はありません)。
ADコンバーターの基準電圧が1.1Vですので、1.1V以上の電圧を読み取ることはできません。そこで、ESP32の内部では基準電圧1.1Vに対してそれ以上の電圧まで読み取れるように、ピンの電圧を減衰器で低くしています(ピンの電圧に一定の倍率を掛け算して低くする回路が接続されています)。
ESP32では、減衰器でどれぐらい減衰するか設定できるようになっています。
例えば、ピンの電圧の減衰率を1倍にすると、0〜1.1Vを0〜4095(10ビット)で読み取ることができます。また、減衰率を0.5倍にすると、0〜2.2Vを0〜4095で読み取ることができます。
ESP32の減衰器設定
減衰器の倍率(減衰率)は次の関数で設定します。
analogSetAttenuation(value);引数は次のとおりです(戻り値はありません)。
| 引数(value) | 減衰率 (ピン電圧を何倍にするか) | 読み取り電圧上限値 |
|---|---|---|
ADC_0db | 1 | 1.1V |
ADC_2_5db | 0. 75 | 1.47V |
ADC_6db | 0.5 | 2.2V |
ADC_11db | 0.282※以下の注記参照 | 3.3V |
減衰率をADC_11dbに指定した場合、11dBの減衰となり減衰の倍率は0.282になります(10の−11/20乗)。この減衰率の値は少しややこしい状況になっています。
ESP32のデフォルトのADC読み取り電圧範囲は0〜3.3Vです。読み取り電圧最大値の3.3Vを基準電圧1.1Vに減衰するためには、3.3Vを約0.333倍する必要があります(3.3V × 0.333 ≒ 1.1V)。ところが、減衰器の設定値はADC_11dbでは0.282倍になっています(3.3Vを0.282倍すると0.93Vになり基準電圧の1.1Vにはなりません)。
これには次のような背景があります。
ESP32内部のADコンバーターは線形性が悪く、基準電圧1.1Vに対してADコンバーターの読み取り範囲は100mV〜950mVとされています(Espressif社「ESP32 Series Datasheet Version5.2」の4.9.1 Analog-to-Digital Converterに記載)。このADコンバーターの特性により、0〜0.1V付近の読み取り値は0、0.95〜1.1V付近の読み取り値は4095になってしまうようです。
このような特性のADコンバーターでピンの電圧を3.3V付近まで(なるべく)正しく読み取れるようにするため、減衰率を下げています。具体的には、減衰率を11dB(約0.282倍)にすることにより、0〜3.9Vの電圧範囲を0〜1.1Vの電圧範囲にマッピングしています。つまり、0〜3.3Vの電圧範囲は0〜0.93Vとなり、ESP32のADコンバーターの読み取り範囲の0〜0.95Vに収まるようになっています。
なお、減衰率が0.282倍のときは基準電圧が1.1Vであれば0〜3.9Vまで読み取れることになりますが、実際にはESP32のピンの耐圧は使用上VDD+0.3V(絶対最大定格)ですので3.9Vの電圧をかけると故障する可能性があります。
また、0V付近の線形性問題は残りますので、読み取り電圧範囲の15%〜85%程度で使用するのが安全です。
Raspberry Pi Picoの基準電圧
Raspberry Pi Picoは、ソフトウェアでADコンバーターの基準電圧を変更することはできません。基準電圧を変更したい場合、外部から基準電圧を供給する必要があります。
Raspberry Pi Picoの内部回路
Raspberry Pi Picoで使用しているプロセッサ(RP2040・RP2350)のADコンバーターは内部に基準電圧を発生する回路がありません。そのためプロセッサのADコンバーター用電源ピン(ADC_AVDDピン)の電圧を基準電圧に利用しています。
Raspberry Pi Picoでは、ADコンバーター用電源として次の回路で3.3Vのシステム電源を利用しています。

上の回路の部品定数はRaspberry Pi Picoのケースです。Raspberry Pi Pico 2では、抵抗R7が200Ω(1%・63mW)、抵抗R9が1Ω(1%・50mW)、コンデンサC13が4.7μF(6.3V)に変更されています。
このような回路でADコンバーター用の電源を生成しているため、次の問題があります。

- 3.3Vのシステム電源はスイッチング方式で生成しているため品質がよくありません。
- ADコンバーターの消費電流(約0.15mA)により、抵抗で約30mV(201Ω × 0.15mA)の電圧降下が発生します。またADコンバーターの計測中はこの電流が変化しますので、電圧降下も変動します。
外部参照電圧の利用
ADコンバーター用に安定した精度のよう電源を供給するため、公式ドキュメントでは、ADC_VREFピンに3.0Vまたは3.3Vのリファレンス電圧源を接続することが推奨されています。
外部リファレンス電圧源として3.0Vを接続した場合、200Ωの抵抗R7には常に1.5mA( (3.3V – 3.0V) ÷ 200)の電流が流れる点に注意が必要です。
外部リファレンス電源として2.5Vなどを選択する場合、R7の抵抗を外すとシステム電源と完全に分離することができます。なお、外部リファレンス電圧は2.0V以上が望ましいとされています。

Arduinoボード内部動作
Arduinoボードの内部動作は次のようになっています。次のイラストは、例としてArduino Uno R3の内部のようすを示しています。

「AD変換モジュール」には、変換の基準となる基準電圧の入力があります。この入力には、基準電圧を選択する「基準電圧セレクタ」(切り替え器)を介して以下のいずれかが接続されます。
- マイコン内部で生成された基準電圧(Uno R3では1.1V。マイコンによって異なる)
- AVCC(マイコンのシステム電圧、Uno R3では5V)
- AREFピンに外部から入力された電圧
analogReference関数を実行すると、この「基準電圧セレクタ」の切り替え設定が変更されます。
ADコンバーターはこの基準電圧を「最大値」として扱い、入力ピンの電圧を0〜最大分解能(10ビットの場合は1023)の範囲の数値に変換します。例えば基準電圧が1.1Vのとき、0Vの入力で0、0.55Vの入力で約512、1.1Vの入力で1023という数値になります。
なおArduino Uno R3では、AD変換モジュール自体は1個しか搭載されていないため、変換する対象のピンは「入力セレクタ」(入力ピンの切り替え器)でA0〜A5のいずれかのピンが選択されます。これはanalogRead関数の引数によ切り替えが行われます。
なお、入力セレクタでピンを切り替えた直後は、ADコンバーター内部の基準電圧新しい電圧で安定するまで多少の時間がかかります。このため、設定を変更した直後の数回分の読み取り値は正確でないことがあります。
