Python から I2C 接続のディスプレイを操作する

# 概要
RaspberryPi に [I2C](http://ja.wikipedia.org/wiki/I2C) 経由で繋いだ LCD を Python から操作する．
今回は，HD44780 に SpikenzieLabs の [MPTH](https://www.spikenzielabs.com/SpikenzieLabs/MPTH.html) を付けた LCD を使用する．

# 準備
RaspberryPi 側で I2C を利用する準備が必要．
先ずは，`/etc/modules` に次の2行を追加する．

```
i2c-bcm2708
i2c-dev
```

次に，`/etc/modprobe.d/raspi-blacklist.conf` から次の行を削除 / コメントアウトする．

```
blacklist i2c-bcm2708
```

一旦再起動し，その後 `i2c-tools` と `python-smbus` をインストールする．

```shell-session
sudo apt-get install i2c-tools python-smbus
```

# I2C バス番号とデバイスアドレスの取得
始めに，使用する LCD のバス番号とアドレスを取得する．
`sudo i2cdetect 0` と `sudo i2cdetect 1` を実行し，
エラーの出ない方がバス番号（0 か 1）であり，出力からアドレスを取得する．
例えば，出力が次のような場合，0x20 がアドレスである．

```shell-session
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- — -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
```

# 実際の通信
I2C 通信には `smbus` ライブラリを利用する．`smbus.SMBus(bus_number)` にてコネクションオブジェクトを取得し`write_i2c_block_data` にてデータを送信する。このメソッドは、`addr`、`cmd`、`vals` を取る。`addr` はデバイスアドレスである。`cmd` と `vals` は変わっていて、送信データのうち最初の 1バイトを `cmd` に、残りを `vals` に入れる。これは最低 1バイトを送る必要があるからだそうだ([参考](http://raspberrypi.stackexchange.com/questions/8469/meaning-of-cmd-param-in-write-i2c-block-data))。

```py
import smbus

bus = smbus.SMBus(bus_number)
s = "abcde"

bus.write_i2c_block_data(addr, ord(s[0]), ord(s[1:]))
```

HD44780 はなぜかコントロールシーケンスを読めないので、クリアなどは MPTH が用意している[コマンド](http://www.spikenzielabs.com/Downloadables/LCD_Interface_v3.pdf)利用する。

特殊コマンドは `0x80` に続けて呼び出す。画面クリアは `0x05 0x01` なので、

```py
bus.write_i2c_block_data(addr, 0x80, [0x05, 0x01])
```

となる。

# ライブラリ
これらをまとめた[ライブラリ](https://github.com/jkawamoto/i2cdisplay)を作成した。他のプログラムから呼び出すことも，コマンドラインから試してみることも可能．どちらの場合も root 権限で実行する必要がある．

## コマンドラインでの利用
書式は次の通り．

```shell-session
sudo ./i2cdisplay.py <bus> <addr> {write|clear|cursor|backlight}
```

`<bus>`, `<addr>` はそれぞれバス番号とデバイスアドレスである．
サブコマンドは，それぞれ文字の出力，画面のクリア，カーソルの表示切り替え，バックライトの調節である．

### 文字の出力
文字の出力は `sudo ./i2cdisplay.py <bus> <addr> write <input>+`．
`<input>` にスペース区切りで複数の文字列を渡すと複数行に分けて出力する．
例えば１行目に abc を 2行目に def を表示する場合，

```shell-session
sudo ./i2cdisplay.py <bus> <addr> write "abc" "def"
```

となる．

### 画面のクリア

```shell-session
sudo ./i2cdisplay.py <bus> <addr> clear
```

### カーソルの表示切り替え

```shell-session
# カーソルを表示する
sudo ./i2cdisplay.py <bus> <addr> cursor True 
# 非表示にする
sudo ./i2cdisplay.py <bus> <addr> cursor False
```

###  バックライトの調節

```shell-session
# 強度は 0-255 から選ぶ（下記の例では 128）
sudo ./i2cdisplay.py <bus> <addr> backlight 128
```

## ライブラリとしての利用

```py
# 初期化
d = MPTHDisplay(<bus>, <addr>)

# 文字の出力
d.write("abc")

# 改行
d.newline()

# クリア
d.clear()

# 複数行の出力
d.writelines("abc", "def")
```

# 参考
  - [Raspberry Piで「I2C LCD Breakout」を使ってみた！ | スイッチサイエンス マガジン](http://mag.switch-science.com/2013/07/30/use-i2c-lcd-brakeout-board-on-raspberry-pi/)
  - [Using the I2C Interface | Raspberry Pi Projects](http://www.raspberry-projects.com/pi/programming-in-python/i2c-programming-in-python/using-the-i2c-interface-2)
  - [MPTH | SpikenzieLabs](https://www.spikenzielabs.com/SpikenzieLabs/MPTH.html)