ℹ️ 関連記事
本記事はESP32での実装例です。Arduino Uno R4での実装やループバックテストによる動作検証を知りたい方はこちら:
👉 【Arduino】MCP23017で16本のピン追加&自己診断テスト

はじめに

ESP32やArduinoで電子工作をしていると、「ピンが足りない!」という状況に直面することがあります。LEDを大量に制御したい、スイッチ入力が多い、センサーを複数接続したい…そんな時に活躍するのがI/Oエキスパンダーです。

本記事では、I2C通信で簡単に16ピンを追加できるMCP23017と、最新のAdafruit_MCP23X17ライブラリを使った実装方法を詳しく解説します。

この記事で学べること

  • MCP23017の基本仕様とピンアサイン
  • I2Cアドレス設定と複数デバイス接続(最大8個、128ピン)
  • 最新Adafruit_MCP23X17ライブラリの使い方
  • LEDとスイッチを使った実践的な回路例
  • 入出力制御のプログラミング手法

MCP23017とは?I/Oエキスパンダーの基礎知識

I/Oエキスパンダーが必要な理由

マイコンを使った電子工作では、以下のような場面でピン不足に悩まされます:

  • LED制御: マトリクスLEDや7セグメントLEDで多数のピンが必要
  • スイッチ入力: ボタンやセンサーの入力点数が多い
  • 複合プロジェクト: ディスプレイ + センサー + モーターなど複数デバイス制御

I/Oエキスパンダーを使えば、この問題を簡単に解決できます:

用途 担当デバイス
単純な入出力 I/Oエキスパンダー(MCP23017)
AD変換、PWM制御 マイコン本体のピン

このように用途に応じて使い分けることで、効率的なシステム設計が可能になります。

MCP23017の特徴

秋月電子で購入

MCP23017は、Microchip Technology社製の16ビットI/O GPIOエキスパンダーです。I2C通信を使って簡単に制御できるため、ESP32やArduinoとの相性が抜群です。


MCP23017の仕様と回路設計

データシートから読み解く基本仕様

MCP23017データシート(Microchip公式)

MCP23017ピンアサイン

MCP23017ピンアサイン

主要仕様

項目 仕様
通信方式 I2C(400kHz対応)
動作電圧 1.8V~5.5V(ESP32の3.3Vで動作可)
入出力ピン数 16ピン(GPA0~GPA7 / GPB0~GPB7)
最大駆動電流 25mA/ピン
同時接続数 最大8個(I2Cアドレス設定により)

I2Cアドレス設定の仕組み

MCP23017は3本のアドレスピン(A0, A1, A2)の組み合わせで、最大8個のデバイスを1つのI2Cバスに接続できます。

アドレス設定表

A2 A1 A0 I2Cアドレス ライブラリ指定値
0 0 0 0x20 0(デフォルト)
0 0 1 0x21 1
0 1 0 0x22 2
0 1 1 0x23 3
1 0 0 0x24 4
1 0 1 0x25 5
1 1 0 0x26 6
1 1 1 0x27 7

重要: A0~A2ピンは0(GND)または1(VDD)に接続します。フローティング(未接続)は避けましょう。

驚異の拡張性:最大128ピン

  • 1個のMCP23017 → 16ピン
  • 8個接続 → 128ピン

これだけあれば、ほとんどのプロジェクトでピン不足に悩むことはありません。

MCP23017のその他の機能

  • 内部プルアップ抵抗: 100kΩのプルアップを各ピンに設定可能
  • 割り込み機能: ピンの状態変化を検出してマイコンに通知
  • ポート単位の制御: 8ビットまとめて読み書き可能

実装回路:スイッチ入力とLED出力

回路の構成

今回は、MCP23017の機能を検証するために以下の構成で回路を作成しました:

  • 入力: スイッチ 3個(GPB0~GPB2)
  • 出力: LED 8個(GPA0~GPA7)
  • アドレス設定: A0, A1, A2すべてGND(アドレス0x20)
MCP23017テスト回路図

MCP23017テスト回路図

回路のポイント

  1. アドレス設定ピン: A0, A1, A2にプルダウン抵抗を接続してGNDに固定
  2. スイッチ入力: プルダウン抵抗付きで、押すとHIGH入力
  3. LED出力: 電流制限抵抗を介してLEDを接続

