ℹ️ ご注意
本記事で使用している MCP23017 のライブラリ Adafruit_MCP23017.h は旧ライブラリです。
新ライブラリ <Adafruit_MCP23X17.h> を使用した記事もあります:
👉 新ライブラリを使った電子工作はこちら

I/Oエキスパンダー MCP23017を使う

I/Oエキスパンダーとは?

マイコンを使っていて I/O ピンが足りなくなった経験はありませんか?
LEDを大量に使用したい場合やスイッチの入力点数が多い場合に便利なのが I/Oエキスパンダー です。
I/Oエキスパンダーを使うことで単純な入出力はI/Oエキスパンダーに、AD変換でやPWMなど複雑な処理はマイコンのピンにさせるなど、用途によって使い分けることによって効率よくマイコンを使用することができます。

そこで、今回使用するのは「MCP23017」という素子です。

秋月電子で購入


MCP23017の仕様確認

「MCP23017」のデータシートを確認していきましょう。 MCP23017 : データシート

MCP23017 の仕様は以下の通りです:

ピンアサイン

ピンアサイン

  • 通信方式:I2C
  • 駆動電圧:1.8V ~ 5.5V
  • 入出力:Aポート・Bポート 各8本、合計16本
  • 最大8個接続可能(アドレスA0, A1, A2 により)

I2C のアドレス構成は以下の通りです:

A0 A1 A2 アドレス ライブラリ指定
0 0 0 0x20 0x00(省略可)
1 0 0 0x21 0x01
0 1 0 0x22 0x02
0 0 1 0x23 0x03
1 1 0 0x24 0x04
1 0 1 0x25 0x05
0 1 1 0x26 0x06
1 1 1 0x27 0x07

他のI2C機器のアドレス競合がなければ、2x2x2の計8個の素子を接続することができます。   I2CのSDA.SCLの2本の信号線で8個の素子、それぞれに16個のIO。

16x8の計128個のI/Oが増設可能となります。

これだけあったら簡単な電子工作ではそうそう困ることもないでしょう。   レジスタの設定をすることで入出力の管理だけでなく内部プルアップが可能であったり割り込み出力などいろいろとできることが多いです。


回路の作成

今回、MCP23017の試験のために作成した、スイッチ入力3点、LED出力8点の回路です。

回路図

回路図

アドレス設定用の入力3ポートにはプルダウン抵抗を入れたスイッチを、出力は8ポートでLEDにつながるようになっています。

ブレッドボードに組むと以下のようになりました。

ブレッドボードへの実装

ブレッドボードへの実装


プログラムの作成

#include <Wire.h>
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp;
int sw1, sw2, sw3;

void setup() {
  delay(1000);
  Serial.begin(115200);
  Wire.begin();
  mcp.begin();  // アドレスが0の場合は省略可能

  // 出力ピン設定
  for (int i = 0; i < 8; i++) {
    mcp.pinMode(i, OUTPUT);
  }

  // 入力ピン設定
  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(sw2); Serial.println(sw3);

  if (sw1 == 1 && sw2 == 0 && sw3 == 0) {
    Serial.println("mode1");
    for (int i = 0; i < 4; i++) mcp.digitalWrite(i, 1);
    for (int i = 4; i < 8; i++) mcp.digitalWrite(i, 0);
  } else if (sw1 == 0 && sw2 == 1 && sw3 == 0) {
    Serial.println("mode2");
    for (int i = 0; i < 4; i++) mcp.digitalWrite(i, 0);
    for (int i = 4; i < 8; i++) mcp.digitalWrite(i, 1);
  } else if (sw1 == 0 && sw2 == 0 && sw3 == 1) {
    Serial.println("mode3");
    for (int i = 0; i < 8; i++) mcp.digitalWrite(i, 1);
  } else {
    Serial.println("mode0");
    for (int i = 0; i < 8; i++) mcp.digitalWrite(i, 0);
  }
  delay(10);
}

関数解説

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

  • mcp.pinMode(pin, mode):ピンのモード設定(0〜7が出力, 8〜15が入力
    それぞれのピンの入出力モードを設定します。 numにはピン番号を設定します。GPA0~GPA7は0~7に、GPB0~7は8~15にそれぞれ対応しています。 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 の基本的な入出力制御が可能となりました


まとめ

今回I/Oエキスパンダー:MCP23017とArduinoIDEで使うための「Adafruit_MCP23017.h」の使い方について学ぶことができました。

  • MCP23017 を使うことで簡単に I/O を増設可能。
  • Arduino IDE でも Adafruit_MCP23017.h ライブラリを使えば簡単に操作できる。
  • 1つのマイコンで最大128個のI/O拡張が可能となり、非常に効率的。

今回はLEDへの出力をしていますが、モータなどの動力、リレーやセンサー入力など、さまざまな用途に応用ができると思います。 I/Oが大量に増やすことができたら、開発の幅もすごく広がると思います。

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