マイコンを使った電子工作をやっていると、マイコンボードのI/O(デジタル端子)が不足してしまいどうしたものかと悩むことが稀にあります。
多くのLEDを点灯制御させたい場合やスイッチなどの入力デバイスが多数必要な時などです。
先日このようなArduinoをベースとした無線コントローラーを製作しました。
電子工作でこれまで製作したものやこれから作るであろうものを動かすことを想定して、現時点で考えられる機能を全て取り入れたコントローラーとなります。
この投稿をInstagramで見る
ジョイスティックやタクトスイッチ、ポテンショメーター、ディスプレイや加速度センサーなどのI2C機器・・・多くのI/O端子を使う製作物となりました。
メインとなるマイコンは最終的にArduino Nanoを使って制御する形としましたが、その製作過程でArduinoで使えるI/O端子のやりくりは結構悩みました!
Arduino Nanoで使えるI/O端子は、デジタル入出力端子としてD0~D13の計14本、そしてアナログ端子A0~A7の計8本はアナログ入力以外にデジタル入出力端子として使うことも出来るので、合計すると最大22本をI/O端子として使える計算になります。
これだけ見ると結構多くの端子を使えるように感じますが、上記のような製作物の場合、多くの入力装置やその他デバイスとの接続で結構ギリギリの数となります。
Arduinoでは多くのI/O端子を使いたい場合にはArduino Megaというボードもありますが、上記コントローラーにはサイズ的に当然収めることが出来ません。
このように多くのI/O端子を使いたい場合、使用するマイコンボードによっては足りなくなってしまうことがあります。
このような場合に役立つのが『I/Oエキスパンダー』です。
マイコンボードに搭載されているI/O端子だけでは足りない場合に、単純にその数を増設することが出来る便利なIC(チップ)となります。
上記コントローラー製作時に試していたのですが、I/Oエキスパンダー(MCP23017)を1本Arduinoに接続することにより16本のI/O端子を増設(追加)する事が出来ます。
接続もI2C(またはSPI)での接続となるので、Arduino側で使う端子は2本だけですんでしまいます。
Arduino側の余ったI/O端子にプラスしてさらに16本もの端子を増やして使うことが出来るようになります。
上記コントローラーの製作では最終的に上手くI/O端子をやりくりして何とかArduino Nanoで使える22本のI/O端子を全て使うことにより完成させることが出来ましたが、I/O端子の数が元々少ないマイコンボードに使えば非常に有効な手段になると思います。
限られた数のI/O端子しか持たないESP8266のようなボードでは特に便利に使うことが出来ると思います。
Wemos D1 Mini(ESP8266)で動かす『ESPboy』というオープンソースの携帯ゲーム機も最近作りました。
Wemos D1 MiniはESP8266開発ボードとして非常に有名なボードですが、ミニサイズの開発ボードなのでそれほど多くのI/O端子が付いていません。
これもI/Oエキスパンダーを使うことにより使えるI/O端子の数を増やして上手くミニサイズに収めています。
このようにマイコンボードを使っていてI/O端子が足りない場合や使用するマイコンボードにより意図的にI/O端子を増やしたい場合に『I/Oエキスパンダー』は非常に役立ちます。
今回この『I/Oエキスパンダー』をArduinoと接続してI/O端子を増やす基本的な方法を見ていきたいと思います。
目次
IOエキスパンダー(MCP23017-E/SP)の基本的な使い方
『I/Oエキスパンダー』について冒頭の説明で雰囲気伝わったかと思います。
I/Oエキスパンダーとして使われるチップ(IC)にはいろいろとあるようですが、「MCP23017-E/SP」というチップを使ってみたいと思います。
MCP23017には表面実装タイプのものもありますが、ブレッドボードでも使えるようにDIP型のものを今回使います。
MCP23017はI2C接続により制御するチップですが、SPIで制御するタイプのMCP23S17というチップもあるようです。
I/Oエキスパンダー MCP23017-E/SP
こちらがI/Oエキスパンダーチップ MCP23017-E/SPです。
ブレッドボードに挿して使えるようにDIP型のものを使っています。
28ピンタイプのICとなり、DIP型のものなら安価で比較的入手もしやすいチップとなります。
MCP23017はI2C接続によりマイコンから制御します。
またSPIで制御するMCP23S17というチップもあります。
機能的には全く同じですが、2本の未使用ピン(11ピン/14ピン)がSPIインターフェイスで接続ができるように変更されているようです。
SPI接続なのでI2Cと比べると高速に動作させることが出来るようですね。
今回はI2C接続タイプのMCP23017の方を使っていきます。
MCP23017はArduinoなどのマイコンボードとI2C接続する事により、入出力端子(I/O)を16個拡張することが出来るICとなります。
またMCP23017にはA0/A1/A2の3本のアドレスピンが用意されています。
I2Cデバイスなのでアドレスを変えることにより複数のMCP23017を接続する事が出来るので、さらに多くのI/O端子を増設する事も出来ます。
3本のアドレスピンがあるので2の3乗(2×2×2=8)、つまり8本のMCP23017を接続しI2Cにより制御する事が可能となるので、トータルすると16×8となり最大128本のI/O端子を増設することも可能となります。
MCP23017-E/SP 仕様
MCP23017-E/SPの仕様について簡単に見ておきます。
こちらがMCP23017のピンアサインです。
MCP23017はマイコンとの接続にI2Cを用いて行います。
駆動電圧は1.8~5.5Vとなっているので、Arduino(5V)以外にもESP(3.3V)などのマイコンボードでも扱うことが出来ます。
増設する入出力端子はAポート(GPA0~GPA7)とBポート(GPB0~GPB7)それぞれ8本ずつの合計16本の入出力端子を増設して使うことが出来るようになっています。
MCP23017を使う最も簡単な方法はライブラリを使ったやり方です。
『Adafruit MCP23017 Arduino Library』ライブラリを使った方法で進めていきます。
今回使う部分を色分けしておきます。
増設するI/O端子(GPA0~GPA7/GPB0~GPB7)とArduinoとのI2C接続端子(SCK/SDA)、そしてI2Cアドレス設定用端子(A0/A1/A2)、MCP23017を駆動するための電源(VDD/VSS)に別れます。
秋月電子さんのサイトにMCP23017のデータシートがあったのでこちらも参考にして下さい!
参考 MCP23017 PDFデータシート秋月電子通商I2Cアドレスの設定
MCP23017はI2Cデバイスなので、その制御にはまずI2Cアドレスを知っておく必要があります。
ライブラリを使った方法だと指定するアドレスが異なってきますが、ライブラリを使わずレジスタを指定して組むなんて時は必要となってくるので合わせて見ておきます。
I2Cアドレスの設定はA0/A1/A2端子を使って行います。
この3つのアドレスピンをHIGH or LOWに設定する事によりアドレスが決定されます。
データシートを見るとI2Cアドレスの設定はこのように決められます。
上位ビットは固定され下位3ビット(A2/A1/A0)を使いアドレスの設定を行います。
ArduinoのI2C接続では7bitを使用しR/Wは使用しません。
上位ビット | 下位ビット | ||||||
(0) | 0 | 1 | 0 | 0 | A2 | A1 | A0 |
これによりI2Cアドレスは以下の表のようになるのですが・・・
実はこのアドレスの設定なんですが、ライブラリを使うと少し変わってきます。
『Adafruit MCP23017 Arduino Library』ライブラリを使用する場合のアドレス指定は、単純にA2/A1/A0の3bitを指定することで接続が出来るようになっています。
こちらの方が分かりやすいですね!
アドレスをまとめるとこのようになります。
今回はライブラリを使って接続を行うので右側のアドレスを使うことになります。
このアドレス変えることにより複数台接続したMCP23017をI2Cデバイスとして認識するということですね!
A2 | A1 | A0 | アドレス | ライブラリ使用 |
0 | 0 | 0 | 0x20 | 0x00 |
0 | 0 | 1 | 0x21 | 0x01 |
0 | 1 | 0 | 0x22 | 0x02 |
0 | 1 | 1 | 0x23 | 0x03 |
1 | 0 | 0 | 0x24 | 0x04 |
1 | 0 | 1 | 0x25 | 0x05 |
1 | 1 | 0 | 0x26 | 0x06 |
1 | 1 | 1 | 0x27 | 0x07 |
ArduinoのI2C接続に関しては、こちらの記事も参考にして下さい!
Arduinoとの接続
それではArduinoとの接続です。
Arduino Unoとの接続を例とします。
MCP23017を駆動するための電源はArduinoの[5V端子]から取ります。
VDDを[5V端子]、VSSをGNDに接続します。
次にI2Cでの接続部分。
Arduino UnoのI2C端子(SCK/SDA)は、アナログ入力端子A4(SDA)、A5(SCK)となります。
動作には問題ありませんが、 通信を安定させるために数kΩの物理プルアップ抵抗を接続しておくのもいいと思います。
そしてI2Cアドレスの設定です。
I2Cアドレスは先述のようにA0/A1/A2端子を使います。
今回はMCP23017を1台のみ接続するので、どのアドレスを使ってもいいのですが3本ともGNDに落としてアドレス[0x00]を使うことにします。(任意に変更出来ます)
最後に[RESET]端子です。
リセットされるのを防ぐために、[RESET]端子をHIGH(5V)の状態にしておきます。(LOWに落とすとリセットされます)
これがArduinoとの基本的な接続方法となります。(他のマイコンボードでも同様です)
マスターとなるArduinoにスレーブ端末としてMCP23017が1台接続されている状態です。
非常に簡単ですね。
MCP23017 | Arduino |
VDD | 5V |
VSS | GND |
SCK | SCK(A5) |
SDA | SDA(A4) |
A2 | GND |
A1 | GND |
A0 | GND |
RESET | 5V |
Arduino側で使うI/O端子はI2C接続の2本(SCK/SDA)のみですが、これでMCP23017側のGPA0~GPA7/GPB0~GPB7までの合計16本のI/O端子を使うことが出来ます。
Arduino側の残ったI/O端子にプラスしてMCP23017側の16本のI/O端子が使えるようになるので、一気に使える端子が増えることになります!
Adafruit MCP23017ライブラリのインストール
それではテストで簡単なスケッチを動かしてみたいと思いますが、その前にライブラリをインストールしておきます。
使用するライブラリは『Adafruit-MCP23017-Arduino-Library』です。
Arduino IDEの[スケッチ]→[ライブラリをインクルード]→[ライブラリを管理]へと進みます。
[MCP23017]で検索すると『Adafruit MCP23017 Arduino Library』が見つかります。これをインストールして完了です!
I/O端子 出力テスト
それでは簡単な動作テストをしてみます。
ライブラリを使用する場合、スケッチは非常に分かりやすくて簡単です。
Arduinoのデジタル端子を扱う際に使う以下関数がそのまま使えます。
・pinMode();
・digitalWrite();
・digitalRead();
そしてライブラリを使う場合、MCP23017のI/O端子のピン番号の割り振りはこのようになります。
【例】GPB6端子を出力端子として使いたい場合、mcp.pinMode(14, OUTPUT);となります!
それではMCP23017のGPB0~GPB7に接続した8本のLEDを点灯させてみます。
数が多いので実際に試される場合は数本接続すれば動作確認は出来ると思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // Arduino入門編㉚ I/OエキスパンダーMCP23017を使ってみる! // https://burariweb.info // デジタル出力のテスト #include <Wire.h> // ライブラリのインクルード #include "Adafruit_MCP23017.h" Adafruit_MCP23017 mcp; // MCPライブラリのオブジェクトを作成 void setup() { Wire.begin(); mcp.begin(); // MCP23017のI2Cアドレスを0x00に設定(0x00は省略可) for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)を出力に設定 mcp.pinMode(i, OUTPUT); } } void loop() { for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)に接続されたLEDを点灯 mcp.digitalWrite(i, HIGH); delay(30); } for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)に接続されたLEDを消灯 mcp.digitalWrite(i, LOW); delay(30); } } |
スケッチ解説
簡単にスケッチ内容を見ておきます。
まず使用するライブラリのインクルードです。
公式のI2C用ライブラリとなる「Wire.h」ライブラリも使います。
Arduino内部でプルアップが行われるので、外部プルアップ抵抗は今回付けていません!
5 6 | #include <Wire.h> // ライブラリのインクルード #include "Adafruit_MCP23017.h" |
MCPライブラリで使うオブジェクトの作成です。
7 | Adafruit_MCP23017 mcp; // MCPライブラリのオブジェクトを作成 |
MCP23017とのI2C通信を開始(初期化)します。
今回の接続ではアドレスピンA2/A1/A0は全てGNDに接続しているのでアドレスは0x00となります。
mcp.begin(0x00);と記述してもいいのですが、0x00の場合省略が可能です。
MCP23017を複数接続する場合や他のI2Cデバイス接続のために任意に変更したい場合は指定します。
【例】mcp.begin(0x02);
11 12 | Wire.begin(); mcp.begin(); // MCP23017のI2Cアドレスを0x00に設定(0x00は省略可) |
【例】
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp2;
Adafruit_MCP23017 mcp3;
mcp1.begin(アドレス1);
mcp2.begin(アドレス2);
mcp3.begin(アドレス3);
ピンモードの設定です。
入力(INPUT)または出力(OUTPUT)を設定します。
14 15 16 | for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)を出力に設定 mcp.pinMode(i, OUTPUT); } |
【例】
GPA0を出力で使用する場合、mcp.pinMode(0, OUTPUT);
GPB7を入力で使用する場合、mcp.pinMode(15, INPUT);
指定した端子の出力を設定。
22 23 24 | for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)に接続されたLEDを点灯 mcp.digitalWrite(i, HIGH); delay(30); |
【例】
GPB4をHIGHにする場合、mcp.digitalWrite(12, HIGH);
ライブラリ使用部分以外は通常のデジタル端子の扱いと同じなので簡単ですね!
この投稿をInstagramで見る
アドレスを変えてみる
I2Cアドレス確認のために、A0/A1/A2を全てHIGH(5V)に接続してみて下さい。
上記スケッチをそのまま動かせばLEDはうまく点灯しませんが、mcp.begin(0x07);に変更すると上手く動作することが確認できると思います。
I/O端子 入力テスト
ライブラリを使うと通常のデジタル端子とほぼ同じ感覚で使えるため簡単で便利ですね!
次に入力端子としてのテストもしておきます。
これも通常のデジタル端子の扱いと同じなのですが、プルアップして使う場合に少し注意が必要となります。
Arduinoには内部プルアップ機能が付いています。
例えば入力端子にスイッチを接続して使う場合に、pinMode(ピン番号, INPUT_PULLUP);このように記述しておけばArduino内部のプルアップ抵抗が有効になるため、外部にプルアップ抵抗を接続する手間が省けます。
Arduinoのプルアップ・プルダウンに関しては、こちらの記事を参考にして下さい!
MCP23017にもプルアップ機能が付いているので、
mcp.pinMode(ピン番号, INPUT_PULLUP);と記述したいところなんですが・・・
これでは上手く動作してくれません!
入力端子としてプルアップ抵抗を有効にしたい場合には、以下のように記述します。
あとは通常のデジタル入力端子と扱いは同じです。
mcp.pinMode(ピン番号, INPUT);
mcp.pullUp(ピン番号, HIGH);
それでは先程の回路にタクトスイッチを1本追加して、スイッチが押されたらLEDが点灯するようにスケッチを修正します。
タクトスイッチは空いているGPA0に繋げました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | // Arduino入門編㉚ I/OエキスパンダーMCP23017を使ってみる! // https://burariweb.info // デジタル入力のテスト #include <Wire.h> // ライブラリのインクルード #include "Adafruit_MCP23017.h" Adafruit_MCP23017 mcp; // MCPライブラリのオブジェクトを作成 void setup() { Wire.begin(); mcp.begin(); // MCP23017のI2Cアドレスを0x00に設定(0x00は省略可) for (int i = 8; i <= 15; i++){ // 8~15(GPB0~GPB7)を出力に設定 mcp.pinMode(i, OUTPUT); } mcp.pinMode(0, INPUT); // 0(GPA0)をプルアップして入力に設定 mcp.pullUp(0, HIGH); } void loop() { if(mcp.digitalRead(0) == 0){ // 入力の判定 LED_ON(); } else { LED_OFF(); } } void LED_ON(){ for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)に接続されたLEDを点灯 mcp.digitalWrite(i, HIGH); } } void LED_OFF(){ for (int i = 8; i <= 15; i++) { // 8~15(GPB0~GPB7)に接続されたLEDを消灯 mcp.digitalWrite(i, LOW); } } |
スイッチが押されたら8本のLEDが点灯する事が確認できると思います。
簡単なテストですが、16本全てのI/O端子に入出力の設定ができ個別で扱うことが出来るので非常に便利となります。
I2Cでの接続なのでArduino側で使う端子はSCK/SDAの2本だけと少なく、簡単に16本のI/O端子を増やすことが出来ますね。
アナログ入出力(analogRead()やanalogWrite())などには対応していません!
I/O端子が少ないマイコンボードで有効に使えます!
MCP23017を使ってデジタル端子を増やし入出力で動かすことが出来ました。
digitalRead()やdigitalWrite()などのデジタル関数を扱うことができ、通常のデジタル入出力端子と同様に使えるので便利ですね。
Arduino Unoを使った簡単な動作テストなのでI/O端子が増えたことの恩恵があまり伝わらないかと思いますが、冒頭でご紹介したコントローラーのような多くのI/O端子が必要となる場合に便利となります。
また、もともとI/O端子の数がそれほど多くないマイコンボードでは非常に有効な手段となります。
先程の回路をESP-01(ESP8266)に繋げて動かしてみました。
この投稿をInstagramで見る
ESP-01は使えるI/O端子が4本しかありませんが、そのうち2本をI2C端子(SCK/SDA)に割り振ることにより同様な方法で簡単に使えるI/O端子の数を増やすことが出来ます!
これは非常に便利ですね!
今回のポイント
- MCP23017はArduinoとのI2C接続により使えるデジタル端子(I/O)を増やすことが出来る!
- ライブラリを使う場合のアドレスは下位3bit(A2/A1/A0)となり、0x00~0x07となる!
- 入力端子として使う場合のプルアップ方法は注意が必要!
- MCP23017はデジタル専用デバイス(チップ)となりアナログ入出力には対応していない!
今回使ったアイテム
Arduino UNO
Arduinoはオープンソースハードウェアなので正規品以外にも互換品が多数販売されています。
互換品でも正規品と比べて特に問題なく使用でき安価なためArduino学習用としていいと思います。
Elegoo製のArduinoボードは、互換ボードの中でも非常にクオリティーが高く本家ボードと遜色なく使えるのでおすすめです!
Arduino スターターキット
これからArduino学習を進めていくにあたりArduino UNO(互換品)やブレッドボード、ジャンパーピンなどがセットになったスターターキットが販売されています。
私はGeekcreit製のスターターキットを使っていますが、ELEGOO製のものは国内Amazonなどでも購入可能で人気があるようです。(セット内容はほぼ同じです!)
そしてELEGOOのサイトからスターターキット用サンプルスケッチのダウンロードも可能です。(Geekcreitのキットでも使えます)
参考 チュートリアルダウンロードELEGOO基本的にこれからこのセットで出来るものから紹介していこうと考えていますが、かなり多くのことが出来ます。
電子工作を始めるにはまずブレッドボードやジャンパーピン、メインとなるArduino UNOやサーボ、LEDなどの基本的なパーツがないと実際に動かすことが出来ませんが、個々にパーツを購入して回路を組んでとなるとかなりの手間がかかります。
スターターキットがあればArduinoの初歩的なことはかなりの数こなすことが出来るのでオススメです!
そこからスキルアップに伴い個別でセンサーやモジュールなど必要なものを増やしていくのがいいと思います。
最近の半導体不足による価格高騰によりArduinoボードも以前と比べ非常に割高感があります。
上記Elegoo製Arduino互換ボードも私が購入していた時より倍近くの価格まで高騰しているようです。
これからArduinoを始めてみようとお考えの方は、価格的にもお得感があるArduinoスターターキットから始めてみるのがいいかと思います。
I/Oエキスパンダー MCP23017
今回使ったI2C接続タイプのものは型番がMCP23017のものとなります。
同性能のSPI接続タイプのMCP23S17もあります。
最後に!
Arduinoの場合、比較的多くのI/O端子が用意されているので足りなくなることは滅多にありませんが、製作するものによってはより多くのI/O端子が必要となってくる場合もあると思います。
今回の例のように多くのLEDを点灯させたいだけなら、シフトレジスタを使ったりPCA9685のようなドライバを使っても実現することは出来ますが、通常のデジタル入出力端子のように簡単に扱うことが出来るのは便利です。
またESP系のマイコンボード、特にESP8266では限られた数のI/Oしか持たないボードも多いので、これは非常に有効な手段になるかと思います。
以前テストしてみて使う機会がなかったことから長らく眠っていたチップなんですが、こんなところで役に立つとは思ってもいませんでした。
マイコンボードのI/O端子が足りない・・・
多くのI/O端子が使えるボードに構成を変えるか?シールドやドライバボードを使うか?
そのような時の選択肢の一つとして使えるので便利だと思います。
コメントを残す