基礎 · 読了まで21分

オペアンプとは?ゲインの式、LM358、Arduinoの回路

オペアンプとは何か、どう動くのかを解説します。反転・非反転増幅回路のゲインの式、バッファ、コンパレーター、LM358とLM741のピン配置、単電源での使い方、ArduinoのADCへの合わせ方まで紹介します。

オペアンプ(演算増幅器)は、2つの入力の間のごくわずかな電圧差を数十万倍に増幅する小さな集積回路で、多くは8ピンです。これがオペアンプとは何かという問いへの短い答えですが、これほど大きなゲインは、それだけではあまり役に立ちません。真価を発揮するのは、いくつかの抵抗で出力の一部を入力に戻したときです。するとオペアンプは、抵抗の比でゲインが決まる高精度の増幅回路にも、バッファにも、コンパレーターにも、フィルタにもなります。マイクのプリアンプから脈拍センサーまで、はかりのモジュールからサウンドカードまで、アナログ電子回路のほぼあらゆる場所にオペアンプが使われています。

Arduinoでオペアンプが必要になる一番の理由はこうです。多くのセンサーの信号はミリボルト単位ですが、Arduino UnoのADCが区別できるのは4.88 mV刻みまでです。K型熱電対は100 °Cでわずか4.1 mVしか出しません。直接つなぐと、Arduinoはこの温度変化をほとんど感知できません。このガイドでは、理想オペアンプのルール、反転・非反転増幅回路のゲインの式、ボルテージフォロワ、コンパレーター、LM358とLM741のピン配置、単電源での使い方、そしてマイクや熱電対の信号をArduino、ESP32、Raspberry Pi PicoのADCに合わせる方法を、すべて実際の値で解説します。

オペアンプとは?どのように動くのか

オペアンプには5つの基本的な端子があります。非反転入力(+)、反転入力(−)、出力、そして2本の電源ピン(V+とV−)です。オペアンプは2つの入力の差だけを見て、それを開ループゲイン(A)倍にします。Vout = A × (V+ − V−)。LM358では、Aは標準で100,000(100 dB)です。つまり入力間にわずか0.1 mVの差があるだけで、出力には10 Vが求められます。しかし出力は電源電圧を超えられないため、帰還のないオペアンプの出力はほとんどの場合どちらかの電源レールに張り付きます。これを飽和といいます。この性質はコンパレーター回路で役立ちます。増幅回路を作るには、出力の一部を抵抗を通して反転入力に戻します。これを負帰還といい、そうするとゲインはオペアンプではなく抵抗で決まるようになります。

特性理想オペアンプLM358(標準値)LM741(標準値)
開ループゲイン無限大100,000(100 dB)200,000(106 dB)
入力(バイアス)電流020 nA80 nA
入力オフセット電圧03 mV(最大7 mV)1 mV(最大5 mV)
利得帯域幅積(GBW)無限大0.7 MHz約1 MHz
スルーレート無限大0.3 V/µs0.5 V/µs
出力振幅電源電圧いっぱいまで下側は0 V近くまで、上側はV+ − 1.5 Vまで各電源レールから1〜3 V内側まで
電源制限なし単電源3〜30 Vまたは±1.5〜±15 V±10〜±18 Vを推奨(LM741C)

理想オペアンプのルール:イマジナリーショートと入力電流ゼロ

  • ルール1:入力には電流が流れ込まない。理想オペアンプの入力抵抗は無限大なので、+ピンにも−ピンにも電流は流れ込みません。実際のLM358では約20 nAが流れますが、100 kΩの抵抗を通しても誤差はわずか2 mVです。
  • ルール2:イマジナリーショート(仮想短絡)。負帰還があると、出力は2つの入力を同じ電圧にするためにどんな値にでも変化するので、V+ = V−になります。入力どうしはつながっていませんが、同じ電圧になります。
  • 実用上のルール:出力は電源電圧を超えられない。式が12 Vを求めても、5 Vで動かしているオペアンプの出力は電源電圧までしか上がらず、LM358なら約3.5 Vまでです。出力がこの限界に張り付いた状態をクリッピングまたは飽和といいます。

このルールを使えば、ほとんどのオペアンプ回路は紙の上で数行で解けます。まず+入力の電圧を求め、−入力も同じ電圧だと考えます。次にオームの法則で各抵抗を流れる電流を書きます。電流は入力に流れ込めないので帰還抵抗を流れるしかなく、そこから出力電圧が求まります。注意点として、2つ目のルールが成り立つのは負帰還があるときだけです。コンパレーターのような帰還のない回路では、2つの入力は違う電圧になり、出力はどちらかの電源レールに張り付きます。電流と電圧の計算を復習したい場合は、オームの法則のガイドを参照してください。

非反転増幅回路:ゲインの式と計算例

非反転増幅回路では、信号を直接+入力に入れます。帰還抵抗(Rf)を出力から−入力へ、グラウンド側の抵抗(Rg)を−入力からGNDへつなぎます。この2本の抵抗は分圧回路になっていて、−入力の電圧はVout × Rg / (Rf + Rg)です。イマジナリーショートのルールにより、これが入力電圧と等しくなるので、Vout = Vin × (1 + Rf / Rg)という式が得られます。Rf = 10 kΩ、Rg = 1 kΩならゲインは11で、100 mVの信号は1.1 Vになります。出力は入力と同じ向きに変化し、ゲインが1を下回ることはなく、回路の入力抵抗がとても高いのでセンサーに負荷をかけません。

