基礎 · 読了まで16分

分圧回路の基本:公式、抵抗の選び方、Arduinoでの例

分圧回路はどう動くのでしょうか。Vout = Vin × R2 / (R1 + R2)の公式、抵抗の選び方、負荷効果、Arduinoでの12 Vの測定、5 Vから3.3 Vへの変換、LDRとNTCの読み取りを解説します。

分圧回路は、直列につないだ2本の抵抗を使って、ある電圧をより小さく予測可能な電圧に変える、いちばんシンプルな回路です。出力電圧はVout = Vin × R2 / (R1 + R2)で求められます。R1は電源側に、R2はグラウンド(GND)側につなぎ、出力は2本が接続される中点から取り出します。たとえば10 kΩの抵抗2本で、12 Vをちょうど半分の6 Vに分けられます。Arduinoで12 Vのバッテリーを測る、5 Vのセンサー信号をESP32の3.3 Vのピンに合わせて下げる、LDRやNTCサーミスタなどのセンサーを読み取るなど、数えきれないほどの回路の中心にこの2本の抵抗があります。

このガイドでは、公式がどこから来るのか、抵抗値をどう選ぶのか、分圧回路に何かをつなぐと出力が下がるのはなぜか(負荷効果)を、実際の数値で確認します。続いて、Arduino Uno、ESP32、Raspberry Pi Picoで電池の電圧を測るコードをステップごとに作り、5 Vを3.3 Vに変換するための適切な抵抗の組み合わせを選び、分圧回路でLDRとNTCを読み取ります。最後に、分圧回路を電源の代わりに使ってはいけない理由を説明します。

分圧回路に使う抵抗
分圧回路に必要なのは抵抗2本だけです。精密な測定には、誤差1%の金属皮膜抵抗を使うと、より正確な結果が得られます。

分圧回路とは?どのように動作するのか

分圧回路の公式は、オームの法則からそのまま導かれます。電源とグラウンドの間に直列につないだR1とR2には、同じ電流が流れます。I = Vin / (R1 + R2)です。出力であるR2の両端の電圧は、この電流にR2を掛けたもので、Vout = I × R2 = Vin × R2 / (R1 + R2)となります。つまり、電源電圧は抵抗値に比例して各抵抗に分配され、大きい抵抗ほど大きな電圧を受け持ちます。R2 / (R1 + R2)の比は1より小さいので、出力は常に入力より小さくなります。直列回路で電圧がどのように分配されるかは、抵抗の直列・並列の計算で詳しく説明しています。

求める値公式例(Vin = 12 V、R1 = 22 kΩ、R2 = 10 kΩ)
出力電圧Vout = Vin × R2 / (R1 + R2)12 × 10 / 32 = 3.75 V
分圧比k = R2 / (R1 + R2)10 / 32 = 0.3125
出力から入力を求めるVin = Vout × (R1 + R2) / R23.75 × 3.2 = 12 V
目的の比に合わせたR1R1 = R2 × (Vin / Vout − 1)10 kΩ × (12 / 3.75 − 1) = 22 kΩ
分圧回路の電流I = Vin / (R1 + R2)12 / 32 kΩ = 0.375 mA
全体の電力P = Vin² / (R1 + R2)144 / 32 kΩ = 4.5 mW
出力抵抗(テブナン)Rth = R1 × R2 / (R1 + R2)22 × 10 / 32 = 6.875 kΩ

逆から考えることもできます。12 Vを3.3 Vに下げたいとき、R2に10 kΩを選んだなら、R1 = 10 × (12 / 3.3 − 1) ≈ 26.4 kΩになります。この値の抵抗は売られていないので、1つ上の標準値である27 kΩを選ぶと、出力は12 × 10 / 37 ≈ 3.24 Vになります。R1を切り上げると出力が少し下がり、ピンにとっては安全側になります。ポテンショメーターも実は可変の分圧回路で、ワイパー(中央の端子)が抵抗体をR1とR2に分けています。手で計算したくない場合は、分圧計算ツールに入力電圧と抵抗値を入れれば、すぐに出力がわかります。電子工作では、分圧回路はおもに次のような用途で使われます。

  • 高い電圧の測定:12 Vのバッテリーや7.4 Vのリチウムパックなどの電源を、アナログ入力で測れる範囲まで下げます。
  • 信号レベルを下げる:5 Vの信号を、ESP32やRaspberry Pi Picoの3.3 Vの入力に安全な電圧にします。
  • 抵抗が変化するセンサーの読み取り:LDR、NTC、曲げセンサー(フレックスセンサー)、感圧センサー(FSR)などの部品の抵抗変化を、電圧に変えます。
  • 1本のピンで複数のボタンを読む:抵抗ラダーでボタンごとに異なる電圧を与えれば、5個のボタンで1本のアナログピンを共有できます。
  • レギュレーターのフィードバック:LM317や可変出力のLM2596などのレギュレーターは、出力を分圧回路で測って一定に保ちます。LM317ではVout = 1.25 × (1 + R2 / R1)です。
  • 基準電圧の生成:オペアンプ回路で、電源電圧の半分を基準電圧として作ります。

