ℹ️ 関連記事
本記事は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ピンアサイン
主要仕様
| 項目 | 仕様 |
|---|---|
| 通信方式 | 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テスト回路図
回路のポイント
- アドレス設定ピン: A0, A1, A2にプルダウン抵抗を接続してGNDに固定
- スイッチ入力: プルダウン抵抗付きで、押すとHIGH入力
- 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を返す
チェック項目:
- I2Cプルアップ抵抗: SDA、SCLに4.7kΩのプルアップを接続
- 電源電圧: VDDに3.3Vまたは5Vが正しく供給されているか確認
- アドレス設定: A0, A1, A2が正しく接続されているか(フローティングNG)
- 配線: 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が正しく点灯しない
チェック項目:
- 電流制限抵抗: 各LEDに330Ωまたは適切な抵抗を接続
- 電流容量: MCP23017の最大駆動電流は25mA/ピン
- プログラム:
pinMode()で正しくOUTPUTに設定されているか確認
スイッチ入力が不安定
対策:
- プルアップ/プルダウン: 内部プルアップを有効化
pinMode(pin, INPUT_PULLUP) - チャタリング除去: ソフトウェアでデバウンス処理を追加
- 配線: 入力ピンがフローティングになっていないか確認
まとめ
ESP32とMCP23017を使ったI/O拡張の実装方法を解説しました。
本記事のポイント
- MCP23017は16ピンをI2C通信で追加できる強力なI/Oエキスパンダー
- 最新Adafruit_MCP23X17ライブラリで簡単に制御可能
- 最大8個接続で128ピンまで拡張可能
- 内部プルアップや割り込み機能など、高度な機能も搭載
- LED制御、スイッチ入力、センサー集約など幅広い用途に対応
次のステップ
- 複数のMCP23017を接続して、さらに多くのピンを制御
- 割り込み機能を使って、効率的なイベント駆動プログラミング
- SPI版のMCP23S17も検討(高速通信が必要な場合)
MCP23017を使えば、ピン不足の悩みから解放され、より大規模で複雑なプロジェクトに挑戦できます。
それでは、良き電子工作ライフを!