RfRg(反転増幅回路ではRin)非反転ゲイン反転ゲイン
10 kΩ10 kΩ2(6.0 dB)−1(0 dB)
47 kΩ10 kΩ5.7(15.1 dB)−4.7(13.4 dB)
10 kΩ1 kΩ11(20.8 dB)−10(20 dB)
100 kΩ4.7 kΩ22.3(27.0 dB)−21.3(26.6 dB)
100 kΩ1 kΩ101(40.1 dB)−100(40 dB)
手持ちの抵抗値でのゲイン、そのdB値、出力電圧はオペアンプ計算ツールで計算できます。出力が電源電圧の限界に達してクリッピングする場合は、事前に警告も表示されます。計算した値に最も近い実在の抵抗を探すには、抵抗の標準値ツールを使ってください。

反転増幅回路と仮想グラウンド

反転増幅回路では、+入力をGNDにつなぎ、信号は抵抗Rinを通って−入力に入ります。Rfは、ここでも出力と−入力の間に入れます。イマジナリーショートのルールにより−入力も0 Vになりますが、GNDにはつながっていません。これを仮想グラウンドといいます。Rinを流れる電流Vin / Rinは入力に流れ込めないのでRfを流れるしかなく、出力はVout = −(Rf / Rin) × Vinになります。Rin = 10 kΩ、Rf = 47 kΩならゲインは−4.7で、0.5 Vの入力から−2.35 Vの出力が得られます。マイナス記号は信号が反転することを表します。回路の入力抵抗はおよそRinなので、内部抵抗の高いセンサーには負荷になることがあります。

反転構成のうまい使い方に加算増幅回路(ミキサー)があります。複数の信号をそれぞれ専用の抵抗を通して−入力につなぐと、出力はそれらの信号の重み付き和を反転したものになります。ただし、単電源のArduino回路では、反転増幅回路の+入力をGNDではなく、電源電圧の半分などの基準電圧につなぐ必要があります。そうしないと、正の入力に対して負の出力が求められ、出力は0 Vに張り付いてしまいます。この場合の式はVout = Vref − (Rf / Rin) × (Vin − Vref)になります。

ボルテージフォロワ(バッファ):ゲイン1の最も便利な回路

出力を直接−入力につなぎ、信号を+入力に入れると、ボルテージフォロワ(バッファ)になります。Rfがゼロ、Rgが無限大なので、ゲインはちょうど1で、Vout = Vinです。増幅しない回路がなぜ役に立つのでしょうか。入力からはほとんど電流を取らないのに、出力からはミリアンペア単位の電流を流せるからです。つまり、高インピーダンスの信号源を低インピーダンスの信号源に変えます。ATmega328Pのデータシートには、ADCは信号源インピーダンスが10 kΩ以下のときに最もよく動作すると書かれています。100 kΩ + 100 kΩの分圧回路は50 kΩの信号源として振る舞うため、Arduinoがチャンネルを切り替えると読み取り値が数ステップずれることがあります。分圧回路の後にフォロワを入れれば、この問題は解消します。

フォロワのほかの定番の使い方としては、PWM信号をRCフィルタで平滑化してバッファし簡単なDACを作る、ポテンショメーターで作った基準電圧を複数の回路で共有する、弱いセンサー出力の代わりにオペアンプの出力で長いケーブルを駆動する、などがあります。単電源のLM358は0 Vまで追従できますが、5 V電源では約3.5 Vより上には出られません。0〜5 Vの全範囲をバッファしたい場合は、レールツーレールのオペアンプを選んでください。

コンパレーターとしてのオペアンプ

帰還をかけずに使うと、オペアンプは2つの電圧を比べるスイッチになります。+入力が−入力よりほんの数ミリボルトでも高ければ出力は上限に、低ければ0 Vになります。マイコンを使わない常夜灯がよい例です。5V、10 kΩ、LDR、GNDの順に組んだ分圧回路の中点を+入力に、ポテンショメーターのワイパーを−入力につなぎます。暗くなるとLDRの抵抗が上がり、中点の電圧がポテンショメーターで設定したしきい値を超え、出力に330 Ωを通してつないだLEDが点灯します。この用途ならLM358でも十分ですが、動作は遅めです。スルーレートが0.3 V/µsなので、出力が0から3.5 Vまで上がるのに10 µs以上かかります。

高速できれいな切り替えが必要な用途には、LM393のような本物のコンパレーターを使います。LM393のピン配置はLM358と同じですが、出力はオープンコレクタです。出力をGNDに引き下げることしかできないため、HIGHにするには出力と電源の間に10 kΩなどのプルアップ抵抗が必要です。このおかげで、プルアップ先を3.3 Vにすれば、5 Vで動かしているコンパレーターの出力を安全にESP32やPicoに入力できます。KY-038サウンドセンサーや、土壌水分・雨・炎・ガスの各モジュールで青い半固定抵抗の隣にある小さなチップは、ほぼ必ずLM393です。

