論理ゲートの解説:AND、OR、NOT、XORの真理値表とArduino
論理ゲートとは?AND、OR、NOT、NAND、NOR、XOR、XNORの記号、真理値表、74HC08と74HC00のIC、半加算器、Arduino・ESP32・Picoのコードを紹介します。
論理ゲートはデジタル回路の基本の部品です。それぞれが1つ以上のデジタル入力を見て、決まったルールに従って1つのデジタル出力を出します。入力は0(LOW)か1(HIGH)だけで、出力も同じです。基本のゲートはAND、OR、NOT、NAND、NOR、XOR、XNORの7つです。スマートフォンのプロセッサから洗濯機の制御基板まで、Arduinoの中のATmega328Pから電卓まで、どのデジタル機器も、何百万もの小さな論理ゲートを組み合わせて動いています。
このガイドでは、すべてのゲートの記号と真理値表、74HC08、74HC32、74HC00などの本物のIC、2つの押しボタンで作るブレッドボードの実験、NANDだけでほかのすべてのゲートを作る方法、2つのビットを足す半加算器の回路を学びます。最後の章では、同じロジックをArduinoで&&、||、!の演算子とビット演算でコードにし、ESP32とRaspberry Pi Pico(MicroPython)の例に進みます。

論理ゲートとは?そのしくみ
デジタル電子回路では、すべての信号が1(HIGH、真)か0(LOW、偽)の2つの状態のどちらかにあります。この2つの値を扱う数学をブール代数と呼びます。1854年に出版された本で、ジョージ・ブールは論理的な推論をまさにこの方法で代数として表しました。1937年にはクロード・シャノンが、この代数がリレーで作るスイッチ回路と1対1で対応することを示し、デジタル回路の設計の基礎を築きました。今では論理ゲートの中にはほんの数個のトランジスタしかありません。CMOS技術では、NOTゲートは2個のMOSFET、NANDゲートは4個でできています。トランジスタがスイッチとして働くしくみはトランジスタとは?で解説しています。
では、回路はどの電圧を1とし、どの電圧を0とするのでしょうか。それはボードの電源電圧とICのファミリーによります。下の表は、入力が確実に1、または0とみなされる限界です。2つの限界の間は不定領域で、入力がそこにとどまると、出力がでたらめに動くことがあります。何もつながっていない浮いた入力は、まさにこの不定領域をさまよいます。そのため、すべての入力は信号につなぐか、抵抗を通してGNDかVCCにつなぐ必要があります。
| ボード / ファミリー | 電源 | 確実に1とみなされる入力 | 確実に0とみなされる入力 |
|---|---|---|---|
| Arduino Uno(ATmega328P) | 5 V | ≥ 3.0 V | ≤ 1.5 V |
| ESP32 | 3.3 V | ≥ 2.5 V | ≤ 0.8 V |
| Raspberry Pi Pico(RP2040) | 3.3 V | ≥ 2.0 V | ≤ 0.8 V |
| 74HCのIC | 5 V | ≥ 3.5 V | ≤ 1.5 V |
| 74HCTのIC | 5 V | ≥ 2.0 V | ≤ 0.8 V |
| CD4000のIC | 5 V | ≥ 3.5 V | ≤ 1.5 V |
7つの基本の論理ゲートとその記号
回路図では、ゲートを2つの異なる規格で描きます。アメリカの規格(ANSI/IEEE)では、ゲートごとに形が違います。ANDはDの文字のような形、ORはとがった盾のような形、NOTは三角形です。出力の小さな丸(バブル)は「反転」を意味し、NANDは実は先端にバブルの付いたANDです。XORがORと違うのは、入力側にある2本目の曲線です。ヨーロッパの規格(IEC)では、すべてのゲートが長方形で、中に書かれた記号で区別します。ANDは&、ORは≥1、XORは=1、NOTは1です。教科書では、NANDを否定論理積、NORを否定論理和、XORを排他的論理和、XNORを否定排他的論理和とも書きます。
| ゲート | 別名 | ANSIの記号 | IECの記号 | 論理式 | 出力が1になるのは? |
|---|---|---|---|---|---|
| AND | 論理積 | Dの形 | & | Y = A · B | 両方の入力が1 |
| OR | 論理和 | とがった盾 | ≥1 | Y = A + B | 少なくとも1つの入力が1 |
| NOT | インバーター(否定) | 三角形+バブル | 1(出力にバブル) | Y = A' | 入力が0 |
| NAND | 否定論理積 | Dの形+バブル | &(出力にバブル) | Y = (A · B)' | 少なくとも1つの入力が0 |
| NOR | 否定論理和 | 盾+バブル | ≥1(出力にバブル) | Y = (A + B)' | 両方の入力が0 |
| XOR | 排他的論理和 | 二重の曲線の盾 | =1 | Y = A ⊕ B | 入力が違う |
| XNOR | 否定排他的論理和 | 二重の曲線+バブル | =1(出力にバブル) | Y = (A ⊕ B)' | 入力が同じ |
論理ゲートの真理値表
真理値表は、入力のすべての組み合わせに対してゲートが出す出力を並べた表です。n個の入力のゲートには2ⁿ行あります。入力2つなら4行、3つなら8行、4つなら16行です。行を2進数の数える順番(00、01、10、11)で書けば、組み合わせを飛ばすことはありません。2入力の6つのゲートを1つの表にまとめました。
| A | B | AND | OR | NAND | NOR | XOR | XNOR |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
| 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
| 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
NOTゲートは入力が1つなので、表は2行です。A = 0なら出力は1、A = 1なら出力は0です。表をよく見ると、規則性に気づきます。NANDの列はANDのちょうど逆、NORはORの逆、XNORはXORの逆です。覚えるには、次の短いルールを使いましょう。ANDは「全部1?」、ORは「少なくとも1つは1?」、XORは「入力が違う?」と問います。名前がNで始まるゲートは、同じ問いに逆の答えを返します。ゲートを自分で試して記号をリアルタイムで見るには、論理ゲートツールでAとBの入力をタップするだけです。
- AND:直列の2つのスイッチです。ランプは両方のスイッチが閉じたときだけ点きます。2本の別々の鍵で開く銀行の金庫も、ANDのルールに従っています。
- OR:並列の2つの押しボタンです。玄関のボタンを押しても裏口のボタンを押しても、同じベルが鳴ります。
- NOT:冷蔵庫の明かりです。ドアが閉まっている間はスイッチが押されていてランプは消え、ドアが開くとスイッチが離れてランプが点きます。
- NAND:「すべて問題がなければ警告しない」というルールです。機械の2つの安全カバーのうち1つでも開いていると、警告ランプが点きます。
- NOR:「どれも起きていない」というルールです。煙もガスも検知されていないときだけ点く、緑の「異常なし」のランプです。
- XOR:階段の3路スイッチです。下と上のどちらのスイッチを切り替えても、ランプの状態が変わります。2つのスイッチの位置が違うとランプが点き、同じだと消えます。
- XNOR:一致の確認です。2つのビットが同じときに1を出し、デジタルの比較器やエラー検出の回路に使われます。
論理ゲートのIC:74HC08、74HC32、74HC00
論理ゲートは、1つずつのトランジスタで作る代わりに既製のICを使います。ホビーの電子工作で最も一般的なファミリーは74HCシリーズです。14ピンのDIPパッケージに2入力のゲートが4つ入り、電源はいつも14番ピン(VCC)に、GNDは7番ピン(GND)につなぎます。74HCのICは2〜6 Vで動き、入力にはほとんど電流が流れず、5 Vでは1つのゲートの遅延は約10ナノ秒と、ArduinoのdigitalWriteを1回呼ぶより何百倍も速いです。各出力は4 mAの負荷で保証された電圧レベルを保ち、絶対最大定格は1出力あたり25 mA、IC全体で50 mAです。
| IC | ゲート | 中身 | ピン配置 | CMOS 4000の同等品 |
|---|---|---|---|---|
| 74HC08 | AND | 2入力 × 4 | 標準(下の表) | CD4081 |
| 74HC32 | OR | 2入力 × 4 | 標準 | CD4071 |
| 74HC00 | NAND | 2入力 × 4 | 標準 | CD4011 |
| 74HC86 | XOR | 2入力 × 4 | 標準 | CD4070 |
| 74HC02 | NOR | 2入力 × 4 | 異なる:出力は1、4、10、13 | CD4001 |
| 74HC04 | NOT | 1入力 × 6 | 入力は1、3、5、9、11、13 | CD4069 |
| 74HC14 | NOT(シュミットトリガー) | 1入力 × 6 | 74HC04と同じ | CD40106 |
| CD4077 / 74HCS7266 | XNOR | 2入力 × 4 | 入手しにくい。ふつうは74HC86+74HC04 | CD4077 |
74HC08、74HC32、74HC00、74HC86はピン配置がまったく同じで、中のゲートの種類だけが違います。ICの上面の切り欠きか点が1番ピンを示します。切り欠きを左にしてICを上から見ると、ピンの番号は反時計回りに並びます。下の列が左から右へ1〜7、上の列が右から左へ8〜14です。AとBが入力、Yが出力で、先頭の数字はゲートの番号です。
| ピン | 役割 | ピン | 役割 |
|---|---|---|---|
| 1 | 1A(ゲート1の入力) | 14 | VCC(+2…6 V) |
| 2 | 1B(ゲート1の入力) | 13 | 4B(ゲート4の入力) |
| 3 | 1Y(ゲート1の出力) | 12 | 4A(ゲート4の入力) |
| 4 | 2A(ゲート2の入力) | 11 | 4Y(ゲート4の出力) |
| 5 | 2B(ゲート2の入力) | 10 | 3B(ゲート3の入力) |
| 6 | 2Y(ゲート2の出力) | 9 | 3A(ゲート3の入力) |
| 7 | GND | 8 | 3Y(ゲート3の出力) |
同じ仕事をするICにも、いくつかのファミリーがあります。74LSシリーズは古いTTL技術で、4.75〜5.25 Vでしか動かず、消費電流が多く、浮いた入力をたいてい1と読みます。74HCTシリーズは、TTL互換の入力を持つ74HCです。5 Vで動きますが、2 V以上を確実に1とみなすので、ESP32やPicoの3.3 Vの信号も問題なく読めます。CD4000シリーズ(CD4081、CD4011など)は3〜18 Vの広い範囲で動きますが遅く、ピン配置も74HCと違うので、CD4011は74HC00の代わりにそのまま使えません。
押しボタンでブレッドボードの実験:74HC08でANDゲート
論理ゲートを理解する一番の方法は、2つの押しボタンで自分で試すことです。この実験にマイコンはなく、必要なのは74HC08、押しボタン2個、10 kΩの抵抗2本、1 kΩの抵抗1本、LED 1個、100 nFのコンデンサ1個だけです。電源には、Arduinoの5VとGNDのピン、ブレッドボード用の電源モジュール、単3電池3本(4.5 V)のどれでもかまいません。ブレッドボードの内部のつながりがよくわからなければ、先にブレッドボードとは?を読みましょう。

