今回は、MCP23017通称IOエキスパンダについてのご紹介です。
なんだかんだRaspberryPiって入出力端子が豊富に見えて、
いざやりたいことを考えると、端子が足りなくなることありませんか?
そんなときにこのMCP23017があると、
なんと最大128点の入出力端子を増やすことができます。
今回は「出力端子を増やす方法」について詳しく解説していきます。
入力端子を増やす方法については長くなってしまう関係上、
別記事で掲載する予定です。
RaspberryPiでIO出力制御できる本数を増やす方法がわかる。
Youtubeチャンネルにさまざまな動画を上げています。
↓↓↓こちらからYoutubeチャンネルにアクセス!! ↓↓↓
MCP23017とはそもそもなんなのか?
MCP23017はMICRO CHIP社が製造しているIOエキスパンダと呼ばれるICです。簡単に言うと、RaspberryPiのGPIOピンを増設できます。
つまり、GPIOが足りなくなっても、このIOエキスパンダがあれば、制御できるIOの数が増やせるということです。
こちらはI2C通信で制御しますが、兄弟機種として、MCP23S17というSPI通信で制御するICもあります。違いは、MCP23Sなのか、MCP230なのかです。型番を見間違いやすいので、購入するときはかならず確認しましょう。
今回はI2C制御のMCP23017のみご紹介します。
Amazonをはじめとした通信販売でも一応購入可能です。↓↓↓
MCP23017とRaspberryPiはどうつなぐ?
続きまして、配線方法です。
今回はGPAの0番にLEDを接続して光らせます。
データシートにも記載されていますが、一応MCP23017のピン配置を載せておきます。
切り欠きの向きだけ注意してくださいね。
線の本数がそれなりに多くなっているので、配線ミスに注意してください。
今回はI2Cのアドレスが0x20となるように配線しています。
RaspberryPi側でMCP23017を認識してみる。
正しく接続できたら、まずはRaspberryPi側で認識されたかチェックです。
LXターミナルに、
i2cdetect -y 1
と打ち込んでください。
こちらのように20番が表示されたらOKです。
PythonでMCP23017のピンを出力する方法。
MCP23017のデータシートから必要な情報を調べる。
MCP23017のデータシートはこちらにあります。
まずはダウンロードしておきましょう。※データシートは必ず読みましょう。
http://ww1.microchip.com/downloads/jp/DeviceDoc/20001952C_JP.pdf必要なところだけ抜粋して紹介しますが、
必要なのは次の3か所です。
ハードウェア アドレスデコーダ
こちらについては、別記事で詳しく書いています。
MCP23017の複数台つなげた場合のアドレスについて書いていますが、
アドレスが決まる原理なども書いてありますので、そちらを参考にしてみてください。
I/O方向レジスタ
こちらは、MCP23017の各IOピンが入力なのか出力なのか、
決めてあげるためのレジスタです。
今回はA0しか使用しないので、IODIRAつまり、0x00しか使用しません。
B0~B7まで使用する場合は、別途IODIRB:0x01も定義してあげる必要があります。
具体的に方向を決める方法ですが、
大前提としてのルールは、
となっています。
今回の例としては、A0ピンを出力としたいので、
0000000
つまり0x00が適用されます。
同様に、例えば4番ピンだけ入力で、他を出力にしたい場合は、
00010000
上記binをhexに変換すると、0x10となります。
ポートレジスタ
最後にポートレジスタです。
これがピンのON/OFFにかかわるところです。
具体的には、I/O方向レジスタと同様に、こちらのルールがあります。
並べ方はI/O方向レジスタとまったく同じです。
今回の例として、A0ピンをHigh(3.3V)にしたいので、
00000001
つまり0x01です。
例えば7番ピンから5番ピンまでHigh(3.3V)としたい場合は、
11100000
hexになおすと、0xE0になります。
Pythonのソースコード
import smbus
import time
CHANNEL = 1 # i2c割り当てチャンネル 1 or 0
I2CADDR = 0x20 # MCP23017のアドレス。この場合はA0~A3までGND接続した場合のアドレス。
REG_IODIRA = 0x00 # 入出力設定レジスタ
REG_GPIOA = 0x12 # 出力レジスタ
bus = smbus.SMBus(CHANNEL) #smbusを定義
# ピンの入出力設定
bus.write_byte_data(I2CADDR, REG_IODIRA, 0x00) #データシートより、0:出力
def loop():
while True:
# GPA0をONする
bus.write_byte_data(I2CADDR, REG_GPIOA, 0x01)
time.sleep(1)
# 全出力OFF
bus.write_byte_data(I2CADDR, REG_GPIOA, 0x00)
time.sleep(1)
# Ctrl+Cキーで入る。
def destroy():
print('end')
# main
if __name__ == '__main__':
print ('Program is starting...' )
try:
loop()
# ターミナル上でCtrl+Cでloop()を中断
except KeyboardInterrupt:
destroy()
importのsmbusが通らない場合は、
sudo apt install python-smbus
とLXターミナルから打ち込んでおきましょう。
また、今回はMCP23017のI2Cアドレスですが、
A0~A3ピンをすべてGND接続していることを想定しているので、
0x20となります。今後複数台のMCP23017を接続したくなった場合は、
こちらの記事のようにアドレスを変更するように気を付けてください。
ちょっとクセがあるとしたら、
bus.write_bite_dataの時の最後の引数でしょうか。
bit7始まりですから、GPIOのAの0番をHIGHにする場合は0b00000001となり、
7番をHIGHにする場合は、0b10000000となります。
最後にbinをhexに変換する必要があります。
7番だけHIGHにする例だと、0b10000000なので、
0x80ですね。
すべてのピンをHIGHにする場合は、
0b11111111なので、
0xFFとなります。
その計算も関数にしてあげるともっと使いやすくなると思います。
そこらへんをスッキリさせたVer.もそのうち作って公開する予定です。
まとめ
今回はRaspberryPiのGPIOが足りなくなった場合の、
増設方法についてMCP23017を使って説明しました。
最大128点も追加できると考えると、だいぶ心強いですよね。
次回は、入力側を増やす方法について説明していきます。
おそらく今回の内容が理解できていればすぐに理解できるはずです。
コメント
コメント失礼いたします。
現在、ラズベリーパイ4にてSPI通信の方のMCP23S17を使用していて、こちらのサイトのようにLEDを点滅させるためにPythonコードを参考にさせてもらったのですが、上手くいきませんでした。
以下が実行させたプログラムになります。ほかのサイトも調べてみたのですが解決すことはできませんでした、どうか力を貸していただきたいです。よろしくお願いいたします。
import spidev
import time
#初期設定
spi = spidev.SpiDev()
spi.open(0,0)
spi.mode = 0
spi.max_speed_hz = 1000000
Control_Byte = 0x40
REG_IODIRA = 0x00 #入出力設定レジスタ
REG_GPIOA = 0x12 #出力レジスタ
spi.xfer2([Control_Byte,REG_IODIRA,0x00]) #出力
# spi.xfer2([Control_Byte,0x05,0xB4]) #出力
try:
while True:
spi.xfer2([Control_Byte,REG_GPIOA,0x01]) #ON
time.sleep(1)
spi.xfer2([Control_Byte,REG_GPIOA,0x00]) #OFF
time.sleep(1)
except KeyboardInterrupt:
pass
コメントありがとうございます。
mcp23017のSPI通信版ですね。手元にあったはずなので引っ張り出してコード付きで解説記事を作りますので少々お待ちください。
ご提示していただいたコードでも動作することは確認できました。
恐らく配線関係の問題が起こっていると推察されます。
やっていくうちに、I2Cとはアドレスの設定が若干違うところがわかりましたので、
そちらについても記事にいたします。
少々お待ちください。