LM393コンパレーターを搭載したKY-038サウンドセンサーモジュール
KY-038サウンドセンサー:マイクの信号を基板上のLM393コンパレーターが半固定抵抗で設定したしきい値と比較し、デジタル出力に変えます。

変化がゆっくりな信号やノイズの多い信号がしきい値付近にあると、コンパレーターの出力は1秒間に何百回もばたつくことがあり、常夜灯は夕暮れどきにちらつきます。対策はヒステリシス、つまりシュミットトリガです。信号を10 kΩの抵抗R1を通して+入力に入れ、出力から+入力へ1 MΩの抵抗R2をつなぎます。出力が切り替わるたびに、この正帰還がしきい値を少しずらします。立ち上がり側と立ち下がり側のしきい値の差はおよそ出力振幅 × R1 / R2です。出力が0〜5 Vで振れるなら、5 × 10k / 1Mで50 mVのヒステリシスになり、たいていはこれでノイズを吸収できます。同じ考え方は、2つのしきい値を使ってソフトウェアでも実現できます。後で紹介するESP32の例がまさにそれです。

LM393はオペアンプではありません。内部に位相補償がないため、負帰還をかけた増幅回路では発振し、プルアップ抵抗がなければ出力はHIGHになりません。逆にオペアンプはコンパレーターとして使えますが、速い信号には遅すぎます。まとめると、増幅にはオペアンプを、しきい値の検出にはコンパレーターを選びましょう。

LM358とLM741のピン配置

電子工作で最もよく見かけるオペアンプは、2回路入りのLM358と、昔ながらの1回路入りのLM741です。どちらも8ピンのDIPパッケージです。刻印が読める向きで、切り欠きを左にしてチップを持つと、1番ピンは左下にあり、番号は反時計回りに増えていきます。ピン配置が異なるので、一方をもう一方の代わりにそのまま差し替えることはできません。

ピンLM358(2回路入りオペアンプ)LM741(1回路入りオペアンプ)
11OUT:出力Aオフセット調整(Offset null)
21IN−:反転入力A反転入力(−)
31IN+:非反転入力A非反転入力(+)
4GND(V−)V−(負電源)
52IN+:非反転入力Bオフセット調整(Offset null)
62IN−:反転入力B出力
72OUT:出力BV+(正電源)
8VCC(V+)NC(未接続)
特性LM358LM741MCP6002
回路数212
電源単電源3〜30 V両電源±10〜±18 Vを推奨単電源1.8〜6 V
5 V単電源で動作する実質的に動作しない動作する
3.3 Vで不向き(出力は最大約1.8 V)動作しないとてもよい
入力範囲0 VからV+ − 1.5 Vまで電源レールから約3 V内側電源レールの0.3 V外側まで
出力範囲(5 V時)約0.02〜3.5 V使えない0.025〜4.975 V(レールツーレール)
GBW/スルーレート0.7 MHz/0.3 V/µs約1 MHz/0.5 V/µs1 MHz/0.6 V/µs
消費電流1回路あたり0.35 mA1.7 mA1回路あたり0.1 mA

LM741は1968年から教科書の主役ですが、±15 Vのような正負対称の電源向けに設計されています。入力は電源レールから約3 V、出力は1〜3 V内側にとどまる必要があります。5 V単電源では、この余裕分を差し引くと使える範囲が残りません。LM741の回路をArduinoの5Vピンから給電して動かない場合、原因はこれです。一方、LM358は単電源で使うことを前提に設計されています。入力範囲に0 Vを含み、出力は0 Vの数ミリボルト手前まで下がり、唯一の欠点は上限がV+ − 1.5 Vで頭打ちになることです。ESP32やPicoのような3.3 Vのボードでは、MCP6002のようなレールツーレールのオペアンプを使ってください。ピン配置はLM358と同じなので、そのまま回路に差し替えられます。4回路必要な場合は、14ピンのLM324がLM358の4回路版にあたります。

チップを逆向きに挿したり電源ピンを取り違えたりすると、オペアンプは発熱し、数秒で壊れます。挿す前に切り欠きの向きを確認し、LM358では8 = VCC、4 = GND、LM741では7 = V+、4 = V−であることを覚えておきましょう。どのオペアンプでも、電源ピンの間にできるだけチップの近くで100 nFのセラミックコンデンサを入れてください。

単電源での使い方:仮想グラウンドとレールツーレール