抵抗値の選び方

公式が気にするのは比だけです。1 kΩ + 1 kΩでも100 kΩ + 100 kΩでも、同じようにちょうど半分に分けます。しかし実際には、抵抗値そのものの大きさも重要です。小さい抵抗では、分圧回路に多くの電流が流れます。この電流は無駄なエネルギーで、電池で動くプロジェクトでは電池を無駄に消耗させます。大きい抵抗では電流はごくわずかですが、出力が弱くなります。つないだ負荷やアナログ入力内部のサンプリングコンデンサが出力電圧を簡単に乱し、配線が拾うノイズも入り込みやすくなります。適切な選択は、この2つの極端の間でバランスを取ることです。

合計抵抗(R1 + R2)12 Vでの電流長所短所主な用途
100 Ω〜1 kΩ12〜120 mA負荷の影響をほとんど受けず、非常に高速発熱し、電流を多く無駄にする測定回路ではほぼ使わない
1 kΩ〜30 kΩ0.4〜12 mAADCに理想的な出力抵抗で、高速な信号に向く電池のプロジェクトでは電流が常に流れる5 V → 3.3 Vの信号変換、Arduinoでの測定
30 kΩ〜300 kΩ40〜400 µA電池にやさしく、発熱しないアナログ入力に100 nFのコンデンサが必要な場合がある電池の監視
1 MΩ以上12 µA未満電流をほとんど流さないノイズに弱く、ADCで正確に読めず、テスターでさえ負荷になるオペアンプのバッファと組み合わせる場合のみ
  1. 最大入力電圧を確認します。12 Vの鉛蓄電池は、充電中に14.4 Vまで上がることがあります。測る電圧の最悪の場合を考え、さらに10%の余裕を加えます。
  2. ピンが受け付ける最大電圧を確認します。Arduino Unoは5 V、ESP32とPicoは3.3 Vです。安全な目標として、Unoでは約4.5 V、ESP32では2.5 V、Picoでは3.0 Vを選びます。
  3. 比を計算します:k = 目標の出力 / 最大入力です。たとえば4.5 / 14.4 ≈ 0.31になります。
  4. R2を選び(ほとんどの場合、10 kΩから始めるのがおすすめです)、R1 = R2 × (1 / k − 1)でR1を求めます。結果は抵抗の標準値の中から、1つ上の値に切り上げます。
  5. 電流と電力を確認します:I = Vin / (R1 + R2)、P = Vin² / (R1 + R2)です。電池のプロジェクトでは、電流をマイクロアンペアの範囲に抑えるようにします。
  6. 出力抵抗を確認します:Arduino Unoでは、R1 × R2 / (R1 + R2)が10 kΩ未満になるようにします。そうならない場合は、アナログピンとGNDの間に100 nFのコンデンサを追加します。
  7. 実際の比をコードに書きます:選んだ標準値で比を計算し直し、回路を組んだらテスターで測ってキャリブレーションします。
抵抗の誤差は、分圧比を直接ずらします。最悪の場合、誤差5%の22 kΩと10 kΩの抵抗では、比が0.291から0.334の間のどこにでもずれる可能性があり、およそ±7%になります。つまり、12 Vを11.2 Vや12.8 Vと読んでしまうかもしれません。誤差1%の金属皮膜抵抗なら誤差は±1.4%まで下がり、テスターで1回キャリブレーションすれば、ほぼなくなります。

負荷効果:分圧回路に何かをつなぐとどうなる?

公式は、出力から電流を取り出さないことを前提にしています。負荷をつないだ瞬間、負荷はR2と並列になり、下側の合成抵抗が小さくなって、出力電圧が下がります。これを簡単に計算するには、分圧回路をテブナンの等価回路として考えます。無負荷で測った電圧(Vth)と、内部抵抗Rth = R1 × R2 / (R1 + R2)を持つ電源とみなすのです。負荷RLをつなぐと、出力はVth × RL / (Rth + RL)になります。下の表は、10 Vの電源を10 kΩ + 10 kΩで分圧し(Vth = 5 V、Rth = 5 kΩ)、出力にさまざまな負荷をつないだ場合です。

出力の負荷(RL)出力電圧誤差
無負荷5.00 V0%
1 MΩ4.98 V0.5%
100 kΩ4.76 V4.8%
10 kΩ3.33 V33%
1 kΩ0.83 V83%