- 74HC08を、ピンが両側に来るようにブレッドボードの中央の溝をまたいで差し、切り欠きを左に向けます。
- 14番ピンを+のレール(5 V)に、7番ピンを−のレール(GND)につなぎ、この2本のピンの間に100 nFのコンデンサを入れます。
- ボタンAの片側を+のレールに、もう片側を1番ピンにつなぎます。同じピンからGNDへ10 kΩの抵抗を入れます。このプルダウン抵抗が、ボタンを押していない間、入力をしっかり0に保ちます。
- ボタンBも同じように2番ピンにつなぎ、専用の10 kΩのプルダウン抵抗を付けます。
- 出力の3番ピンから、1 kΩの抵抗を通してLEDの長い足(アノード)へつなぎ、LEDの短い足(カソード)をGNDにつなぎます。
- 使わない入力の4、5、9、10、12、13番ピンをGNDにつなぎ、出力の6、8、11番は開放のままにします。
- 電源を入れ、4つの組み合わせを順に試します。LEDは両方のボタンを一緒に押したときだけ点くはずです。結果を真理値表と比べましょう。
| 接続 | 74HC08のピン | 接続先 |
|---|---|---|
| 電源 | 14(VCC) | +のレール、5 V |
| グラウンド | 7(GND) | −のレール |
| パスコン | 14と7の間 | 100 nFのセラミック、ICの近くに |
| 入力A | 1 | ボタンA → 5 V、10 kΩ → GND |
| 入力B | 2 | ボタンB → 5 V、10 kΩ → GND |
| 出力 | 3 | 1 kΩ → LEDのアノード、LEDのカソード → GND |
| 使わない入力 | 4、5、9、10、12、13 | GND |
| 使わない出力 | 6、8、11 | 開放 |
NANDですべてのゲートを作る:万能ゲート
NANDは、NANDゲートだけでほかのすべてのゲートを作れるので万能ゲートと呼ばれます。これには実用的な面もあります。CMOS技術ではNANDはわずか4個のトランジスタで作れる最も簡単なゲートの1つですが、ANDは実はNANDのあとにNOTが続いたもので、6個必要です。そのため、チップの設計者はNANDを好みます。USBメモリのNANDフラッシュも、メモリセルがNANDゲートのトランジスタのように直列につながっていることから名前が付いています。NORも万能です。月へ飛んだアポロ誘導コンピューターは、3入力のNORゲートを2つずつ持つ約2,800個のICで作られていました。
| 作るゲート | NANDでどう作る? | 必要なNANDの数 |
|---|---|---|
| NOT | A NAND A(両方の入力をつなぐ) | 1 |
| AND | (A NAND B)の出力をNOTに通す | 2 |
| OR | (A NAND A) NAND (B NAND B) | 3 |
| NOR | OR + NOT | 4 |
| XOR | N1 = A NAND B; (A NAND N1) NAND (B NAND N1) | 4 |
| XNOR | XOR + NOT | 5 |
表のORの行はド・モルガンの法則にもとづいています:(A' · B')' = A + B。つまり、まず両方の入力を反転してからNANDに入れると、ORになります。ド・モルガンの第2法則は(A + B)' = A' · B'です。どちらの法則も、コードの条件を簡単にするのに役立ちます。Arduinoでは、!(a && b)はいつも(!a || !b)と同じ結果になり、!(a || b)は(!a && !b)と同じになります。
4つのNANDゲートでXORを作るのは、定番の試験問題と実習の課題で、1つの74HC00の4つのゲートでちょうど足ります。まずN1 = A NAND Bを求めます。次にN2 = A NAND N1とN3 = B NAND N1を求め、最後のゲートの出力Y = N2 NAND N3がXORになります。下の配線で、ブレッドボードの実験を4つのNANDのXORに変えられます。
| 74HC00のピン | 接続 | 役割 |
|---|---|---|
| 1と4 | ボタンA | 入力A(ゲート1と2) |
| 2と10 | ボタンB | 入力B(ゲート1と3) |
| 3 → 5と9 | ジャンパーワイヤー | N1 = A NAND B |
| 6 → 12 | ジャンパーワイヤー | N2 = A NAND N1 |
| 8 → 13 | ジャンパーワイヤー | N3 = B NAND N1 |
| 11 | 1 kΩ + LED | Y = A XOR B |
| 14 / 7 | 5 V / GND | 電源 |
もう一歩進めましょう。2つのNANDゲートの出力を互いの入力に交差させてつなぐと、SRラッチという1ビットのメモリになります。この回路は、ボタンを離したあとも最後の状態を覚えています。プロセッサのレジスタ、カウンター、74HC595シフトレジスタのようなICは、ゲートで作ったこのようなメモリセルをつないで作られています。
半加算器:ゲートで2つのビットを足す
論理ゲートができることで最も印象的なのは、数を足すことです。2進数では、0 + 0 = 0、0 + 1 = 1、1 + 0 = 1、1 + 1 = 10(10進数の2)です。結果の右の桁を和、左にあふれる桁を桁上がり(キャリー)と呼びます。下の表を見ると、和はちょうどXOR、桁上がりはちょうどANDであることがわかります。つまり、XORゲートとANDゲートを並べると、1ビットの数を2つ足す半加算器になります。
| A | B | 桁上がり(C = A AND B) | 和(S = A XOR B) | 10進数の結果 |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 0 | 2(2進数の10) |
ブレッドボードで作るには、ボタンAとBを74HC86と74HC08の両方の1番と2番ピンにつなぎます。74HC86の3番ピンが和のLEDを、74HC08の3番ピンが桁上がりのLEDを駆動します。両方のボタンを押すと、和のLEDが消えて桁上がりのLEDが点きます。LEDは2進数の10、つまり2を表しています。74HC00だけを使いたいなら、XORに4つのNANDが、桁上がりを得るためにN1を反転する5つ目のNANDが必要です。つまり、半加算器には5つのNANDゲートが要ります。
半加算器は、下の桁から来る桁上がりを考えられません。そのためには全加算器が必要です。式はS = A ⊕ B ⊕ CinとCout = (A · B) + (Cin · (A ⊕ B))で、半加算器2つとORゲート1つになります。全加算器を4つつなぎ、それぞれが桁上がりを次に渡すようにすれば、4ビットの加算器になります。既製の74HC283のICも同じ4ビットの足し算をしますが、桁上がりがチェーンを伝わるのを待つのではなく、内部の高速な回路(キャリー先見)で求めます。パソコンのプロセッサの演算装置は、同じ考え方を64ビットではるかに速くしたものです。
Arduinoでの論理ゲート:&&、||、!とビット演算
Arduinoのコードでは、それぞれの論理ゲートに2つの対応があります。論理演算子(&&、||、!)は条件を組み合わせ、真か偽の結果を返し、if文やwhile文で使います。ビット演算子(&、|、^、~)は、数のすべてのビットに列ごとに一度に適用されます。1バイトを扱うのは、8つのゲートを同時に動かすようなものです。表の例では0b1100と0b1010の数を使っています。
| ゲート | 論理(bool) | ビット演算 | 例 | 結果 |
|---|---|---|---|---|
| AND | a && b | x & y | 0b1100 & 0b1010 | 0b1000 |
| OR | a || b | x | y | 0b1100 | 0b1010 | 0b1110 |
| NOT | !a | ~x | ~0b00001100(byte) | 0b11110011 |
| NAND | !(a && b) | ~(x & y) | ~(0b1100 & 0b1010) & 0x0F | 0b0111 |
| NOR | !(a || b) | ~(x | y) | ~(0b1100 | 0b1010) & 0x0F | 0b0001 |
| XOR | a != b | x ^ y | 0b1100 ^ 0b1010 | 0b0110 |
| XNOR | a == b | ~(x ^ y) | ~(0b1100 ^ 0b1010) & 0x0F | 0b1001 |
2種類の違いは小さく見えますが、気づきにくいバグの原因になります。&&と||は短絡評価を使います。a && bでaが偽なら、bはまったく評価されません。&はいつも両側を評価し、数のビットを見ます。2 && 1は真ですが、2 & 1は0です。0b10と0b01には共通のビットがないからです。C++には論理XORの専用の演算子はなく、2つのboolならa != bと書くのが最も読みやすい方法です。ビット演算、<<と>>のシフト、2進数について詳しくは数の表し方とビット演算をご覧ください。
では、ブレッドボードの実験をArduino Unoに移しましょう。2つの押しボタンを2番と3番のピンに、7つのLED(それぞれ330 Ωの抵抗付き)を4〜10番のピンにつなぎます。各ボタンの片側をピンに、もう片側をGNDにつなぎます。内部プルアップ抵抗をオンにするので、追加の抵抗は不要です。1つのスケッチで、7つのゲートすべてを一度に動かします。
1// Mantık kapısı simülatörü: 2 buton, 7 LED / Logic gate simulator: 2 buttons, 7 LEDs
2const byte PIN_A = 2; // A butonu, diğer ucu GND / button A, other leg to GND
3const byte PIN_B = 3; // B butonu, diğer ucu GND / button B, other leg to GND
4
5// Sıra: AND, OR, NOT A, NAND, NOR, XOR, XNOR / Order: AND, OR, NOT A, NAND, NOR, XOR, XNOR
6const byte LED_PINS[7] = {4, 5, 6, 7, 8, 9, 10};
7const char* const GATE_NAMES[7] = {"AND", "OR", "NOT A", "NAND", "NOR", "XOR", "XNOR"};
8
9byte lastInputs = 0xFF; // ilk turda yazdırmayı zorlar / forces a print on the first pass
10
11void setup() {
12 pinMode(PIN_A, INPUT_PULLUP);
13 pinMode(PIN_B, INPUT_PULLUP);
14 for (byte i = 0; i < 7; i++) {
15 pinMode(LED_PINS[i], OUTPUT);
16 }
17 Serial.begin(9600);
18}
19
20void loop() {
21 // Basılı buton LOW okunur, ! ile 1 yapılır / A pressed button reads LOW, ! turns it into 1
22 bool a = !digitalRead(PIN_A);
23 bool b = !digitalRead(PIN_B);
24
25 bool out[7];
26 out[0] = a && b; // AND
27 out[1] = a || b; // OR
28 out[2] = !a; // NOT A
29 out[3] = !(a && b); // NAND
30 out[4] = !(a || b); // NOR
31 out[5] = a != b; // XOR: girişler farklı mı? / are the inputs different?
32 out[6] = a == b; // XNOR: girişler aynı mı? / are the inputs equal?
33
34 for (byte i = 0; i < 7; i++) {
35 digitalWrite(LED_PINS[i], out[i] ? HIGH : LOW);
36 }
37
38 // Yalnız girişler değişince yaz / Print only when the inputs change
39 byte inputs = (a << 1) | b;
40 if (inputs != lastInputs) {
41 Serial.print("A=");
42 Serial.print(a);
43 Serial.print(" B=");
44 Serial.print(b);
45 for (byte i = 0; i < 7; i++) {
46 Serial.print(" ");
47 Serial.print(GATE_NAMES[i]);
48 Serial.print('=');
49 Serial.print(out[i]);
50 }
51 Serial.println();
52 lastInputs = inputs;
53 }
54 delay(20); // basit sıçrama önleme / simple debounce
55}INPUT_PULLUPでは押したボタンがLOWになるので、コードは値を!で反転し、押したボタンを1にします。それから各LEDが自分のゲートの結果を表示します。4がAND、5がOR、6がNOT A、7がNAND、8がNOR、9がXOR、10がXNORです。シリアルモニタを9600ボーで開くと、ボタンが変わるたびに1行全体が表示されます。4つの組み合わせをすべて試せば、自分の手で真理値表を作ったことになります。プルアップについて詳しくはArduinoに押しボタンをつなぐ方法にあります。
ビット演算の力を見るために、2つ目の例では真理値表全体を数行で求めます。コツは、Aの列を0b1100という数、Bの列を0b1010と書くことです。各ビットが表の1行に対応するので、1回の&でANDの列の4行すべてが一度に得られます。スケッチの後半では、全加算器の式を使って2つの4ビットの数を1ビットずつ足し、プロセッサの加算回路をソフトウェアでまねします。このスケッチにハードウェアは不要で、シリアルモニタを開くだけです。
1// Bit işlemleriyle doğruluk tablosu ve 4 bitlik toplayıcı / Truth tables with bitwise ops and a 4-bit adder
2// Her bit bir satırdır: bit 0 = (A=0, B=0) ... bit 3 = (A=1, B=1) / Each bit is one row: bit 0 = (A=0, B=0) ... bit 3 = (A=1, B=1)
3const byte COL_A = 0b1100;
4const byte COL_B = 0b1010;
5const byte MASK = 0b1111; // yalnız 4 satır / only 4 rows
6
7void printRow(const char* name, byte column) {
8 Serial.print(name);
9 Serial.print('\t');
10 for (byte row = 0; row < 4; row++) {
11 Serial.print(bitRead(column, row)); // satır satır yaz / print row by row
12 Serial.print(" ");
13 }
14 Serial.println();
15}
16
17// Tam toplayıcı: iki bit + gelen elde / Full adder: two bits + carry in
18void fullAdder(byte a, byte b, byte carryIn, byte &sum, byte &carryOut) {
19 sum = a ^ b ^ carryIn; // XOR'lar toplamı verir / XORs give the sum
20 carryOut = (a & b) | (carryIn & (a ^ b)); // AND + OR eldeyi verir / AND + OR give the carry
21}
22
23// 4 tam toplayıcı zincirlenir (ripple carry) / 4 full adders chained (ripple carry)
24byte add4(byte x, byte y, byte &carryOut) {
25 byte result = 0;
26 byte carry = 0;
27 for (byte i = 0; i < 4; i++) {
28 byte s, c;
29 fullAdder(bitRead(x, i), bitRead(y, i), carry, s, c);
30 bitWrite(result, i, s);
31 carry = c;
32 }
33 carryOut = carry;
34 return result;
35}
36
37void setup() {
38 Serial.begin(9600);
39 Serial.println(F("AB:\t00 01 10 11"));
40 printRow("AND", COL_A & COL_B);
41 printRow("OR", COL_A | COL_B);
42 printRow("NAND", ~(COL_A & COL_B) & MASK); // ~ sonrası maske şart / mask is required after ~
43 printRow("NOR", ~(COL_A | COL_B) & MASK);
44 printRow("XOR", COL_A ^ COL_B);
45 printRow("XNOR", ~(COL_A ^ COL_B) & MASK);
46
47 byte carry;
48 byte s = add4(9, 12, carry); // 1001 + 1100
49 Serial.print(F("9 + 12 = "));
50 Serial.print(s + carry * 16); // elde 16'lar basamağıdır / the carry is the 16s place
51 Serial.print(F(" (toplam / sum = "));
52 Serial.print(s, BIN);
53 Serial.print(F(", elde / carry = "));
54 Serial.print(carry);
55 Serial.println(')');
56}
57
58void loop() {
59}Arduinoで74HCのICテスター
ICの印字が消えてしまったときや、まだ動くか知りたいときは、Arduinoをテスターにできます。このスケッチは、74HC00、74HC08、74HC32、74HC86(標準のピン配置のIC)の4つのゲートすべてに4つの入力の組み合わせを順に加え、出力を読み、結果を既知のパターンと比べます。ICの14番ピンを5Vに、7番ピンをGNDに、ほかのピンをコードの表にあるArduinoのピンにつなぎます。
1// 74HC00 / 08 / 32 / 86 tanıyıcı ve test cihazı / 74HC00 / 08 / 32 / 86 identifier and tester
2// Entegre: bacak 14 -> 5V, bacak 7 -> GND / Chip: pin 14 -> 5V, pin 7 -> GND
3// Her kapı: {A, B, Y} Arduino pinleri / Each gate: {A, B, Y} Arduino pins
4const byte GATES[4][3] = {
5 {2, 3, 4}, // kapı 1: entegre 1, 2 -> 3 / gate 1: chip 1, 2 -> 3
6 {5, 6, 7}, // kapı 2: entegre 4, 5 -> 6 / gate 2: chip 4, 5 -> 6
7 {8, 9, 10}, // kapı 3: entegre 9, 10 -> 8 / gate 3: chip 9, 10 -> 8
8 {11, 12, A0} // kapı 4: entegre 12, 13 -> 11 / gate 4: chip 12, 13 -> 11
9};
10
11// Desenin bit sırası: bit 0 = (0,0), bit 3 = (1,1) / Pattern bit order: bit 0 = (0,0), bit 3 = (1,1)
12const char* nameOf(byte pattern) {
13 switch (pattern) {
14 case 0b1000: return "AND (74HC08)";
15 case 0b1110: return "OR (74HC32)";
16 case 0b0111: return "NAND (74HC00)";
17 case 0b0110: return "XOR (74HC86)";
18 default: return "?";
19 }
20}
21
22byte testGate(byte g) {
23 byte pattern = 0;
24 for (byte row = 0; row < 4; row++) {
25 digitalWrite(GATES[g][0], bitRead(row, 1)); // A = satırın üst biti / A = high bit of the row
26 digitalWrite(GATES[g][1], bitRead(row, 0)); // B = satırın alt biti / B = low bit of the row
27 delayMicroseconds(10); // kapı ~10 ns gecikir, bol pay / the gate needs ~10 ns, plenty of margin
28 bitWrite(pattern, row, digitalRead(GATES[g][2]));
29 }
30 return pattern;
31}
32
33void setup() {
34 Serial.begin(9600);
35 for (byte g = 0; g < 4; g++) {
36 pinMode(GATES[g][0], OUTPUT);
37 pinMode(GATES[g][1], OUTPUT);
38 pinMode(GATES[g][2], INPUT);
39 }
40
41 byte first = testGate(0);
42 bool allSame = true;
43 for (byte g = 0; g < 4; g++) {
44 byte p = testGate(g);
45 Serial.print(F("Kapi / Gate "));
46 Serial.print(g + 1);
47 Serial.print(F(": "));
48 Serial.print(nameOf(p));
49 Serial.print(F(" desen / pattern 0b"));
50 Serial.println(p, BIN);
51 if (p != first) allSame = false;
52 }
53
54 if (allSame && nameOf(first)[0] != '?') {
55 Serial.println(F("Sonuc / Result: entegre saglam / chip OK"));
56 } else {
57 Serial.println(F("Sonuc / Result: bozuk kapi ya da baglanti hatasi / faulty gate or wiring error"));
58 }
59}
60
61void loop() {
62}ESP32でプログラムできる論理ゲート
同じ演算子はESP32でもそのまま動きます。この例では、3つ目のボタンでゲートの種類を切り替え、1つのLEDで選んだゲートの出力を表示します。これなら、教室や発表で1つの回路で6つのゲートを見せられます。ボタンはGPIO 25、26、27に(もう片側はGNDに)、LEDは220 Ωの抵抗を通してGPIO 23につなぎます。選んだゲートの名前は、115200ボーのシリアルモニタに表示されます。
1// ESP32 programlanabilir mantık kapısı / ESP32 programmable logic gate
2const int PIN_A = 25; // A butonu, diğer ucu GND / button A, other leg to GND
3const int PIN_B = 26; // B butonu / button B
4const int PIN_MODE = 27; // kapı seçme butonu / gate select button
5const int PIN_LED = 23; // çıkış LED'i (220 ohm) / output LED (220 ohm)
6
7const char* const NAMES[] = {"AND", "OR", "NAND", "NOR", "XOR", "XNOR"};
8const int GATE_COUNT = 6;
9const unsigned long DEBOUNCE_MS = 30; // sıçrama süresi / bounce time
10
11int gate = 0;
12int modeStable = HIGH; // kararlı buton durumu / stable button state
13int modeRaw = HIGH; // son ham okuma / last raw reading
14unsigned long modeChangedAt = 0; // ham değerin son değiştiği an / when the raw value last changed
15
16bool evaluate(int g, bool a, bool b) {
17 switch (g) {
18 case 0: return a && b;
19 case 1: return a || b;
20 case 2: return !(a && b);
21 case 3: return !(a || b);
22 case 4: return a != b; // XOR
23 default: return a == b; // XNOR
24 }
25}
26
27void setup() {
28 Serial.begin(115200);
29 pinMode(PIN_A, INPUT_PULLUP);
30 pinMode(PIN_B, INPUT_PULLUP);
31 pinMode(PIN_MODE, INPUT_PULLUP);
32 pinMode(PIN_LED, OUTPUT);
33 Serial.printf("Kapi / Gate: %s\n", NAMES[gate]);
34}
35
36void loop() {
37 int reading = digitalRead(PIN_MODE);
38 if (reading != modeRaw) { // ham değer değişti, süreyi yeniden başlat / raw value changed, restart the timer
39 modeRaw = reading;
40 modeChangedAt = millis();
41 }
42 // 30 ms boyunca sabit kaldıysa gerçek değişimdir / steady for 30 ms means a real change
43 if (millis() - modeChangedAt > DEBOUNCE_MS && reading != modeStable) {
44 modeStable = reading;
45 if (modeStable == LOW) { // yeni basış (bırakma sayılmaz) / new press (release is ignored)
46 gate = (gate + 1) % GATE_COUNT;
47 Serial.printf("Kapi / Gate: %s\n", NAMES[gate]);
48 }
49 }
50
51 bool a = !digitalRead(PIN_A); // basılı = 1 / pressed = 1
52 bool b = !digitalRead(PIN_B);
53 digitalWrite(PIN_LED, evaluate(gate, a, b) ? HIGH : LOW);
54}Raspberry Pi PicoとMicroPythonで論理ゲート
MicroPythonでは、論理演算子を英語の単語で書きます:and、or、not。ビット演算子はC++と同じで、&、|、^、~です。下のコードは、GP14とGP15の2つの押しボタンを読み、AND、OR、NAND、NOR、XOR、XNORの結果を、GP16〜GP21の6つのLEDに表示します。各ボタンのもう片側はGNDに、各LEDは220〜330 Ωの抵抗を通してつなぎます。Thonnyでコードをmain.pyとして保存すれば、Picoの電源を入れるたびに動きます。Picoが初めてなら、Raspberry Pi Picoとは?から始めましょう。
1# Pico ile 6 mantık kapısı / 6 logic gates on the Pico
2from machine import Pin
3import time
4
5btn_a = Pin(14, Pin.IN, Pin.PULL_UP) # A butonu, diğer ucu GND / button A, other leg to GND
6btn_b = Pin(15, Pin.IN, Pin.PULL_UP) # B butonu / button B
7
8# GP16..GP21: AND, OR, NAND, NOR, XOR, XNOR
9leds = [Pin(n, Pin.OUT) for n in range(16, 22)]
10gates = [
11 ("AND", lambda a, b: a and b),
12 ("OR", lambda a, b: a or b),
13 ("NAND", lambda a, b: not (a and b)),
14 ("NOR", lambda a, b: not (a or b)),
15 ("XOR", lambda a, b: a != b),
16 ("XNOR", lambda a, b: a == b),
17]
18
19last = None
20while True:
21 a = int(not btn_a.value()) # basılı = 1 / pressed = 1
22 b = int(not btn_b.value())
23 results = [int(f(a, b)) for _, f in gates]
24 for led, r in zip(leds, results):
25 led.value(r)
26 if (a, b) != last: # yalnız değişince yaz / print only on change
27 line = " ".join("%s=%d" % (g[0], r) for g, r in zip(gates, results))
28 print("A=%d B=%d %s" % (a, b, line))
29 last = (a, b)
30 time.sleep_ms(20)Pythonにも似た落とし穴があります。~Trueは-2になります。boolは実は整数だからです。ビットを反転するには、not x、1 - x、x ^ 1を使いましょう。また、PythonのandとorはいつもTrueかFalseを返すとは限らず、最後に評価した値を返すので、0 or 5は5になります。そのため、コードではint()で変換して、LEDにはいつも0か1だけが渡るようにしています。
論理ゲートを使ったプロジェクトのアイデア
- スマートなナイトライト(AND):暗い、かつ動きを検知したときに明かりを点けます。LDRとPIRセンサーを1つの&&の条件で組み合わせます。
- 階段の明かり(XOR):階段の下と上の2つのボタンで1つのランプを制御します。ランプの状態をXORで求め、リレーモジュールで商用電源のランプを切り替えます。
- 家庭用アラーム(AND + OR):システムが作動中に、ドアか窓が開いたらサイレンを鳴らします。ドアと窓はリードスイッチで検知します。詳しくはArduinoのアラームシステムのガイドをご覧ください。
- 2つの鍵の金庫(AND):2人の別々の人が同時にボタンを押すか、キーパッドの番号が確認されるまで、ロックが開かないようにします。
- 4ビットの計算機:スイッチで入力した2つの数を全加算器のロジックで足し、結果を7セグメントディスプレイに表示します。
- 早押しクイズのブザー:最初に押した解答者のLEDを固定し、ほかの人をブロックします。これはNANDを使ったラッチのソフトウェア版です。
- パリティチェック:1バイトのすべてのビットをXORします。結果が1なら、1の数は奇数です。シリアル通信のパリティビットは、まさにこの方法で計算されます。
よくある失敗と対処法
| 症状 | 考えられる原因 | 対処法 |
|---|---|---|
| LEDが勝手にちらつき、手を近づけると変わる | 入力が浮いている、プルダウン抵抗がない | すべての入力に10 kΩのプルダウン抵抗かプルアップ抵抗を入れる |
| ICが熱くなる | VCCとGNDが逆、または2つの出力がつながっている | 14番ピンをVCC、7番をGNDにする。出力同士は決してつながない |
| どのゲートもまったく反応しない | 電源がない、またはICが溝をまたいで差さっていない | テスターで14番と7番のピンの間を測り、ICを溝をまたいで差す |
| 74HC02やCD4011で結果がおかしい | ピン配置が74HC08と違う | データシートのピンの表に合わせて配線する |
| ICの消費電流が多すぎる | 使わない入力が浮いたまま | 使わない入力をすべてGNDにつなぐ |
| ESP32やPicoで結果が不安定 | 5 Vの74HCには3.3 Vの信号では足りない | 74HCを3.3 Vで給電するか、74HCTを使う |
| if (a & b)が思いがけず偽になる | &はビットごとに働く。2 & 1 = 0 | 条件には&&を使う |
| if (x & 1 == 0)が決して実行されない | ==が&より先に評価される | かっこを使う:(x & 1) == 0 |
| 1回押しただけでゲートが何回も変わる | 接点のチャタリング | ソフトウェアで20〜50 ms待つか、RCフィルタ+74HC14を使う |
論理ゲートは、LEDを点けることからプロセッサが数を足すことまで、デジタルの世界全体のアルファベットです。AND、OR、NOTがわかれば、if文の条件、アラームのルール、シフトレジスタを読むのがずっと楽になります。BlueGraysアプリには、押しボタンとLEDのプロジェクト、ESP32とRaspberry Pi Picoのボタンのプロジェクト、スマートな階段の照明のプロジェクト、PIRとLDRを組み合わせたスマート照明のプロジェクトが、ステップごとの回路図とコード付きで用意されていて、この記事のゲートのロジックを本物のプロジェクトで使えます。
よくある質問
論理ゲートの種類と用途は?
基本の論理ゲートはAND、OR、NOT、NAND、NOR、XOR、XNORの7つです。それぞれ0か1の入力を見て、独自のルールで1つの出力を出します。プロセッサ、メモリ、カウンター、電卓を含め、すべてのデジタル回路はこれらのゲートを組み合わせて作られています。
真理値表はどう作りますか?
まず入力の数から行の数を求めます。n個の入力には2ⁿ行が必要です。入力を2進数の数える順番(00、01、10、11)で書き、各行にゲートのルールを当てはめて出力の列を埋めます。複数のゲートのある回路では、途中の出力ごとに別の列を加えると作業が楽になります。
NANDが万能ゲートと呼ばれるのはなぜですか?
NANDゲートだけで、NOT、AND、OR、NOR、XOR、XNORを作れるからです。たとえばNANDの2つの入力をつなぐとNOT、NAND 2つを続けるとAND、NAND 4つでXORになります。NORゲートにも同じ性質があるので、NORも万能ゲートです。
XORとXNORの違いは何ですか?
XORは入力が違うときに1を出し、XNORは入力が同じときに1を出します。XNORはXORの反転で、2つのビットが等しいかを確かめるのに使います。XORは加算回路、パリティチェック、ビットの反転に使われます。
74HC08と74LS08の違いは何ですか?
どちらも2入力のANDゲートを4つ持ち、ピン配置も同じです。74HC08はCMOS技術で作られ、2〜6 Vで動き、消費電流がとても少なくなっています。74LS08はTTLで、5 V前後でしか動かず、電流も多く使います。新しいプロジェクトには74HCを、3.3 Vの信号を5 Vの回路につなぐなら74HCTを選びましょう。
Arduinoの&&と&の違いは何ですか?
&&は論理ANDの演算子で、両方の条件が真かを確かめ、真か偽を返します。&はビットごとのANDで、2つの数の各ビットを別々に比べます。そのため2 && 1は真ですが、2 & 1は0です。if文の条件には&&を使いましょう。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
ボタンでLEDを点灯(押している間のみ)
呼び鈴のように、押している間は点灯し、離すと消灯します。Arduinoはボタンの状態を常に読み取り、押されている間はLEDを点灯させ、指を離した瞬間に消灯させます。このシンプルな回路で、ボードが外部からの操作を検知する仕組みを学べます。