教科書のオペアンプ回路の多くは±15 Vのような正負対称の電源を使い、信号は0 Vを中心に上下に振れます。Arduinoの世界では、たいてい5 Vか3.3 Vしかありません。熱電対、シャント抵抗、LM35のように常に正の値をとる直流信号なら問題ありません。入力範囲に0 Vを含むオペアンプで、そのまま増幅できます。しかし、マイクのように正負に振れる交流信号は、まず電源電圧の中央まで持ち上げる必要があります。そのために2本の抵抗で中点電圧を作り、ノイズを減らすために10 µFのコンデンサを横に追加します。この点を仮想グラウンドまたは基準電圧と呼び、信号はカップリングコンデンサを通してこの電圧に重ねます。

  • 適切なオペアンプを選ぶ:LM741やTL072のように入力範囲に0 Vを含まないモデルは、単電源では思わぬところでクリッピングします。LM358、LM324、MCP6002を使ってください。
  • 出力の限界を考慮する:5 VでのLM358の出力は約0.02〜3.5 Vなので、交流信号の中点は2.5 Vより1.8 V前後のほうがバランスがとれます。MCP6002は両方の電源レールの約25 mV手前まで振れるので、中点をちょうどVCC/2にできます。
  • オペアンプはボードと同じ電圧で動かす:12 Vで動かしたオペアンプは、ゲインを間違えるとESP32やPicoのピンに10 V以上を加えてしまうことがあります。
  • GNDを共通にする:センサー、オペアンプ、ボードのグラウンドはつながっている必要があります。理由は共通GNDのガイドで解説しています。
  • 使わないチャンネルを浮かせたままにしない:LM358の余った片側はフォロワとして配線し(出力を−入力へ)、+入力をGNDか中点につなぎます。浮いた入力は発振や無駄な電流消費の原因になります。

マイクの信号を増幅する:エレクトレットコンデンサーマイクのプリアンプ

エレクトレットコンデンサーマイクの感度は一般に−44 dBV/Pa前後で、94 dBという大きな音圧でも約6 mVしか出力しません。1 m離れた場所での普通の話し声は0.1 mV程度にとどまり、マイクのすぐ横で手をたたいても数十ミリボルトです。Arduinoの4.88 mV刻みでは、この信号はまったく現れないか、数ステップ動くだけです。KY-038サウンドセンサーのようなモジュールのアナログ出力がとても弱いのも、これで説明がつきます。解決策は、ゲイン約100の非反転交流増幅回路です。次の回路ではLM358のAチャンネルを使います。

部品値接続
マイクのバイアス抵抗2.2 kΩ5Vとマイクの+端子の間(マイクの−端子はGNDへ)
カップリングコンデンサC11 µFマイクの+端子からLM358の3番ピン(1IN+)へ
中点用の抵抗100 kΩと56 kΩ3番ピンから5Vへ100 kΩ、3番ピンからGNDへ56 kΩ(約1.8 V)
帰還抵抗Rf100 kΩ1番ピン(1OUT)と2番ピン(1IN−)の間
RgとC21 kΩ + 10 µF2番ピンからGNDへ直列に(C2の−端子をGNDへ)
電源8番ピンと4番ピン8番ピンを5Vへ、4番ピンをGNDへ、その間に100 nF
出力1番ピンArduino UnoのA0(ESP32はGPIO 34、PicoはGP26:MCP6002を使い3.3 Vで)

コンデンサC2のおかげで、この回路は直流に対してはゲイン1のフォロワになり、無音時の出力は中点の約1.8 Vで落ち着きます。一方、音声周波数ではC2がショートのように働き、ゲインは1 + 100k / 1k = 101(40 dB)になります。下側のカットオフ周波数はRgとC2で決まり、1 / (2π × 1 kΩ × 10 µF) ≈ 16 Hzです。上限はオペアンプの利得帯域幅積で決まり、LM358では0.7 MHz / 101 ≈ 7 kHzです。話し声にはこれで十分です。ゲインを上げたい場合は、帯域幅が同じ割合で狭くなることを忘れないでください。1000のゲインが必要なら、約32ずつの2段に分けるほうが適しています。

C++ (Arduino IDE)
1// LM358 mikrofon ön yükselteci ile ses seviyesi / Sound level with an LM358 mic preamp
2const int MIC_PIN = A0;                // LM358 pin 1 (1OUT)
3const float GAIN = 101.0;              // 1 + 100k / 1k
4const unsigned long WINDOW_MS = 50;    // ölçüm penceresi / sampling window
5
6void setup() {
7  Serial.begin(115200);
8}
9
10void loop() {
11  int minV = 1023, maxV = 0;
12  unsigned long start = millis();
13  while (millis() - start < WINDOW_MS) {   // 50 ms boyunca örnekle / sample for 50 ms
14    int v = analogRead(MIC_PIN);
15    if (v < minV) minV = v;
16    if (v > maxV) maxV = v;
17  }
18  float ppVolt = (maxV - minV) * 5.0 / 1023.0;   // tepe-tepe çıkış / peak-to-peak output
19  float micMv = ppVolt * 1000.0 / GAIN;          // mikrofonun kendi sinyali / the mic's own signal
20
21  Serial.print("Çıkış / output: ");
22  Serial.print(ppVolt, 3);
23  Serial.print(" V p-p   Mikrofon / mic: ");
24  Serial.print(micMv, 2);
25  Serial.println(" mV p-p");
26}

このコードは50 msの間にできるだけ多くのサンプルを取り、最小値と最大値を求めて、その差を電圧に換算します。これが音のピークツーピーク振幅です。結果を101で割ると、マイク自体が出している電圧がわかります。静かな部屋では出力はADCで数ステップ(0.01〜0.02 V)しか動きませんが、近くで手をたたくと簡単に1 Vを超えます。信号がクリッピングする、つまり出力が0 Vや3.5 Vに達する場合は、Rfを47 kΩに下げてください。測定値をもっと安定させる方法はセンサーデータのフィルタリングのガイドで紹介しています。

