I/O Expander(2)

I2C接続のI/O拡張チップMCP23017をRaspberry Piに接続して、I/Oポートを16bit分増やすことができたので、試しにそのポート全てにLEDをつなげてみた。R0012002

写真の最も右側のLEDが拡張ポートBのB7、最も左のLEDが拡張ポートAのB0になるように接続してある。LEDの+極が電流制限抵抗を介してVCCにつながっているので、拡張ポートの出力を0にするとLEDが点灯、1にするとLEDが消灯する。

これを見ただけで分かる人には何をやろうとしているか判ると思うが、残像によって空間に文字や図形を描くPOV(Persistent Of Vision)またはバーサライタと呼ばれるものをRaspberry Piで試してみようと思った次第。

実際に暗い所でこれを左右に振ると、こんなふうに見える。
R0012001表示したい図形を縦一列ごとに高速に切り替えて表示しているから、左右に振ると残像で元の画像が見える。

プログラムは前回のテストプラグラムとほとんど同じで、表示する図形データを順番に読み込んでMCP23017のポートAとポートBに書き込んでいるだけ。負論理でLEDが点灯するようになっているので、図形データは予めビット反転させてある。

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

import smbus
import time

pb = (0x80,0x80,0xFC,0xFC,
      0xFC,0x80,0x80,0x80,
      0xFF,0xFF,0xFC,0xF8,
      0xF9,0xF9,0xF8,0xFC,
      0xFF,0x80,0x80,0xFF,
      0xFF,0x80,0x80,0xFF,
      0xFF,0xFC,0xF8,0xF8,
      0xF1,0xF8,0xF8,0xFC,
      0xFF,0xFF,0xFF,0x80,
      0x80,0x9E,0x9E,0x8E,
      0x80,0xC0,0xF1,0xFF,
      0x88,0x88,0xFF,0xFF)
pa = (0x01,0x01,0xFF,0xFF,
      0xFF,0x03,0x01,0x01,
      0xFF,0x0F,0x03,0x03,
      0x31,0x21,0x23,0x27,
      0xFF,0x01,0x01,0xFF,
      0xFF,0x01,0x01,0xFF,
      0xFF,0x07,0x03,0xE1,
      0xF1,0xE1,0x03,0x07,
      0xFF,0xFF,0xFF,0x01,
      0x01,0x7F,0x7F,0x7F,
      0x7F,0xFF,0xFF,0xFF,
      0x01,0x01,0xFF,0xFF)

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(0x00, 0x00)
        while True:
            for i in range(48):
                expand.write(1, pb[i])
                expand.write(0, pa[i])
                time.sleep(0.001)
    except KeyboardInterrupt:
        print '\nbreak'

ソースを見ても判るように、このコードではLEDの振られている方向を関知しないので、逆方向に振ると裏返しの図形が表示されてしまう。これを防ぐためには何らかのセンサーが必要で、水銀スイッチや加速度センサを使って順方向の時だけ表示するようにすれば良い。

そのあたりについてはまた後日。

広告