目安として、負荷の抵抗が分圧回路の出力抵抗(Rth)の100倍以上あれば、誤差は1%未満に収まります。負荷がそれより小さい場合は、抵抗値を小さくするか、間にオペアンプのボルテージフォロワ(バッファ)を入れます。マイコンのアナログ入力自体は非常に高い抵抗を持っていますが、内部には変換のたびに充電される小さなサンプリングコンデンサがあります(ATmega328Pでは約14 pF)。そのため、データシートでは信号源の出力抵抗を約10 kΩ以下にするよう推奨しています。それより大きな抵抗の分圧回路を使う場合は、アナログピンとGNDの間に100 nFのコンデンサを追加してください。サンプリングの瞬間に必要な電荷を、このコンデンサが用意しておいてくれます。また、複数のアナログピンを順番に読む場合は、各ピンの最初の読み取り値を捨てると、チャンネルの切り替えで残った誤差を取り除けます。

分圧回路を電源として使えない理由

初心者がいちばん陥りやすい落とし穴は、12 VのACアダプターから2本の抵抗で5 Vを取り出し、それでArduinoやモジュールを動かそうとすることです。計算上は7 kΩと5 kΩの分圧回路で12 Vからちょうど5 Vが得られますが、それは出力から電流を取り出さない場合に限ります。50 mAを消費するボードは約100 Ωの負荷のように振る舞い、5 kΩのR2と並列になると下側の抵抗は98 Ωまで下がって、出力は0.17 Vまで落ち込みます。抵抗を70 Ωと50 Ωまで小さくすると、今度は何もつないでいなくても回路に100 mAが流れ、1.2 Wが熱になります。負荷をつなげば出力はやはり3.9 Vまで下がり、ボードの消費電流が変わるたびに(Wi-Fi、サーボ、リレー)電圧も変動します。さらに、負荷を外すと電圧が再び上がり、繊細な部品を壊すおそれがあります。

回路に電源を供給するには、分圧回路ではなくレギュレーターを使います。小さな電流なら7805電圧レギュレーター(3.3 VならAMS1117)、大きな電流と高い効率が必要ならLM2596のような降圧コンバーターが、負荷にかかわらず出力を一定に保ちます。分圧回路は測定と信号だけに使い、商用電源をシンプルな分圧回路でArduinoにつなぐことは絶対にしないでください。そのための絶縁型モジュールがあります。

Arduinoで12 Vのバッテリーと電池の電圧を測る

Arduino Unoのアナログ入力で読めるのは最大5 Vまでで、12 Vのバッテリーを直接つなぐとピンが壊れます。解決策は、22 kΩ(R1)と10 kΩ(R2)の分圧回路です。比が0.3125なので、充電時の14.4 Vはピンに4.5 Vとして届き、この回路で最大16 Vまで測れます。12 Vでの分圧回路の電流はわずか0.375 mAで、出力抵抗の6.9 kΩも推奨される10 kΩの上限を下回ります。10ビットADCの1ステップは約4.9 mVなので、分圧回路と合わせると、入力側の分解能は約15.6 mVになります。ESP32とPicoは3.3 Vで動作するので、これらのボードではより大きなR1(56 kΩ)を使います。

接続Arduino UnoESP32Raspberry Pi Pico
R1(上側の抵抗)22 kΩ56 kΩ56 kΩ
R2(下側の抵抗)10 kΩ10 kΩ10 kΩ
R1の上端電源のプラス(+12 V)電源のプラス(+12 V)電源のプラス(+12 V)
中点(R1–R2)A0GPIO 34(ADC1)GP26(ADC0、31番ピン)
R2の下端と電源のマイナスGNDGNDGND(例:38番ピン)
14.4 Vでのピンの電圧4.50 V2.18 V2.18 V
測れる最大入力16 V約16 V(正確に測れる範囲)約21 V
電源のマイナス端子とArduinoのGNDは、必ずつないでください。共通のグラウンドがないと測定する電圧に基準がなくなり、値が意味もなく飛び回ります(詳しくはGNDと共通グラウンドを参照してください)。抵抗を逆に付けるのも危険です。上に10 kΩ、下に22 kΩを付けると、12 Vのうち8.25 Vがピンにかかります。回路をマイコンにつなぐ前に、テスターで中点の電圧を測ってください。
C++ (Arduino IDE)
1// 12 V akü gerilimini gerilim bölücüyle ölçme / Measuring a 12 V battery with a voltage divider
2// Kaynak + -> 22k (R1) -> A0 -> 10k (R2) -> GND / Source + -> 22k (R1) -> A0 -> 10k (R2) -> GND
3// Kaynağın eksisi Arduino GND'sine bağlı / Source minus is tied to the Arduino GND
4const int VIN_PIN = A0;
5const float VREF = 5.0;      // 5V pininde ölçtüğün gerilim / voltage you measured on the 5V pin
6const float R1 = 22000.0;    // üst direnç (ohm) / top resistor (ohms)
7const float R2 = 10000.0;    // alt direnç (ohm) / bottom resistor (ohms)
8const float CAL = 1.000;     // kalibrasyon: gerçek / okunan / calibration: real / measured
9const float LOW_V = 11.8;    // düşük akü eşiği (V) / low battery threshold (V)
10
11float readInputVoltage() {
12  analogRead(VIN_PIN);                        // ilk okumayı at / discard the first reading
13  long sum = 0;
14  for (int i = 0; i < 16; i++) {              // 16 ölçümün ortalaması / average of 16 readings
15    sum += analogRead(VIN_PIN);
16    delay(2);
17  }
18  float vPin = (sum / 16.0) * VREF / 1024.0;  // pindeki gerilim / voltage at the pin
19  return vPin * (R1 + R2) / R2 * CAL;         // bölücüden önceki gerilim / voltage before the divider
20}
21
22void setup() {
23  Serial.begin(9600);
24  pinMode(LED_BUILTIN, OUTPUT);
25}
26
27void loop() {
28  float v = readInputVoltage();
29  Serial.print(F("Giris / Input: "));
30  Serial.print(v, 2);
31  Serial.println(F(" V"));
32  digitalWrite(LED_BUILTIN, v < LOW_V ? HIGH : LOW);  // akü zayıfsa LED yanar / LED on when the battery is low
33  delay(1000);
34}