熱電対を増幅する:K型熱電対とLM358

K型熱電対は、異なる2種類の金属が接する接点の温度差に比例した小さな電圧、約41 µV/°Cを出力します。100 °Cで4.1 mV、500 °Cで20.6 mV、1000 °Cで41.3 mVです。Arduinoに直接つなぐと、ADCの1ステップ(4.88 mV)はおよそ119 °Cに相当し、これでは測定になりません。LM358のBチャンネルでゲイン101の非反転増幅回路を組むと、信号は4.14 mV/°Cになります。これで1ステップは約1.2 °Cになり、LM358の出力上限3.5 Vなら、オフセットにもよりますが約700〜800 °Cまで読み取れます。配線は次のとおりです。熱電対の+端子を5番ピン(2IN+)へ、−端子をGNDへ。Rf = 100 kΩを7番ピンと6番ピンの間に、Rg = 1 kΩを6番ピンとGNDの間に入れます。7番ピンはArduinoのA1へつなぎます。K型では−端子であるアルメル線がわずかに磁性をもつので、端子を見分けるのに便利です。

熱電対が実際に測っているのは、温接点と、熱電対の線が銅の接続部とつながる冷接点との温度差です。実際の温度を得るには冷接点の温度を別に測って足す必要があり、これを冷接点補償といいます。次のコードでは、そのために接続端子のすぐ横に置いたLM35を使います(出力はA2へ)。さらに、LM358の3〜7 mVの入力オフセットも101倍され、出力で0.3〜0.7 V、つまり70〜170 °Cの誤差になります。コードは起動時にこのオフセットを測り、その後の読み取り値から差し引くので、プローブが室温のときにボードの電源を入れてください。

C++ (Arduino IDE)
1// K tipi termokupl + LM358 (kazanç 101) + LM35 soğuk uç / K-type thermocouple + LM358 (gain 101) + LM35 cold junction
2const int TC_PIN = A1;           // LM358 pin 7 (2OUT)
3const int LM35_PIN = A2;         // LM35 çıkışı / LM35 output
4const float GAIN = 101.0;        // 1 + 100k / 1k
5const float MV_PER_C = 0.041;    // K tipi: yaklaşık 41 µV/°C / K-type: about 41 µV/°C
6float zeroMv = 0;                // açılışta ölçülen ofset / offset measured at power-up
7
8float readMv(int pin) {
9  long sum = 0;
10  for (int i = 0; i < 64; i++) sum += analogRead(pin);   // 64 okumanın ortalaması / average of 64 readings
11  return sum / 64.0 * 5000.0 / 1023.0;
12}
13
14void setup() {
15  Serial.begin(115200);
16  delay(500);
17  zeroMv = readMv(TC_PIN);       // prob oda sıcaklığında olmalı / probe must be at room temperature
18  Serial.print("Ofset / offset: ");
19  Serial.print(zeroMv, 1);
20  Serial.println(" mV");
21}
22
23void loop() {
24  float coldC = readMv(LM35_PIN) / 10.0;           // LM35: 10 mV/°C
25  float tcMv = (readMv(TC_PIN) - zeroMv) / GAIN;   // termokupl gerilimi / thermocouple voltage
26  float hotC = coldC + tcMv / MV_PER_C;            // soğuk uç telafisi / cold-junction compensation
27
28  Serial.print("Ortam / ambient: ");
29  Serial.print(coldC, 1);
30  Serial.print(" °C   Prob / probe: ");
31  Serial.print(hotC, 1);
32  Serial.println(" °C");
33  delay(500);
34}
オフセットが負の場合、出力は0 Vに張り付き、熱電対の電圧がそのオフセットを上回るまで回路は何も示しません。起動時にA1からゼロにとても近いオフセットが読み取れたら、この状態です。LM358のオフセットは温度によってもずれ、41 µV/°Cという近似は0〜500 °Cの範囲でも数度以内の精度しかありません。オーブン、3Dプリンター、熱処理のように精度が必要な用途では、冷接点補償とデジタル出力を備えたMAX6675やMAX31855のモジュール、または高精度のゼロドリフト・オペアンプを使ってください。

ArduinoのADCに合わせる:信号を適切な範囲に収める

Arduinoのプロジェクトでのオペアンプの本当の役割は、センサーの信号を、ADCが最も効率よく使える範囲に移すことです。ルールは簡単です。信号の最大値はADCの範囲の上端に近づけますが、オペアンプやADCが直線的でなくなる両端にははみ出さないようにします。たとえばLM35は0〜50 °Cで0〜500 mVを出力します。Unoで直接読むと、分解能は1ステップあたり0.49 °Cです。同じ信号をゲイン6.6で0〜3.3 Vに増幅すると、分解能は0.074 °Cまで細かくなります。設計の手順は次のとおりです。

  1. センサーの出力範囲を調べる:データシートから出力電圧の最小値と最大値を確認します(LM35、0〜50 °C:0〜0.5 V)。
  2. 目標の範囲を決める:安全な範囲は、LM358を使ったUnoで約0.02〜3.5 V、ESP32で0.15〜2.5 V、MCP6002を使ったPicoで0.03〜3.25 Vです。
  3. ゲインを計算する:G = 目標の最大値 / センサーの最大値 = 3.3 / 0.5 = 6.6です。非反転増幅回路で1 + Rf / Rg = 6.6にするには、Rf = 56 kΩ、Rg = 10 kΩを選びます。
  4. オフセットを取り除く:センサーが1〜2 Vのようにゼロから始まらない範囲で動く場合は、まず基準電圧を差し引いてから(反転増幅回路のVrefや差動増幅回路を使います)増幅します。
  5. 保護とフィルタ:オペアンプの出力とADCピンの間に1 kΩの直列抵抗を、ピンとGNDの間に100 nFを入れます。このRCフィルタは約1.6 kHz以上のノイズを抑え、ピンに流れ込む異常電流も制限します。
  6. ソフトウェアで逆算する:測定した電圧をゲインで割ると、センサーの実際の電圧が得られます(Vsensor = Vadc / G)。ゲインを正確に求めるために、抵抗の値をテスターで測っておきましょう。
