電子ペーパー "Inky pHAT" の開発環境を Raspbian(Buster) にセットアップする最小手順 (venv 環境下)

Raspberry Pi Zero とほとんど同じサイズの電子ペーパー「[Inky pHAT](https://www.switch-science.com/catalog/5983/)」の開発環境を Raspbian(Buster) にセットアップする最小手順です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/5c75c540-aa10-fd16-4a42-323c077f3b76.png)

#### 動作確認

* Raspberry Pi Zero
* Raspberry Pi 4

※いづれも OS は Raspbian (Buster) 2019-09-26 です

## 手順

よくある Raspbian(Buster) 起動直後のセットアップです。タイムゾーン、ホスト名の設定、apt update && apt upgrade しています。不要ならスキップしてください。
`do_hostname YOUR_RPI_HOST_NAME` は `raspberrypi` というホスト名から変更したい場合は実行してください。

```console
(LOGIN)
$ sudo raspi-config nonint do_change_timezone Asia/Tokyo
$ sudo raspi-config nonint do_hostname YOUR_RPI_HOST_NAME
$ sudo apt update && sudo apt upgrade -y && sudo systemctl reboot
```

ここから inky pHAT の環境セットアップです。
Python3 + venv を使って `$HOME/.inky_pHAT_venv/` に仮想環境を作ります。
python3-pilのインストール時のダウンロードに70MBほどかかります。

```console
(LOGIN)
$ sudo raspi-config nonint do_i2c 0
$ sudo raspi-config nonint do_spi 0
$ sudo apt install -y python3-pip python3-venv
$ python3 -m venv --system-site-packages .inky_pHAT_venv
$ source .inky_pHAT_venv/bin/activate
(.inky_pHAT_venv) $ sudo apt install -y python3-pil libatlas-base-dev
(.inky_pHAT_venv) $ pip install inky
```

pip インストール時のコンパイルを避けるため、 apt でライブラリをインストールしています。そのライブラリを参照できるようにするため `--system-site-packages` を付けて venv 環境を作っています。このオプションを忘れると Python スクリプト内の `import PIL` で失敗しますのでご注意。

### 動作確認

```console
(.inky_pHAT_venv) $ cat << __CODE__ | python3
import io
import urllib.request
url = 'https://placehold.jp/20/fff/000/212x104.png?text=Hello_inky_pHAT'
content = io.BytesIO(urllib.request.urlopen(url).read())
from PIL import Image
pal_img = Image.new("P", (1, 1))
pal_img.putpalette((255, 255, 255, 0, 0, 0, 255, 0, 0) + (0, 0, 0) * 252)
img = Image.open(content).convert("RGB").quantize(palette=pal_img)
from inky import InkyPHAT
inky_display = InkyPHAT("black")
inky_display.set_image(img)
inky_display.show()
__CODE__
```

以下のように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/abd18192-a1b1-b79e-ffd5-432218bbc315.png)

## 公式のチュートリアル

[Getting Started with Inky pHAT](https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-inky-phat)にチュートリアルがあり、`curl https://get.pimoroni.com/inky | bash` でインストールは完了します。

しかし、様々なものをインストールしたり、pipから入れる関係でコンパイルが走ったりと、めちゃんこ時間がかかります。(Raspberry Pi Zero で1時間くらいかかった)

## アーキテクチャと注意点

チュートリアルの手順では Pillow (Python Image lib) の他にフォント関係がインストールされます。そのため、文字を(画像としてレンダリングして) inky pHAT で表示する事が可能になります。