このコードは、ADCのサンプリングコンデンサが安定するように最初の読み取り値を捨て、その後16回の平均をとってノイズを減らします。読み取った数値はまずピンの電圧に変換され(ATmega328PのデータシートではADC = Vin × 1024 / Vrefとされているので、1024で割ります)、次に(R1 + R2) / R2 = 3.2を掛けて分圧前の電圧を求めます。最大の誤差の原因はVrefです。USB給電のUnoの5Vピンは、4.7〜5.1 Vのどこかになっていることがよくあります。そこで、5Vピンをテスターで測ってその値をVREFに入れ、さらにバッテリーの実際の電圧もテスターで測ってシリアルモニタの値と比べ、CAL = 実測値 / 読み取り値をコードに入力します。この1ステップで、Vrefと抵抗の誤差をまとめて補正できます。分圧回路を機器の電源スイッチの後ろにつなげば、電源がオフの間は電流が流れません。0.375 mAは1日で約9 mAhになり、車のバッテリーなら問題になりませんが、小さな電池でははっきりと影響が出ます。ほかの電源に合う抵抗の組み合わせは次のとおりです。

測る電源電圧範囲Arduino Uno(5 V):R1 + R2ESP32 / Pico(3.3 V):R1 + R2
1セルのLi-ion / LiPo(1S)3.0〜4.2 V分圧回路は不要(4.2 V < 5 V)100 kΩ + 100 kΩ → 最大2.10 V
2SのLi-ionパック6.0〜8.4 V10 kΩ + 10 kΩ → 最大4.20 V100 kΩ + 33 kΩ → 最大2.08 V
3SのLiPoパック9.0〜12.6 V22 kΩ + 10 kΩ → 最大3.94 V56 kΩ + 10 kΩ → 最大1.91 V
12 Vの鉛蓄電池10.5〜14.4 V22 kΩ + 10 kΩ → 最大4.50 V56 kΩ + 10 kΩ → 最大2.18 V
24 Vのシステム21〜29 V56 kΩ + 10 kΩ → 最大4.39 V120 kΩ + 10 kΩ → 最大2.23 V

ESP32で電圧を測る

ESP32のADCは12ビット(0〜4095)ですが、2つの重要な違いがあります。1つ目は、Wi-Fiがオンの間はADC2のピンを読めないことです。分圧回路は必ず、ADC1のピンであるGPIO 32〜39のどれかにつないでください(GPIO 34〜39は入力専用で、この用途に最適です)。2つ目は、ADCが両端付近で直線的でないことです。初期設定の11 dBの減衰では、Espressifはおよそ150〜2450 mVをもっとも正確な範囲として推奨しています。ピンは約3.1 Vまでの値を示しますが、その領域では誤差が大きくなります。そのため、56 kΩ + 10 kΩの分圧回路を選びました。14.4 Vはピンに2.18 Vとして届き、正確な範囲に収まります。生のanalogRead()の代わりに、工場でチップに書き込まれたキャリブレーションデータを使ってミリボルト値を直接返すanalogReadMilliVolts()を使います。