ボードADC推奨入力範囲1ステップアナログピン
Arduino Uno10ビット0〜5 V(内部基準電圧使用時は0〜1.1 V)4.88 mV(1.07 mV)A0〜A5
ESP3212ビット約0.15〜2.5 V(デフォルトの11 dB減衰)約0.8 mVGPIO 32〜39(ADC1、Wi-Fiオン時も使用可能)
Raspberry Pi Pico12ビット0〜3.3 V0.81 mVGP26、GP27、GP28
Unoでとても小さな信号を扱うなら、analogReference(INTERNAL)でADCの基準電圧を1.1 Vに下げ、1ステップを1.07 mVまで小さくできます。これで、オペアンプの増幅段がまったく要らなくなる場合もあります。ただしこのモードでは、1.1 Vを超える入力で読み取り値が飽和します。ADCの詳細はADCとアナログ-デジタル変換のガイドを参照してください。

ESP32でオペアンプの出力を読む:拍手スイッチ

ESP32は3.3 Vで動くので、同じマイク回路をMCP6002で組み、3V3ピンから給電します。中点には100 kΩの抵抗を2本使います(1.65 V)。LM358を5 Vで動かすと出力が3.5 Vに達し、ESP32のピンに負担をかけることがあります。オペアンプの出力は、Wi-Fiがオンのときも使えるADC1チャンネルの1つ、GPIO 34につなぎます。次のコードは20 msごとの区間でピークツーピーク振幅を測り、analogReadMilliVolts()で補正済みのミリボルト値を使い、2つのしきい値でソフトウェア的にヒステリシスをかけます。手をたたくたびに、ボード上のLEDが切り替わります。初めてこのボードを使う場合は、ESP32とは?のガイドのセットアップ手順から始めてください。

C++ (Arduino IDE)
1// ESP32: MCP6002 mikrofon yükselteci ile el çırpma anahtarı / ESP32: clap switch with an MCP6002 mic preamp
2const int MIC_PIN = 34;      // MCP6002 çıkışı, ADC1 kanalı / MCP6002 output, ADC1 channel
3const int LED_PIN = 2;       // dahili LED / onboard LED
4const int ON_MV = 800;       // üst eşik, mV tepe-tepe / upper threshold, mV peak-to-peak
5const int OFF_MV = 300;      // alt eşik: histerezis / lower threshold: hysteresis
6
7bool loud = false;
8bool ledOn = false;
9
10void setup() {
11  Serial.begin(115200);
12  pinMode(LED_PIN, OUTPUT);
13}
14
15void loop() {
16  int minMv = 3300, maxMv = 0;
17  unsigned long start = millis();
18  while (millis() - start < 20) {                // 20 ms pencere / 20 ms window
19    int mv = analogReadMilliVolts(MIC_PIN);      // kalibre edilmiş mV / calibrated mV
20    if (mv < minMv) minMv = mv;
21    if (mv > maxMv) maxMv = mv;
22  }
23  int pp = maxMv - minMv;
24
25  if (!loud && pp > ON_MV) {                     // üst eşik aşıldı: alkış / upper threshold crossed: a clap
26    loud = true;
27    ledOn = !ledOn;
28    digitalWrite(LED_PIN, ledOn ? HIGH : LOW);
29    Serial.printf("Alkış / clap: %d mV p-p\n", pp);
30    delay(250);                                  // yankıları yok say / ignore echoes
31  } else if (loud && pp < OFF_MV) {              // ses alt eşiğin altına indi / sound fell below the lower threshold
32    loud = false;
33  }
34}

Raspberry Pi PicoとMicroPython:シャント抵抗で電流を測る

オペアンプのもう1つの実用的な用途が電流の測定です。モーターやLEDテープのマイナス側とGNDの間に0.1 Ωのシャント抵抗を入れると、1 Aの電流でもその両端の電圧降下はわずか100 mVです。MCP6002で組んだ非反転増幅回路(Rf = 100 kΩ、Rg = 4.7 kΩ)はこの電圧を22.3倍にします。これで1 Aが2.23 Vになり、Picoの3.3 Vの範囲なら約1.45 Aまで測れます。シャントの上側をMCP6002の3番ピンに、オペアンプの出力(1番ピン)をPicoのGP26(ADC0)ピンにつなぎます。オペアンプは3V3(OUT)ピンから給電し、負荷用電源のGNDはPicoのGNDとつなぎます。1.5 Aではシャントの消費電力が0.225 Wになるので、定格0.5 W以上の抵抗を使ってください。

