ラズパイでビットトレードワンのラズパイ入門ボードを載っけたときの教材（液晶にIPアドレス表示）

<!--
この記事は、[obnizを中心にプログラミング教育の教材を作ったりする（1人アドベントカレンダー）](https://gw-advent.9wick.com/calendars/5)のために作成されました。
-->
#概要
[ビットトレードワンのラズパイ入門ボード](http://btoshop.jp/2018/09/28/4562469771441/)は、シェルスクリプトマガジンとの連動企画で生まれたラズパイ学習向けの入門ボードです。

[BitTradeOne製品紹介記事「ガイドブック付！ラズパイ入門ボード ADSSMG01」](http://bit-trade-one.co.jp/product/assemblydisk/adssmg01gk/)より引用
>4個の赤色LED、2個のカラーLED、4個の押しボタンスイッチ、単色有機ELディスプレイ、圧電スピーカーなど、ラズパイで制御方法を学ぶ基礎となる電子部品を搭載しています。
![](http://bit-trade-one.co.jp/wp/wp-content/uploads/2017/12/ADSSMG01-SUB21.png)


自身が講師をしている専門学校で1年生の入門用に購入されたので、担当している4年生にも使えないかなと思いまとめてみました。ガイドブックもあるし簡単と思っていたら、OLEDディスプレイの作成はガイドブックになくちょっとだけ大変でした。
IPアドレスの表示ができれば、SSHやVNCのアクセスの際に便利です。やってみてください。

#ラズパイ入門ボードを使う
##取り付け
ラズパイ入門ボードの40ピンソケットを、ラズパイの40ピンヘッダーに差し込みます。ジャンパーワイヤーやブレッドボードで電子工作パーツを接続する必要がなく便利です。

##Raspberry Piの設定を変更する
[設定]-[Raspberry Piの設定]を選択し、SPIとI2Cの設定を[有効]にします。OLED液晶パネルがSPI(Serial Peripheral Interface)を利用しています。今回は使いませんが、Grove拡張コネクタにI2C(Inter-Integrated Circuit)が利用されていますので有効にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4092/28c0b043-bce5-1452-2cc5-23754b31c6e3.png)

##APTのアップデート＆アップグレード
RPi.GPIOライブラリパッケージの更新を行います。ライブラリはすでにインストール済みになっているはずですのでAPTパッケージのアップデートとアップグレードを行います。
ターミナル![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4092/63d138e2-29e7-b508-b4bb-6255cf8cae1c.png)を起動して、以下のコマンドを打ちます。

```shell
$ sudo apt update
$ sudo apt upgrade
```

##OLED液晶を使う
ラズパイ入門ボードでは、128x64ドットの単色有機ELディスプレイ（OLED）パネルがついています。こちらは米Adafruit Industries社が公開しているPythonライブラリを使います。`pip3`コマンドでライブラリをインストールします。

```
$ sudo pip3 install Adafruit-SSD1306
Collecting Adafruit-SSD1306
  Using cached https://www.piwheels.org/simple/adafruit-ssd1306/Adafruit_SSD1306-1.6.2-py3-none-any.whl
Collecting Adafruit-GPIO>=0.6.5 (from Adafruit-SSD1306)
  Using cached https://www.piwheels.org/simple/adafruit-gpio/Adafruit_GPIO-1.0.3-py3-none-any.whl
Requirement already satisfied: spidev in /usr/lib/python3/dist-packages (from Adafruit-GPIO>=0.6.5->Adafruit-SSD1306)
Collecting adafruit-pureio (from Adafruit-GPIO>=0.6.5->Adafruit-SSD1306)
  Downloading https://www.piwheels.org/simple/adafruit-pureio/Adafruit_PureIO-0.2.3-py3-none-any.whl
Installing collected packages: adafruit-pureio, Adafruit-GPIO, Adafruit-SSD1306
Successfully installed Adafruit-GPIO-1.0.3 Adafruit-SSD1306-1.6.2 adafruit-pureio-0.2.3
```

##Hello Worldの表示
まずは文字列"Hello, World!"を表示する以下のソースを`hello.py`ファイルにして実行してみましょう。

```python:hello.py
# -*- coding: utf-8 -*-

#AdafruitのOLEDパネルのライブラリをインポート
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
# コマンドをサブプロセス上で実行させるライブラリをインポート
import subprocess

# PIL(Python Imageing Library)から３つのライブラリをインポート
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

# OLEDのサイズ設定
OLED_WIDTH = 128
OLED_HEIGHT = 64

# OLEDとSPIバスの設定
RST = 24
DC = 23
SPI_PORT = 0
SPI_DEVICE = 0

# SPIオブジェクト
spi = SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)

# 128×64ドットのOLEDオブジェクト
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=spi)

disp.begin() # OLEDオブジェクトのスタート

disp.clear() # OLEDオブジェクトのバッファークリア
disp.display() # バッファの表示

# Imageオブジェクトの作成
image = Image.new('1', (OLED_WIDTH, OLED_HEIGHT) ,0)
# drawオブジェクトの取得
draw = ImageDraw.Draw(image)
#デフォルト・フォントのロード指定
font = ImageFont.load_default()

#表示メッセージ
msg = "Hello, World!"
# 文字をimageに描く
draw.text((0,0),msg, font=font, fill=255)

disp.image(image) # imageをOLEDバッファーに書き込む
disp.display() # バッファーを表示
```
保存した後、実行します。ここではターミナルから`python3`コマンドで実行しています。

```sh
$ python3 hello.py
```
以下の様にOLED液晶の左上から"Hello, World!"が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4092/0384532e-2921-7511-1961-443a2f2d4940.png)

##IPアドレスの表示
###`hostname`コマンドの利用
起動しているラズベリーパイのIPアドレスを表示するには`hostname`コマンドを使います。
以下の様に打てば、IPアドレスが表示されます。

```sh
$ hostname -I
192.168.0.122 240b:250:480:a200:44d4:1b0a:5b32:d22d #表示されるアドレスは環境によって違う
```
IPv4とv6のアドレスがスペース区切りで表示されますので`cut`コマンドを用いてスペース`' '`デリミタでカットして1番目の項目だけ取り出します。

```sh
$  hostname -I | cut -d' ' -f1
192.168.0.122
```
###`hostname`コマンドをPython上で利用する

`hostname`コマンドは、シェルコマンドですのでPythonのプログラム上では直接利用できません。subprocessライブラリをインポートして、文字列にしたシェルコマンドを`subprocess.check_output()`メソッドなどで実行させます。
`subprocess.check_output()`メソッドを用いてシェルコマンドの結果をOLED液晶に表示させるソースは以下の通りです。

* このソースは[Usage | Adafruit PiOLED - 128x32 Mini OLED for Raspberry Pi | Adafruit Learning System](https://learn.adafruit.com/adafruit-pioled-128x32-mini-oled-for-raspberry-pi/usage)を参考に作成しました。

```python:ip.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

#AdafruitのOLEDパネルのライブラリをインポート
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
# コマンドをサブプロセス上で実行させるライブラリをインポート
import subprocess

# PIL(Python Imageing Library)から３つのライブラリをインポート
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

# OLEDのサイズ設定
OLED_WIDTH = 128
OLED_HEIGHT = 64

# OLEDとSPIバスの設定
RST = 24
DC = 23
SPI_PORT = 0
SPI_DEVICE = 0

# SPIオブジェクト
spi = SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)

# 128×64ドットのOLEDオブジェクト
disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=spi)

disp.begin() # OLEDオブジェクトのスタート

disp.clear() # OLEDオブジェクトのバッファークリア
disp.display() # バッファの表示

# Imageオブジェクトの作成
image = Image.new('1', (OLED_WIDTH, OLED_HEIGHT) ,0)

# drawオブジェクトの取得
draw = ImageDraw.Draw(image)

#デフォルト・フォントのロード指定
font = ImageFont.load_default()

# Shell scripts for system monitoring from here:
# https://unix.stackexchange.com/questions/119126/command-to-display-memory-usage-disk-usage-and-cpu-load
cmd = "hostname -I | cut -d\' \' -f1"
IP = subprocess.check_output(cmd, shell=True).decode("utf-8")

# 文字をimageに描く
draw.text((0,0),"IP:"+IP, font=font, fill=255)

disp.image(image) # imageをOLEDバッファーに書き込む
disp.display() # バッファーを表示
```

変数`cmd`に`hostname`コマンドと`cut`コマンドをパイプでつないでいるシェルコマンドの文字列を作っています。文字列`""`内でスペース区切りを指定するためにシングルクォーテーション`'`をエスケープ`\`している点に気を付けてください。

```python:ip.pyでシェルコマンドをsubprocess.check_output()メソッドで実行しているところ
cmd = "hostname -I | cut -d\' \' -f1"
IP = subprocess.check_output(cmd, shell=True).decode("utf-8")
```
実行すると、以下の様にIPアドレスが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4092/1ff149ee-25aa-e36e-b6fc-b50ca9e266db.png)

##IPアドレス表示を自動起動させる

`ip.py`ファイルでは1行目にPython3のインタプリタ指定を行う[シバン (Unix) - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix))行を入れています。

```Python:ip.pyの1行目のシバン行
#!/usr/bin/python3
```
この指定を入れることで、`python3`コマンドを使わずにコマンドとして実行可能になります。
ターミナルから以下の様に、`ip.py`ファイルに実行権限を与えてファイル名で実行してみましょう。

```bash
$ chmod +x ip.py #実行権限を追加
$ ls -l ip.py #実行権限がついたか確認
-rwxr-xr-x 1 pi pi 1584  5月  3 10:57 ip.py
$ ./ip.py #ファイル名で実行
```
今回、作業をしていたディレクトリ`/home/pi/python_board`は実行パスの指定が無いために`./ファイル名`で実行しています。自動起動する際には、実行パスが通っているディレクトリに`ip.py`を移動させるか、全体パス指定`/home/pi/python_board/ip.py`で実行します。

自動起動の指定方法は改めて記述します。