C++ (Arduino IDE)
1// ESP32: 56k + 10k bölücüyle 12 V ölçme / ESP32: measuring 12 V with a 56k + 10k divider
2const int VIN_PIN = 34;        // ADC1_CH6, Wi-Fi açıkken de çalışır / ADC1_CH6, works with Wi-Fi on
3const float R1 = 56000.0;      // üst direnç (ohm) / top resistor (ohms)
4const float R2 = 10000.0;      // alt direnç (ohm) / bottom resistor (ohms)
5const float CAL = 1.000;       // multimetreyle ayarla / tune with a multimeter
6
7void setup() {
8  Serial.begin(115200);
9  analogReadResolution(12);    // 0-4095 (varsayılan / default)
10}
11
12void loop() {
13  uint32_t mv = 0;
14  for (int i = 0; i < 32; i++) {
15    mv += analogReadMilliVolts(VIN_PIN);     // kalibre edilmiş milivolt / calibrated millivolts
16  }
17  float vPin = mv / 32.0 / 1000.0;           // pindeki gerilim (V) / voltage at the pin (V)
18  float vIn = vPin * (R1 + R2) / R2 * CAL;   // bölücüden önceki gerilim / voltage before the divider
19  Serial.printf("Pin: %.3f V  Giris / Input: %.2f V\n", vPin, vIn);
20  delay(1000);
21}

Raspberry Pi Picoで電圧を測る(MicroPython)

Raspberry Pi Picoのアナログ入力は、GP26、GP27、GP28(ADC0〜ADC2)です。MicroPythonのread_u16()は12ビットの測定値を0〜65535の範囲にスケーリングし、基準はボードの3.3 Vから来るADC_VREFです。PicoのADCは3.3 Vまで測れるので、56 kΩ + 10 kΩの分圧回路で約21 Vまで測定できます。おもしろいことに、Pico自身も分圧回路を使っています。ボード上の分圧回路がVSYSの電源電圧を3分の1にしてGP29(ADC3)に入力しているので、ADC(29)で読み取った電圧に3を掛ければ、ボードの電源電圧がわかります(Pico WではGP29が無線チップと共用されているため、この方法はそのままでは使えません)。

MicroPython
1from machine import ADC
2import time
3
4adc = ADC(26)            # GP26 = ADC0 (pin 31)
5VREF = 3.3               # ADC_VREF; multimetreyle ölçüp düzelt / measure and correct with a multimeter
6R1 = 56000               # üst direnç (ohm) / top resistor (ohms)
7R2 = 10000               # alt direnç (ohm) / bottom resistor (ohms)
8CAL = 1.000              # kalibrasyon katsayısı / calibration factor
9
10
11def read_input_voltage(samples=32):
12    total = 0
13    for _ in range(samples):
14        total += adc.read_u16()                  # 0-65535
15    v_pin = total / samples * VREF / 65535       # pindeki gerilim / voltage at the pin
16    return v_pin * (R1 + R2) / R2 * CAL          # bölücüden önceki gerilim / voltage before the divider
17
18
19while True:
20    v_in = read_input_voltage()
21    print("Giris / Input: {:.2f} V".format(v_in))
22    time.sleep(1)

5 V信号を3.3 Vに下げる(ESP32とPico向け)

ESP32とPicoのピンは5 Vトレラントではありません。HC-SR04のECHO出力、Arduino UnoのTXピン、5 Vで動くモジュールのデジタル出力をこれらのボードに直接つなぐと、入力の保護ダイオードに負担がかかり、ピンがしだいに壊れることがあります。一方向の信号なら、いちばん安い解決策は分圧回路です。目標は、3.3 Vを超えることはないものの、ボードがHIGHと読める程度には高い電圧です。ESP32は電源電圧の75%(約2.5 V)を、PicoのRP2040は2.0 VをHIGHの最低レベルとしています。つまり、3.0〜3.3 Vの出力なら、どちらのボードでも十分な余裕があります。これはHC-SR04距離センサーのガイドで、ECHOピンを3.3 Vのボードにつなぐ方法として紹介しているのと同じやり方です。

R1(信号側)R2(GND側)5 V入力時の出力出力抵抗評価
1 kΩ2 kΩ(1 kΩ×2本を直列)3.33 V667 Ω定番の組み合わせ。高速な信号にも使える
1.2 kΩ2.2 kΩ3.24 V776 ΩE12系列の標準値で、3.3 Vのすぐ下
10 kΩ20 kΩ3.33 V6.7 kΩ電流が少ない。UARTとHC-SR04には十分
2.2 kΩ3.3 kΩ3.00 V1.3 kΩもっとも安全な余裕。どちらのボードもHIGHと読める
4.7 kΩ10 kΩ3.40 V3.2 kΩぎりぎり。5 Vラインが5.25 Vまで上がると3.57 Vになるため、非推奨

分圧回路は、ピン自体の静電容量と合わさって小さなRCフィルタを作ります。10 kΩ + 20 kΩの分圧回路の出力抵抗6.7 kΩと、ピンとブレッドボードの約15 pFの静電容量では、時定数はおよそ100 nsになります。115200ボーのUART(1ビットあたり8.7 µs)には影響しませんが、数MHzのSPI信号ではエッジが丸くなってしまいます。高速な信号線には1 kΩ + 2 kΩを選んでください。また、分圧回路が働くのは、高い電圧から低い電圧への一方向だけであることも覚えておきましょう。逆方向では、たいてい何もする必要はありません。Arduino Unoは3.0 Vを超える電圧をHIGHとみなすので、余裕は小さいものの、ESP32の3.3 Vの出力を読み取れます。ただし、I2Cのような双方向の信号線では分圧回路は役に立たず、MOSFETを使ったレベル変換モジュールを使います。