MicroPython
1# Pico: 0,1 Ω şönt + MCP6002 (kazanç 22,3) ile akım ölçümü / current sensing with a 0.1 Ω shunt + MCP6002 (gain 22.3)
2from machine import ADC
3import time
4
5adc = ADC(26)                 # GP26 = ADC0, MCP6002 pin 1
6VREF = 3.3
7GAIN = 1 + 100000 / 4700      # Rf = 100k, Rg = 4.7k -> 22.3
8SHUNT = 0.1                   # şönt direnci, ohm / shunt resistance, ohms
9
10def read_volts(n=100):
11    total = 0
12    for _ in range(n):        # 100 okumanın ortalaması / average of 100 readings
13        total += adc.read_u16()
14    return total / n * VREF / 65535
15
16zero = read_volts()           # yük kapalıyken ofset / offset with the load off
17print("Sıfır / zero: {:.3f} V".format(zero))
18
19while True:
20    v_out = read_volts() - zero
21    amps = v_out / GAIN / SHUNT           # I = V / R
22    print("Akım / current: {:.3f} A".format(max(amps, 0)))
23    time.sleep(0.5)

コードは起動時に負荷をオフにした状態でオペアンプのオフセットを測り、その後の読み取り値から差し引きます。100回の読み取りを平均することで、ADCのノイズを抑えています。もっと大きな電流を測るには、シャントの抵抗値かゲインを下げます。シャントの両端の電圧と消費電力はオームの法則計算ツールで確認しましょう。既製の部品を使いたい場合は、ホール効果を利用したACS712電流センサーなら、負荷を回路から絶縁したまま電流を測れます。初めてPicoをセットアップする場合は、Raspberry Pi Picoとは?のガイドでMicroPythonのインストール方法を解説しています。

そのほかのオペアンプ回路

回路式/動作どこで使う?
加算増幅回路(ミキサー)Vout = −Rf × (V1/R1 + V2/R2 + …)(重み付き和の反転)オーディオミキサー、複数の信号の合成
差動増幅回路Vout = (R2 / R1) × (V2 − V1)(2点間の差)オフセットの除去、2点間の電圧差の測定
計装アンプ1本の抵抗で高いゲインを設定でき、同相信号除去が非常に優れているロードセル、ホイートストンブリッジ、生体信号
積分回路帰還にコンデンサを入れ、出力は入力の時間積分になる三角波発生回路、PI制御
アクティブフィルタ(サレン・キー)抵抗2本とコンデンサ2個による2次フィルタオーディオフィルタ、ADCの前段のエイリアシング防止フィルタ
シュミットトリガ正帰還をかけたコンパレーターで、しきい値が2つあるノイズの多い信号からきれいなデジタル出力を得る

ロードセルのようなブリッジ型センサーでは、2つの出力がどちらも電源電圧の中央付近にあり、その差はわずか数ミリボルトです。こうした用途には専用のチップのほうが便利です。HX711は、最大128倍のゲインをもつアンプと24ビットのADCを内蔵しています。また、脈拍センサーの基板に載っているオペアンプは光センサーの弱い信号を増幅すると同時にフィルタもかけているので、Arduinoは最初からはっきりした脈波を受け取れます。

心拍センサーPulse Sensor
Pulse Sensor:基板上のオペアンプが、指で反射した光のわずかな変化を増幅してフィルタをかけます。安静時の出力は電源電圧の半分付近にあります。

オペアンプを使ったプロジェクトのアイデア

  • 拍手で点くランプ:マイクのプリアンプと、ヒステリシスを組み込んだESP32のコードでリレーモジュールを駆動します。
  • VUメーター:ピークツーピーク振幅を、WS2812BのLEDテープ上で音楽に合わせて伸び縮みするバーに変えます。
  • オーブン用温度計:熱電対の増幅回路で500 °Cまで測り、値をOLEDディスプレイに表示します。
  • コード不要の常夜灯:マイコンを使わず、LDRとLM358のコンパレーターだけで、暗くなると点灯するLEDを作ります。
  • デジタルはかり:HX711でロードセルを読み取り、1グラム単位で量れるキッチンスケールを作ります。
  • モーター電流モニター:ロボットカーのモーター電流をシャント抵抗とオペアンプで測り、モーターが拘束されて電流が上がったら停止させます。

よくある間違いと対処法