一方、ここで紹介している最小手順では Pillow のみをインストールしています。そのため直接文字をレンダリングする環境が無い代わりに `urllib.request` を使って [ダミー画像生成 Web サービス "Placehold.jp"](https://placehold.jp/) で画像を生成してもらい、その結果を表示しています。
Web サービス側で文字レンダリングが行えれば、 Raspberry Pi 上にフォント関係をインストールする必要もありません。

Inky pHAT は、最終的には PNG-8 な画像を表示しているだけであるため、たとえばクラウド上で PNG-8 な画像を生成して Raspberry Pi では表示に徹するというアーキテクチャもあると考え、今回の紹介をしています。

## inky pHAT で表示できる PNG-8 画像

inky pHAT で表示できる画像の条件は以下の通りです。(ref: [Getting Started 内 "Displaying images on Inky pHAT"](https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-inky-phat))

* フォーマット: PNG-8
    * 8 bit インデックスカラー
    * パレット順序は「白、黒、赤」 ※
* 解像度: 212 x 104

※ ページには "black, white and red" って書いてあるけど、正解は "白(fff),黒(000),赤(f00)" です

### 静的ファイルの作成には GIMP 用パレットを利用できます

[GIMP 用のカラーパレットが配布](https://github.com/pimoroni/inky/blob/master/tools/inky-palette.gpl)されており、静的ファイルであればこのパレットを利用して作ることができます。

### 動的生成は「減色処理」でパレットを調整できます

既存ファイルを読み込む等、動的な場合は「減色時に利用するパレット」を inky pHAT 向けパレットとして適用する手法で実現できます。(ref: [Getting Started 内 "Converting images to be displayed on Inky wHAT"](https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-inky-what))

```python:画像読み込みから減色まで
from PIL import Image
pal_img = Image.new("P", (1, 1))
pal_img.putpalette((255, 255, 255, 0, 0, 0, 255, 0, 0) + (0, 0, 0) * 252)
img = Image.open("PNG_FILE.png").convert("RGB").quantize(palette=pal_img)
inky_display.set_image(img)
```

* `pal_img` には inky pHAT 用パレットを `#putpalette` で埋め込んでおく。画像サイズは1 x 1 で構わない。(白,黒,赤, 残りは void(黒))
* `Image.open` で開いたファイルを RGB に変換しつ、 `#quantize` で減色する。減色時のパレットには `pal_img` を使うように指定する。
* 減色済みの `img` を `#set_image` する。

#### AWS Lambda で Pillow したい場合は？

こうなると画像生成をクラウド上、しかも昨今は **サーバを立ち上げたら負け** だと思っていますので AWS Lambda などの FaaS 上で生成したいものです。

AWS Lambda には Pillow は標準で入ってませんので外部から入れることになります。
方法としては、Amazon Linux 2 を Docker や EC2 上でを立ち上げ※、そのローカルに Pillow をインストールし、 ZIP で固めて AWS Lambda にアップロードします。

参考: [AWS Lambda で Pillow を使おうとしたらハマった - michimani.net](https://michimani.net/post/aws-use-pillow-in-lambda/)

※ ああ、サーバを立ち上げてしまった！！！

## 今回使った機材の費用

ざくっと計算すると、このくらいでした。

* 初期: 約 3,820円

※金額は税抜きです。

| 役割 | 機材 | 金額 |
|-----|-----|-----:|
| マイコン | [Raspberry Pi Zero](https://soracom.jp/products/module/wio_lte/) | 611円 |
| 電子ペーパー | [Inky pHAT（黄・黒・白）](https://www.switch-science.com/catalog/5983/) | 3209円 |

## おわりに

それでは皆様
![out.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/74d8dc27-6875-8e7c-b4ff-f9037848cca3.gif)

### Raspberry Pi Zero に無線ネットワークを、、、！

Raspberry Pi Zero (W じゃない方) は、無線通信機能がありません。 USB を介して Wi-Fi アダプタという選択もありますが、そのほかの方法として **セルラー通信** という手もあります。

今回は Raspberry Pi Zero に [LTE 対応データ通信端末 Huawei MS2372h-607](https://soracom.jp/products/module/ms2372h_607/) と、 [SORACOM 特定地域向け IoT SIM (plan-D)](https://soracom.jp/products/sim/plan-d/) を取り付けて、[SORACOM Napter](https://soracom.jp/services/napter/) を使って SSH してました。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22754/d6f7a64a-cf90-cb51-5662-302044b090e0.png)

詳しくは [Raspberry Pi Zero (W) + USB セルラーモデムで SORACOM に接続する](https://qiita.com/ma2shita/items/c9d0e5a981c02cf58c5e) をご覧ください。

費用感はこんな感じです。

| 役割 | 機材 | 金額 |
|-----|-----|-----:|
| LTE データ通信 USB ドングル型モデム | [MS2372h-607](https://soracom.jp/products/module/ms2372h_607/) | 9980円 |
| SIM | [SORACOM 特定地域向け IoT SIM (plan-D)](https://soracom.jp/products/sim/plan-d/) | 895円 |

※ 3G の [AK-020](https://soracom.jp/products/module/ak-020/) も動作します。
※ SORACOM Air はランニングも必要になります。 [SORACOM / ご利用料金 - 特定地域向け IoT SIM](https://soracom.jp/services/air/cellular/price_specific_area_sim/) で確認ください。

### 参考情報

* [GitHub: pimoroni/inky](https://github.com/pimoroni/inky)
* [Getting Started with Inky pHAT](https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-inky-phat)
* [RaspberryPi: raspi-config コマンドラインから設定(ノンイタラクティブ)](https://qiita.com/mt08/items/d27085ac469a34526f72)
* [Python3でPillowを使ってURLから画像を読み込む](https://qiita.com/zabeth129/items/b355ebfc82d38bc49778)
* [venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)

EoT