分圧回路でLDRとNTCを読み取る

LDR(フォトレジスタ)光センサー
LDRの抵抗は光によって変化します。固定抵抗と組み合わせて分圧回路を作ると、その変化をArduinoが読み取れる電圧に変えられます。

マイコンは抵抗を直接測ることはできず、測れるのは電圧だけです。LDRやNTCのような抵抗が変化するセンサーを固定抵抗と直列につないで分圧回路を作ると、抵抗の変化が中点の電圧の変化になります。固定抵抗の値で感度が決まります。電圧の変化幅を最大にするには、固定抵抗を、測りたい範囲でのセンサーの最小抵抗と最大抵抗の幾何平均にします。R = √(Rmin × Rmax)です。明るいところで1 kΩ、暗いところで100 kΩになるLDRなら、√(1 k × 100 k) = 10 kΩです。5 Vの場合、10 kΩなら出力は4.09 Vの幅で変化しますが、1 kΩや100 kΩでは変化幅が2.45 Vに縮まります。スターターキットに10 kΩの抵抗が入っているのは、このためです。もう1つ利点があります。分圧回路とADCが同じ5 Vで動くので、計算した抵抗値は電源電圧に左右されません(レシオメトリック測定)。そのため、下のコードではVrefの値さえ必要ありません。

C++ (Arduino IDE)
1// LDR ve NTC'yi gerilim bölücüyle okuma / Reading an LDR and an NTC with voltage dividers
2// A0: 5V -> LDR -> A0 -> 10k -> GND
3// A1: 5V -> 10k -> A1 -> NTC 10k (B = 3950) -> GND
4const float R_FIXED = 10000.0;  // sabit dirençler (ohm) / fixed resistors (ohms)
5const float R0 = 10000.0;       // NTC'nin 25 °C direnci / NTC resistance at 25 °C
6const float BETA = 3950.0;      // NTC B katsayısı / NTC beta coefficient
7const float T0 = 298.15;        // 25 °C kelvin cinsinden / 25 °C in kelvin
8
9void setup() {
10  Serial.begin(9600);
11}
12
13void loop() {
14  analogRead(A0);                         // kanal değişti, ilk okumayı at / channel changed, discard first reading
15  int ldrRaw = analogRead(A0);
16  analogRead(A1);
17  int ntcRaw = analogRead(A1);
18  if (ldrRaw < 1) ldrRaw = 1;             // sıfıra bölmeyi önle / avoid division by zero
19
20  // Oransal ölçüm: besleme gerilimi hesaptan düşer / ratiometric: the supply voltage cancels out
21  float rLdr = R_FIXED * (1024.0 / ldrRaw - 1.0);
22  float rNtc = R_FIXED * ntcRaw / (1024.0 - ntcRaw);
23  float tempC = 1.0 / (1.0 / T0 + log(rNtc / R0) / BETA) - 273.15;  // Beta denklemi / Beta equation
24
25  Serial.print(F("LDR: "));
26  Serial.print(rLdr / 1000.0, 1);
27  Serial.print(F(" kOhm   NTC: "));
28  Serial.print(rNtc / 1000.0, 2);
29  Serial.print(F(" kOhm   "));
30  Serial.print(tempC, 1);
31  Serial.println(F(" C"));
32  delay(1000);
33}

コードではLDRを上側に置いているので、明るくなるほど読み取り値が大きくなります。LDRの抵抗はR = 10 kΩ × (1024 / ADC − 1)です。NTCは下側に置いていて、温度が上がると抵抗が下がり、読み取る電圧も下がります。25 °Cで10 kΩ、B定数3950の一般的なNTCでは、温度はB定数の式(Beta式)で求めます。1 / T = 1 / T0 + ln(R / R0) / B(温度はケルビン)です。固定抵抗をNTCの25 °Cでの抵抗値と同じにしているので、室温では出力がちょうど電源電圧の半分になり、そこで感度がもっとも高くなります。広い温度範囲でより高い精度が必要な場合のSteinhart-Hartの式や、NTCの自己発熱については、NTCサーミスタのガイドで取り上げています。