ブレッドボード実装

ブレッドボードへの実装例

ブレッドボードへの実装例

ESP32との接続

ESP32 MCP23017
3.3V VDD
GND VSS, A0, A1, A2
GPIO21 (SDA) SDA
GPIO22 (SCL) SCL

重要: I2Cプルアップ抵抗(4.7kΩ程度)をSDA、SCL両方に接続してください。


Adafruit_MCP23X17ライブラリのセットアップ

ライブラリのインストール

Arduino IDEのライブラリマネージャーから「Adafruit MCP23017」で検索し、Adafruit MCP23XXX libraryをインストールします。

または、以下のコマンドでもインストール可能:

ライブラリマネージャー → "Adafruit MCP23XXX" → インストール

必要な依存ライブラリ

Adafruit_MCP23X17ライブラリは、以下のライブラリも自動的にインストールします:

  • Adafruit BusIO
  • Wire(標準ライブラリ)

サンプルプログラム:スイッチでLEDパターン切替

完全なコード

#include <Wire.h>
#include <Adafruit_MCP23X17.h>

Adafruit_MCP23X17 mcp;

int sw1, sw2, sw3;

void setup() {
  delay(1000);
  Serial.begin(115200);
  
  // MCP23017の初期化
  if (!mcp.begin_I2C(0x20)) {  // アドレス0x20で初期化
    Serial.println("MCP23017 not found!");
    while (1);
  }
  Serial.println("MCP23017 initialized");

  // GPA0~GPA7を出力に設定(LED用)
  for (int i = 0; i < 8; i++) {
    mcp.pinMode(i, OUTPUT);
  }

  // GPB0~GPB2を入力に設定(スイッチ用)
  mcp.pinMode(8, INPUT);
  mcp.pinMode(9, INPUT);
  mcp.pinMode(10, INPUT);

  delay(1000);
}

void loop() {
  // スイッチの状態を読み取り
  sw1 = mcp.digitalRead(8);
  sw2 = mcp.digitalRead(9); 
  sw3 = mcp.digitalRead(10); 
  
  Serial.print("SW1:"); Serial.print(sw1);
  Serial.print(" SW2:"); Serial.print(sw2);
  Serial.print(" SW3:"); Serial.println(sw3);

  // スイッチの組み合わせでLEDパターンを変更
  if (sw1 == 1 && sw2 == 0 && sw3 == 0) {
    // モード1: 前半4つ点灯
    Serial.println("Mode 1: Front LEDs ON");
    for (int i = 0; i < 4; i++) mcp.digitalWrite(i, HIGH);
    for (int i = 4; i < 8; i++) mcp.digitalWrite(i, LOW);
    
  } else if (sw1 == 0 && sw2 == 1 && sw3 == 0) {
    // モード2: 後半4つ点灯
    Serial.println("Mode 2: Back LEDs ON");
    for (int i = 0; i < 4; i++) mcp.digitalWrite(i, LOW);
    for (int i = 4; i < 8; i++) mcp.digitalWrite(i, HIGH);
    
  } else if (sw1 == 0 && sw2 == 0 && sw3 == 1) {
    // モード3: 全点灯
    Serial.println("Mode 3: All LEDs ON");
    for (int i = 0; i < 8; i++) mcp.digitalWrite(i, HIGH);
    
  } else {
    // モード0: 全消灯
    Serial.println("Mode 0: All LEDs OFF");
    for (int i = 0; i < 8; i++) mcp.digitalWrite(i, LOW);
  }
  
  delay(100);
}

