I/O Expander

Raspberry PiのGPIOには17ビット分のI/Oピンが存在しているが、他の機能と兼用になっているピンも多いため、17ビット全てを使用する事ができない場合もある。

I/Oが不足した時にそれを拡張する方法は何種類かあって、I/O拡張チップを使うのがそのうちの一つ。Microchip社のMCP23017はI2C接続で16bitのI/Oポート拡張ができる。

比較的入手が容易で、このチップを搭載した基板も出ているので試しやすい。一個では16bitまでだが、I2Cバスに8個まで同時に接続できるので、最大で128bitの拡張が可能だ。出力ポートのラッチや、入力ポートのプルアップ、割り込み機能もある。

今回はこのキットを使用したが、表面実装ICのハンダ付けが必要なので慣れていないと組み立ては難しいかも知れない。実装サービスを利用するか、DIPタイプを入手してブレッドボードで試すという手もある。DIPタイプはマルツや共立エレショップで入手可能。

Raspberry PiのI2Cポート(SCL/SDA)と基板のSCL/SDAピンを接続し、MCP23017のポートAのA0とA1にLED、ポートBのB0にタクトスイッチを接続した。スイッチは押すとGNDに接続されるようにしてある。
2013-05-23 11.23.46

このままだとスイッチが押されていない時は入力が開放状態となり、値が不安定になるので初期設定で内蔵プルアップが有効になるようにしてある。プログラムは以下の通り。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import smbus
import time

class i2c:
    def __init__(self, bus, addr):
        self.b = smbus.SMBus(bus)
        self.addr = addr
    def put(self, cmd, data):
        self.b.write_byte_data(self.addr, cmd, data)
    def get(self, cmd):
        return self.b.read_byte_data(self.addr, cmd)

class MCP23017(i2c):
    def __init__(self, porta, portb):
        i2c.__init__(self, 1, 0x27)
        i2c.put(self, 0x05, 0x00)   # Config
        i2c.put(self, 0x00, porta)  # PortA I/O Set
        i2c.put(self, 0x01, portb)  # PortB I/O Set
    def invert(self, port, data):
        i2c.put(self, 0x02 + port, data)    # Invert Input Bit
    def pullup(self, port, data):
        i2c.put(self, 0x0C + port, data)    # Pull-Up Input
    def write(self, port, data):
        i2c.put(self, 0x12 + port, data)
    def read(self, port):
        return i2c.get(self, 0x12 + port)

if __name__ == '__main__':
    try:
        expand = MCP23017(0xFC, 0xFF)
        expand.pullup(1, 0x01)
        expand.invert(1, 0x01)
        blink = False
        ss = expand.read(1) & 0x01
        while True:
            sw = expand.read(1) & 0x01
            if ss != sw:
                blink = not blink if sw else blink
                if sw:
                    print 'Blink Start' if blink else 'Blink Stop'
                ss = sw
            if blink:
                expand.write(0, 0x01)
                time.sleep(0.5)
                expand.write(0, 0x02)
                time.sleep(0.5)
    except KeyboardInterrupt:
        print '\nbreak'

プログラムを実行するとスイッチが押されるまで待機して、押されるとLEDを交互に点滅、再びスイッチを押すと点滅が停止する。

線2本(VCCとGNDで4本)だけで16bitのI/O拡張が可能で、必要なら更に増やすこともできる。値段も200円以下と安価なので、GPIOのI/Oピンだけでは不足するような場合に役立つだろう。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中