分圧回路を使ったプロジェクトアイデア

  • バッテリーモニターと低電圧アラーム:キャンピングカーやソーラー発電システムのバッテリーを監視し、11.8 Vを下回ったらブザーを鳴らします。電池で動くプロジェクトの電源の選択肢については、Arduinoを電池で動かす方法を参照してください。
  • デジタル電圧計:測定した電圧をLCDやOLEDディスプレイに表示します。手順はArduinoで電圧計を作るで説明しています。
  • 自動常夜灯:LDRの分圧回路を使い、暗くなったらLEDやリレーをオンにします。
  • 太陽追尾装置:2つのLDR分圧回路の電圧を比べ、パネルを光の方向に向けます(太陽追尾装置)。
  • 1本のピンに5個のボタン:異なる抵抗でラダーを組み、アナログ値からどのボタンが押されたかを判断します(ボタンの配線)。
  • サーモスタット:NTCの分圧回路で温度を測り、設定した温度になったらファンやヒーターをリレーで切り替えます。

よくある間違いと対処法

症状考えられる原因対処法
値が意味をなさず、ずっと飛び回る電源のマイナスがArduinoのGNDにつながっていないGNDを共通にする
ピンの電圧が予想よりずっと高いR1とR2が逆になっている大きい抵抗を電源側(上側)に付ける。つなぐ前にテスターで測る
測定値が実際の値と5〜10%ずれる誤差5%の抵抗、またはVrefが5.00 Vではない誤差1%の金属皮膜抵抗を使い、コードのVREFとCALでキャリブレーションする
モジュールをつなぐと出力が下がる負荷効果:負荷がR2と並列になっている負荷をRthの100倍以上にする、抵抗を小さくする、またはオペアンプのバッファを使う
高抵抗の分圧回路で値がずれていくADCのサンプリングコンデンサが十分に充電されないピンに100 nFのコンデンサを追加し、最初の読み取り値を捨てる
Wi-Fiを開始するとESP32の読み取りが動かなくなる分圧回路がADC2のピンにつながっているGPIO 32〜39(ADC1)を使う
機器がオフでも電池が減る分圧回路が電池から常に電流を流している分圧回路をスイッチの後ろにつなぎ、高い値の抵抗を使う
分圧回路から給電したモジュールが動かない分圧回路は電源ではない7805、AMS1117、LM2596などのレギュレーターを使う
分圧回路を通すとI2Cが動かない分圧回路は一方向、I2Cは双方向MOSFETを使ったレベル変換モジュールを使う
新しい分圧回路を作ったら、マイコンにつなぐ前に電源を入れて、中点の電圧をテスターで測ってください。値が分圧計算ツールの結果と数%以内で一致していれば、配線をアナログピンに移します。この10秒の確認で、逆に付けた抵抗がボードを壊すのを防げます。

分圧回路は抵抗2本と公式1つだけですが、何かを測るほぼすべてのプロジェクトのどこかに登場します。比は公式で選び、抵抗値そのものは電流と出力抵抗のバランスで選び、負荷効果を考慮して、結果をテスターでキャリブレーションすれば、信頼できる測定値が得られます。アナログ読み取りの背景はADCとは?で読めます。BlueGraysアプリには、LDRで光の強さを測る、LDRで作る常夜灯、LCD付きのデジタル電圧計、NTCで温度を測る、ESP32とHC-SR04で作る距離計などのプロジェクトがあり、どれも回路図とコード付きで、ステップごとに解説しています。

よくある質問

分圧回路の公式は?

出力電圧はVout = Vin × R2 / (R1 + R2)で、R1は電源側、R2はグラウンド側の抵抗です。たとえば9 Vを10 kΩと10 kΩで分けると4.5 Vになります。この公式が正確に成り立つのは、出力から電流を取り出さない場合だけです。

分圧回路で12 Vから5 Vを作れますか?

測定や信号用ならできます。22 kΩと10 kΩで12 Vを3.75 Vに下げ、Arduinoのアナログ入力で読み取れます。ボードやモジュールに電源を供給する用途ではできません。負荷が電流を流した途端に、出力が落ち込みます。電源には、7805のようなレギュレーターや、LM2596のような降圧コンバーターを使ってください。

5 Vを3.3 Vに変換するにはどの抵抗が必要ですか?

もっとも一般的な組み合わせは信号側1 kΩ、グラウンド側2 kΩで、5 Vを3.33 Vにします。10 kΩと20 kΩでも同じ比になりますが、高速な信号には小さい値のほうが適しています。2 kΩがなければ、2.2 kΩと3.3 kΩで3.0 Vになり、ESP32とPicoはこれでもHIGHと読み取ります。

分圧回路の抵抗値はどう選べばいいですか?

まず最大入力電圧とピンの上限から比を決め、次にR2(通常は10 kΩ)を選んでR1を計算します。合計抵抗が小さいと分圧回路が電流を無駄にし、大きすぎると負荷効果とADCの誤差が大きくなります。Arduinoでは出力抵抗を10 kΩ未満に、電池のプロジェクトでは合計を100 kΩ前後にすると、バランスが良くなります。

Arduinoで12 Vを測るには?