Adafruit_MCP23X17ライブラリ関数リファレンス

  • mcp.begin():I2C通信の開始
    mcpとのI2C通信を開始します。( )内にはライブラリ使用時の設定したアドレスを入力します。ただし、0x00の場合は空白3のままにしておきます。 例:アドレスが0x00の場合 mcp.begin(); アドレスが0x05の場合 mcp.begin(0x05);

  • mcp.pinMode(pin, mode):ピンのモード設定(0〜7が出力, 8〜15が入力
    それぞれのピンの入出力モードを設定します。 numにはピン番号を設定します。GPA0GPA7は07に、GPB07は815にそれぞれ対応しています。 modeにはピン番号に対する入出力モードを設定します。出力なら"OUTPUT"を、入力なら”INPUT”を入力します。

  • mcp.digitalRead(pin):入力状態の取得(1=HIGH, 0=LOW)
    指定ピン番号の入力状態を確認します。HIGHが入力されていたら1を、LOWが入力されていたら0を返します。

  • mcp.digitalWrite(pin, val):ピンに出力(1=HIGH, 0=LOW)
    指定ピン番号の出力を設定します。mode = 0ならLOWを、mode = 1ならHIGHを出力します。


実際の動作

実際に動作させると以下の動画のようになります。

スイッチの状態に応じて、LEDの点灯パターンがリアルタイムで変化しています。これでMCP23017の基本的な入出力制御が実現できました。

動作の詳細

  • スイッチ1のみON: 前半4個のLED(GPA0~GPA3)が点灯
  • スイッチ2のみON: 後半4個のLED(GPA4~GPA7)が点灯
  • スイッチ3のみON: 全8個のLEDが点灯
  • 全スイッチOFF: 全LEDが消灯

応用例とプロジェクトアイデア

MCP23017の16ピン拡張を活用したプロジェクト例を紹介します。

1. 大型LEDマトリクス制御

8×8のLEDマトリクスなら、MCP23017を1個使って行列制御が可能です。さらに複数接続すれば、16×16以上の大型ディスプレイも実現できます。

2. 多ボタン入力システム

最大16個のボタンやスイッチを1つのMCP23017で管理。内部プルアップ機能を使えば、外付け抵抗も不要です。

3. リレー制御ボード

8個のリレーを制御して、家電製品やモーターの ON/OFF を自動化。スマートホームプロジェクトに最適です。

4. センサー集約システム

複数のデジタルセンサー(温湿度、人感、ドア開閉など)の入力をMCP23017に集約し、ESP32のピンを節約します。


トラブルシューティング

MCP23017が認識されない

症状: begin_I2C()falseを返す

チェック項目:

  1. I2Cプルアップ抵抗: SDA、SCLに4.7kΩのプルアップを接続
  2. 電源電圧: VDDに3.3Vまたは5Vが正しく供給されているか確認
  3. アドレス設定: A0, A1, A2が正しく接続されているか(フローティングNG)
  4. 配線: SDA/SCLが逆接続されていないか確認

I2Cスキャナーで確認:

#include <Wire.h>
void setup() {
  Wire.begin();
  Serial.begin(115200);
  Serial.println("I2C Scanner");
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.print("Device found at 0x");
      Serial.println(address, HEX);
    }
  }
}
void loop() {}

LEDが正しく点灯しない

チェック項目:

  1. 電流制限抵抗: 各LEDに330Ωまたは適切な抵抗を接続
  2. 電流容量: MCP23017の最大駆動電流は25mA/ピン
  3. プログラム: pinMode()で正しくOUTPUTに設定されているか確認

スイッチ入力が不安定

対策:

  1. プルアップ/プルダウン: 内部プルアップを有効化 pinMode(pin, INPUT_PULLUP)
  2. チャタリング除去: ソフトウェアでデバウンス処理を追加
  3. 配線: 入力ピンがフローティングになっていないか確認

まとめ

ESP32とMCP23017を使ったI/O拡張の実装方法を解説しました。

本記事のポイント

  1. MCP23017は16ピンをI2C通信で追加できる強力なI/Oエキスパンダー
  2. 最新Adafruit_MCP23X17ライブラリで簡単に制御可能
  3. 最大8個接続で128ピンまで拡張可能
  4. 内部プルアップや割り込み機能など、高度な機能も搭載
  5. LED制御、スイッチ入力、センサー集約など幅広い用途に対応

次のステップ

  • 複数のMCP23017を接続して、さらに多くのピンを制御
  • 割り込み機能を使って、効率的なイベント駆動プログラミング
  • SPI版のMCP23S17も検討(高速通信が必要な場合)

MCP23017を使えば、ピン不足の悩みから解放され、より大規模で複雑なプロジェクトに挑戦できます。

それでは、良き電子工作ライフを!