症状考えられる原因対処法
出力が常に0 Vか上限に張り付いている帰還がない、または違う入力につないでいる。ゲインが高すぎる。入力が入力範囲の外にあるRfが−入力につながっているか確認し、ゲインを下げ、入力が0〜V+ − 1.5 Vの範囲にあることを確かめる
LM741の回路が5 Vで動かないLM741には正負対称の、より高い電源電圧が必要LM358かMCP6002を使う
出力が3.5 Vより上がらないLM358の出力はV+ − 1.5 Vで頭打ちになるそれに合わせてゲインを決めるか、レールツーレールのオペアンプを使う
読み取り値がノイズでばらつく電源のパスコンがない、配線が長い、ゲインが必要以上に高い電源ピンに100 nF、配線を短く、出力にRCフィルタ、ソフトウェアで平均化
回路が勝手に発振するオペアンプが長いケーブルや大きな容量性負荷を直接駆動している出力に100〜470 Ωの直列抵抗を入れる
コンパレーターの出力がHIGHにならないLM393はオープンコレクタで、プルアップがない出力と電源の間に4.7〜10 kΩをつなぐ
ESP32やPicoのピンが壊れたオペアンプを5 Vや12 Vで動かし、出力が3.3 Vを超えたオペアンプを3.3 Vで動かすか、出力に分圧回路とクランプダイオードを入れる
小さな信号で出力が0 Vに張り付く単電源では、負の入力オフセットによって出力が下側に押し付けられる高精度のオペアンプを使うか、入力に小さなバイアスを加える
オペアンプ回路のトラブルシューティングでは、まずテスターで両方の入力の電圧を測ります。負帰還がかかって正しく動いている増幅回路なら、+入力と−入力の差は数ミリボルト以内です。差が大きい場合はオペアンプが飽和しています。出力はどちらかの電源レールに張り付いていて、原因はゲイン、入力範囲、または帰還の接続不良です。測定方法そのものはテスターの使い方のガイドを参照してください。

オペアンプは、アナログの世界をマイコンが理解できる言葉に変える翻訳者です。2つのルールと2つのゲインの式を覚えれば、マイク、熱電対、シャント抵抗、ブリッジ型センサーのどれから来た信号でも、ADCに適した形にできます。値を試すにはオペアンプ計算ツールを使ってください。BlueGraysアプリでは、LDRで光の強さを測定、LDRで作る常夜灯、デジタル電圧計、NTCで温度を測定、炎センサーやガスセンサーといったアナログのプロジェクトを、回路図とコード付きでステップごとに紹介しています。

よくある質問

オペアンプは何に使うのですか?

オペアンプは、弱い信号の増幅、2つの電圧の比較、信号の加算や減算、フィルタリング、高インピーダンスの信号源のバッファに使います。Arduinoのプロジェクトでは主に、マイク、熱電対、シャント抵抗から得られるミリボルト単位の信号を、ADCが読み取れるレベルまで上げるのに使います。

オペアンプのゲインはどう計算しますか?

非反転増幅回路のゲインは1 + Rf / Rg、反転増幅回路では−Rf / Rinです。たとえばRf = 100 kΩ、Rg = 1 kΩなら、非反転ゲインは101、反転ゲインは−100です。デシベルでの値は20 × log10(ゲイン)で求められます。

LM358とLM741の違いは何ですか?

LM358は1つのパッケージに2回路のオペアンプを内蔵し、3〜30 Vの単電源で動き、入力範囲に0 Vを含むので、Arduinoの5 Vでそのまま使えます。LM741は±15 Vのような正負対称の電源向けに設計された1回路のオペアンプで、5 V単電源では実質的に動作しません。ピン配置も異なります。

オペアンプは5 V単電源で動きますか?

はい、LM358、LM324、MCP6002のような単電源向けに設計されたモデルなら動きます。交流信号では入力を電源電圧の中央まで持ち上げ、出力の限界も考慮する必要があります。LM358の出力は、5 V電源では約3.5 Vまでしか上がりません。

オペアンプとコンパレーターの違いは何ですか?

オペアンプは負帰還をかけても安定するように位相補償を内蔵しており、出力は電流を流し出すことも引き込むこともできます。LM393のようなコンパレーターは帰還なしで高速に切り替わるように設計されていて、多くはプルアップ抵抗が必要なオープンコレクタ出力です。オペアンプは遅いコンパレーターとして使えますが、コンパレーターを増幅回路として使ってはいけません。

レールツーレールのオペアンプとは何ですか?

レールツーレールのオペアンプは、入力または出力が電源電圧の数十ミリボルト手前まで届きます。たとえばMCP6002は5 V電源で0.025〜4.975 Vを出力しますが、LM358は約3.5 Vまでしか上がりません。ESP32やRaspberry Pi Picoのような3.3 Vのボードで、ADCの全範囲を使うにはレールツーレールのオペアンプが必要です。

全プロジェクトを見る
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
炎センサーの使い方
#50中級
プレミアム

炎センサーの使い方

キッチンや作業場で、人より先に火に気づく小さな見張り役です。炎センサーは火が放つ目に見えない光を検出します。異常がないときは緑色のLEDが点灯し、炎を検出すると赤色のLEDが点灯してブザーが鳴ります。このシンプルな回路で火災感知器の基本的な仕組みを学べますが、実際の感知器の代わりにはなりません。

4.6(33)
44
ガスセンサーの使い方
#51初級
プレミアム

ガスセンサーの使い方

キッチンのガス漏れに人より先に気づく小さな見張り役です。ガスセンサーは空気中のガスを常に監視します。異常がないときは緑色のLEDが点灯し、ガス濃度が一定の値を超えると赤色のLEDが点灯してブザーが鳴ります。家庭用ガス警報器の仕組みを実際に確かめられます。

4.6(37)
50
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