ボタンでLEDの点灯・消灯を切り替え
部屋の照明スイッチのように、ボタンを1回押すと点灯し、もう1回押すと消灯します。Arduinoはボタンが押されるたびにLEDの状態を反転させます。ボタン内部の小さな接点の振動で誤動作しないよう、短い待ち時間も設けます。1つのボタンでオン・オフを切り替える、シンプルな仕組みです。

ESP32でボタンによるLED制御(押している間だけ点灯)
ボタンを押している間はLEDが点灯し、離すと消灯します。ESP32のデジタル入力ピンと内蔵プルアップ抵抗の使い方を学びます。INPUT_PULLUPモードを使うため、外付け抵抗は不要です。

ESP32でボタンによるLED制御(トグル)
ボタンを押すたびにLEDの状態が切り替わり、点灯中なら消灯し、消灯中なら点灯します。基本的なトグル動作です。チャタリング対策でボタンの機械的なノイズを除去し、1回の操作で1回だけ切り替わるようにします。

Raspberry Pi Picoでボタンを押してLEDを点灯
Picoで初めての入力プロジェクト、ボタンの読み取りです!ボタンを押している間はLEDが点灯し、離すと消灯します。LEDアニメーションから一歩進んで、外部からPicoに信号を入力する方法を学びます。Pin.IN(入力モード)、Pin.PULL_UP(ボタンで一般的に使う内蔵プルアップ抵抗)、button.value()による読み取りを扱います。LEDはGP14、ボタンはGP2(内蔵PULL_UP)に接続します。押すとLOW(0)、離すとHIGH(1)になります。この逆の論理は最初は戸惑いますが、業界で標準的に使われています。