バッテリーのプラス端子を22 kΩを通してA0に、A0を10 kΩを通してGNDに、バッテリーのマイナス端子をArduinoのGNDにつなぎます。コードでは、analogRead()の値に5 / 1024を掛けてピンの電圧を求め、さらに3.2を掛けてバッテリーの電圧を求めます。この分圧回路なら、16 Vまで安全に測れます。

分圧回路は電池を消耗させますか?

はい。分圧回路には常にI = Vin / (R1 + R2)の電流が流れます。32 kΩの分圧回路は12 Vで0.375 mA、1日で約9 mAhを消費します。車のバッテリーなら問題になりませんが、小さな電池では無視できません。電池のプロジェクトでは、100 kΩ前後の抵抗とアナログピンの100 nFのコンデンサを使うか、分圧回路を機器のスイッチの後ろにつないでください。

全プロジェクトを見る
LDRで光の強さを測定
#11初級

LDRで光の強さを測定

部屋の明るさを数値で見てみませんか?光に反応する小さな部品、LDRで周囲の光を測定し、Arduinoが0.5秒ごとにその値をコンピューターの画面に表示します。手で覆うと数値が変わる様子を確認できます。自動で点灯する常夜灯などのプロジェクトへの第一歩です。

4.6(81)
139
LDRで作る常夜灯
#12初級

LDRで作る常夜灯

暗くなると自動で点灯し、朝になると消灯する小さな常夜灯です。光センサーが部屋の明るさを測定し、Arduinoが十分に暗くなったらLEDを点灯させ、明るくなったら消灯させます。街灯が夕方になると自動で点灯する仕組みも理解できます。

4.8(102)
205
ESP32とLDRモジュールで光の強さを読み取る
#113初級

ESP32とLDRモジュールで光の強さを読み取る

LDRモジュールの生のADC値と、暗い状態・明るい状態の基準値から計算した相対的な明るさの割合を、シリアルモニタでリアルタイムに確認します。この割合はルクスの測定値ではありません。モジュールの校正の仕組みを学べます。しきい値の決定に使うため、プロジェクト10の前に取り組むのが適しています。

4.6(36)
55
LCDディスプレイ付きデジタル電圧計
#56中級
プレミアム

LCDディスプレイ付きデジタル電圧計

自作の測定器で、電池や電源アダプターが出力する電圧を調べます。2つの抵抗で作る分圧回路が、高い電圧をボードで読み取れるレベルまで下げます。Arduinoが元の電圧を計算し、2行のLCDディスプレイにボルト単位で表示します。この回路では約55ボルトまでの直流電圧を測定できます。コンセントの商用電源には絶対に接続しないでください。

4.5(27)
36
NTCと2x16 LCDディスプレイで温度を測定
#44初級
プレミアム

NTCと2x16 LCDディスプレイで温度を測定

小さなビーズのようなセンサーで周囲の温度を測ります。NTCというこの部品は、温まるほど電気が流れやすくなります。Arduinoがその変化を読み取り、数式で摂氏温度に変換して、2行のLCDディスプレイに0.5秒ごとに表示します。手のひらでセンサーを温めて、数値が上がる様子を見るのも楽しみの1つです。

4.5(33)
44
ESP32とLDRで作るナイトライト
#112初級
プレミアム

ESP32とLDRで作るナイトライト

暗くなるとLEDが自動で点灯し、明るくなると消灯するナイトライトです。LDRセンサーモジュールのD0(デジタル出力)ピンを使います。モジュール上の小さな可変抵抗で暗さのしきい値を設定すると、モジュール自体がHIGH/LOWを出力します。ESP32はdigitalRead()でこの信号を読み取るだけなので、コードはとてもシンプルです。

4.6(17)
30
ESP32とHC-SR04で作る超音波距離計
#116中級

ESP32とHC-SR04で作る超音波距離計

HC-SR04超音波センサーは、発した音波が物体に反射して戻るまでの時間(Time of Flight)を測定して距離を計算します。このプロジェクトでは、ESP32からセンサーのTRIGピンに10マイクロ秒のパルスを送り、ECHOピンからの反射波の持続時間をpulseIn()で読み取ります。計算した距離をcm単位で16x2 I2C LCDに表示します。HC-SR04は5Vで動作するため、ECHOピンには分圧回路が必須です。分圧しないとESP32の3.3V GPIOが破損します。

4.9(28)
45
ESP32と可変抵抗でLEDの明るさを制御(アナログ→PWM)
#115中級
プレミアム

ESP32と可変抵抗でLEDの明るさを制御(アナログ→PWM)

可変抵抗を使ってLEDの明るさをアナログ操作で調整します。ESP32のADCピンで可変抵抗からの0-3.3Vの電圧を読み取り、PWM(パルス幅変調)信号に変換してLEDに出力します。可変抵抗を回すと、LEDが徐々に明るくなったり暗くなったりします。Arduino Core 3.0+ではanalogWrite()を直接使えます。ESP32-S2/S3ではADCの分解能を12ビットに固定します。

4.5(19)
32