みかんのゆるふわ技術ブログ

Raspberry PiやIoT関係のことを書き残していきます

Raspberry Piに1.7ドルの小型OLEDディスプレイをつなぐ

中国のお店が中国国外に売る通販モールAliExpressで、激安の小型OLEDディスプレイを買いました。

www.aliexpress.com

サイズは0.96インチ、解像度は128x64pxI2Cで制御できます。。色は"Yellow-Blue"と書いてあるので2色出せるのかと思いきや、上14pxが黄色、残りの下部が青色の固定でした。他にも白色、青色オンリーのモデルもあるようです。

小型でちょっとした情報を表示するのに便利そうですね🥰

おそらく、Amazon.co.jpで売られているこちらのものと同じではないかと思います。どちらも、SSD1306というOLEDディスプレイ制御ICが使われているようです。

AliExpressでの私が購入時の値段は、なんと$1.70でした!200円しないのでお買い得ですね1

このディスプレイもPythonから簡単にアクセスできるライブラリを公開されている方がいて、ドライバを書かずとも簡単に好きなものが表示できます。 とても便利ですね🥰早速Raspberry Piにつないでみましょう。

Raspberry Piに接続

購入したOLEDディスプレイ

f:id:kimura_khs:20200924191410j:plain

サイズ感がわかりやすいように、Raspberry Pi 3Bを横に置いています。 購入したOLEDディスプレイは左上のものです。右隣のケースに入って届きました。この価格でケース入りとはすごいですね。 ピンヘッダもついていて、はんだ付けなしでジャンパワイヤーなどを使って簡単にRaspberry Piに接続できます。

ほぼ1インチで解像度も128x64しかないですが、ちょっとした情報を表示するのに便利そうです。

Raspberry Piにつないでみよう

f:id:kimura_khs:20200922113215p:plain
画像出典: raspberrypi.org

Raspberry Piのピンヘッダは上図のように機能が割り当てられています。このモジュールはI2Cで通信するので、次のピンに接続します。

RasPiピン番号 RasPi 機能 OLEDディスプレイ 説明
1 3V3 power VIN 電源(3.3V)
6 Ground GND グランド (0V基準電圧)
3 GPIO 2 (SDA) SDA I2Cデータ
5 GPIO 3 (SCL) SCL I2Cクロック

これらをジャンプワイヤーで接続すると、次のようになりました。

f:id:kimura_khs:20200924191417j:plain

Raspberry Piの準備

I2Cの有効化

Raspberry Pi OSのインストール直後はI2Cが無効になっていて、そのままでは使えません。 有効化するには、raspi-configのメニューから設定できます。

$ sudo raspi-config

で設定画面を起動し、"5 Interfacing Options" → "P5 I2C" → "Yes" を選択してください。

もしくは、同じことが次の1行でもできます。メニューをたどる必要はありません。

$ sudo raspi-config nonint do_i2c 0

I2Cアドレスを調べる

ディスプレイにアクセスするには、I2Cアドレスを調べなければなりません。 データーシートを見ればわかりますが、見なくてもi2cdetectコマンドを使うと、全アドレスをスキャンしてくれます。

I2CにOLEDディスプレイだけつないだ状態で、次のコマンドを実行します。

$ sudo i2cdetect -y 1

次のような結果が出てきました。

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

0x3Cだけ見つかりましたね。これがOLEDディスプレイのアドレスです。

Pythonで表示させてみよう

スポンサーリンク

Pythonライブラリーのインストール

アメリカのオープンソースなハードウェアメーカーAdafruitがPythonライブラリーを開発しています。

github.com

これを使うと簡単に表示できます。

$ sudo apt install python3-pip
$ sudo pip3 install adafruit-circuitpython-ssd1306

基本的な使い方

早速画面表示を試してみましょう。まず、

$ python3

でPythonのシェルを起動します。起動したら、必要なライブラリを読み込みます。

>>> from busio import I2C
>>> from adafruit_ssd1306 import SSD1306_I2C

これでライブラリの使用準備ができました。まずは、ディスプレイのインスタンスを作成します。

>>> display = SSD1306_I2C(128, 64, I2C(), addr=0x3C)

displayという名前でインスタンスを作成しました。 最初の2つのパラメータに横、縦の解像度を指定します。また、addr=でOLEDディスプレイのI2Cアドレスを指定します。

このdisplayインスタンスのメソッドを呼ぶことで、画面の制御ができます。試してみましょう。

>>> display.fill(1)

このOLEDディスプレイはモノクロ表示で、各画素の明るさに1(ON)/0(OFF)を指定して画面表示をします。 fill()メソッドを呼ぶと、全画素を指定した明るさで塗りつぶします。ここでは1(ON)を指定しているので、全ピクセルがONになります。

この段階ではまだ実際の画面には反映されていません。画面に反映するには、showメソッドを呼び出します。

>>> display.show()

これで、実際に画面に反映されます。

f:id:kimura_khs:20200924191422j:plain:w480

全体が点灯しましたね。黄色と青の境界に黒い線が入りますが、ここには画素がないようです。 上14ピクセルが黄色、下50ピクセルが青色の画素になっているようです。