Raspberry Pi Picoで2個のボタンから2個のLEDを個別に制御
2個のボタンと2個のLEDが、それぞれ独立して動作します!各ボタンが対応するLEDを制御し、BTN1を押すと赤色LED、BTN2を押すと緑色LEDが点灯します。両方を同時に押すと、2個とも点灯します(並列動作)。複数のPinオブジェクトの管理(複数の入出力を同時に扱う方法)、三項演算子(1 if x else 0というPythonの簡潔なif-else)、独立したI/O制御(並列動作の仕組み)、GPIOの割り当て(GP12/13をLED出力、GP4/5をボタン入力に分ける基本的な構成)を学びます。

階段・廊下のスマート照明
階段や廊下に足を踏み入れると、進む方向に沿って照明が1段ずつ点灯します。両端に距離センサーがあり、どちらの前を通っても、その端から8個のLEDが0.5秒間隔で順番に点灯し、その後、同じ方向に順番に消灯します。夜の暗がりで足元を照らす、おしゃれなホームオートメーションのアイデアです。

ESP32スマート照明(PIR + LDR + リレー + OLED)
ESP32で廊下やトイレ、食品庫の照明をスマート化します!PIRモーションセンサー、LDR光センサー、リレーモジュールを使い、「暗い場所で動きを検知すると点灯する」定番の仕組みを作ります。周囲が明るければ動きを検知しても点灯しないため、日中の無駄な電力消費を抑えられます。照明は30秒間点灯し、動きが続くとタイマーがリセットされて点灯時間が延びます。SSD1306 OLEDには大きな文字で状態(ON / DAYTIME / WAITING)とカウントダウンを表示します。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