逆に、0(OFF)で塗りつぶすと、全部の画素が消えます。

>>> display.fill(0)
>>> display.show()

これで基本的な操作ができるようになりましたね。

スポンサーリンク

特定の画素を点灯させる

続いて、特定の画素だけ点灯させてみます。今度はスクリプトファイルを作成してみましょう。

$ nano point.py

でエディタを起動してpoint.pyを編集します。中身は次のようにします。

from busio import I2C
from adafruit_ssd1306 import SSD1306_I2C

display = SSD1306_I2C(128, 64, I2C(), addr=0x3C)

# Clear display
display.fill(0)
display.show()

# Turn on some pixels
display.pixel(0, 0, 1)
display.pixel(64, 32, 1)
display.pixel(127, 63, 1)
display.show()

pixel(x, y, value)メソッドで特定の画素(x,y)の明るさを指定します。明るさは1(ON)か0(OFF)です。 ここでは、3つの画素のみ点灯させてみました。

ファイルを保存し、実行しましょう。

$ python3 point.py

画面はこのようになります。

f:id:kimura_khs:20200924191433j:plain:w480

小さいので分かりにくいですが、3つだけ画素が点灯しています。 これで、好きな場所を点灯/消灯させられるようになりましたね。 ということは、もはや何でも書けるということです。素晴らしいですね✨

他にも、丸を書くcircle()、四角を書くrect()、線を描くline()、ビットマップフォントを用意して文字を書くtext()などの各種メソッドが使えます。 詳しくはAPIリファレンスを参照してください。

circuitpython.readthedocs.io

displayインスタンスはFrameBufferクラスを継承しているので、そのメソッドが使えます。

文字を書いてみよう

ビットマップフォントを使えばtext()メソッドで文字は書けるのですが、フォントの用意が面倒ですし、使い慣れたフォントを使いたいですね。 image()メソッドを使うと、PillowというPython画像処理ライブラリで作成した画像をそのまま表示できます。 PillowならTrueTypeフォントのレンダリングができますので、これで自由自在ですね。

Pillowをインストールしてみましょう。

$ sudo pip3 install Pillow

2020/12/2追記 Raspberry Pi OS Lite版の場合、ライブラリが足りないとエラーが出るようです。 "sudo apt install libopenjp2-7 libtiff5"でインストールしてください。

Raspberry Piにデフォルトで入っているDejaVu Sansフォントで文字を描いてみます。

2020/12/2追記 Raspberry Pi OS Lite版の場合、フォントがありません。 "sudo apt install fonts-dejavu-core"でインストールしてください。

from board import I2C
from adafruit_ssd1306 import SSD1306_I2C
from PIL import Image, ImageDraw, ImageFont

FONT_SANS_13 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 13)

# Create display instance
display = SSD1306_I2C(128, 64, I2C(), addr=0x3C)

# Prepare image
img = Image.new("1", (display.width, display.height))
draw = ImageDraw.Draw(img)
draw.text((0, 0), "www.mikan-tech.net", font=FONT_SANS_13, fill=1)
draw.text((0, 28), "Hello, world!", font=FONT_SANS_13, fill=1)

# Show image
display.image(img)
display.show()

これを実行すると、次のように文字が表示できました。

f:id:kimura_khs:20200924191438j:plain:w480

注意点としては、img= Image.new("1", (display.width, display.height))と、"1"を指定して2値画像とし、画像サイズをディスプレイの解像度に一致させなければなりません。それをdisplay.image(img)とすると、OLEDディスプレイに表示できます。

日本語を書いてみよう

同じようにして、日本語も表示できます。日本語フォントをインストールして表示しましょう。IPAフォントの中でも画面表示向けにカスタマイズされたIPA UIゴシックを使ってみましょう。

$ sudo apt install  fonts-ipafont-nonfree-uigothic

プログラムは次のようになります。

from board import I2C
from adafruit_ssd1306 import SSD1306_I2C
from PIL import Image, ImageDraw, ImageFont

FONT_SANS_13 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 13)
FONT_IPAGUI_18 = ImageFont.truetype("/usr/share/fonts/truetype/ipafont-nonfree-uigothic/ipagui.ttf", 18)

# Create display instance
display = SSD1306_I2C(128, 64, I2C(), addr=0x3C)

# Prepare image
img = Image.new("1", (display.width, display.height))
draw = ImageDraw.Draw(img)
draw.text((0, 0), "www.mikan-tech.net", font=FONT_SANS_13, fill=1)
draw.text((0, 20), u"みかんのゆるふわ", font=FONT_IPAGUI_20, fill=1)
draw.text((0, 40), u"技術ブログ", font=FONT_IPAGUI_20, fill=1)

# Show image
display.image(img)
display.show()

これを実行すると、次のようになります。

f:id:kimura_khs:20200924201757j:plain:w480

ちゃんと日本語も表示できました。階調表現ができないので、どうしてもギザギザにはなってしまいますが…😅

これを応用すれば、ちょっとした情報を表示するディスプレイとして大活躍できそうですね。 Raspberry PiでのDIYに役立ちそうです!


  1. 前回の記事でも書いた通り、発送が連絡なく大幅に遅延するトラブルがありましたが、無事に届きました。