Amazonのアソシエイトとして、ラズパイダ(raspida.com)は適格販売により収入を得ています。詳しくは当サイトの プライバシーポリシーをご覧ください。
ラズパイダでは電子工作は苦手なのであまり試してきませんでした。それでもGPIO端子に接続するだけで使えるパーツはイジっていて楽しいです。 今回は、パーツの中でも比較的に安価で手に入るOLEDディスプレイを試しました。マニュアル類も充実しているWaveshare製のOLEDディスプレイをサイズ違いで2つです。
Raspberry PiはGPIO端子が付いていますから、SPI、I2C接続で簡単に動作させられます。 事前に想像したとおり、今ではSPIとI2Cを有効にし、使用するライブラリをインストールするだけで サンプルプログラムが走ります。 はじめからPythonの環境も整っているから、Raspberry Piなら事前準備も少ないですね。
同じように興味のある方で、まだの人はぜひトライしてみてください。
今回の環境
試した環境は次の通りです。Wikiページを読めばスンナリと進められます。
- Raspberry Pi 4
- Raspberry Pi OS bookworm
- Waveshare製OLEDディスプレイ0.91インチ、1.54インチ
- いくつかのサンプルプログラム
1.54inch OLED Display Module

1.54inch OLED Module - Waveshare Wiki

0.91inch OLED Module - Waveshare Wiki
どちらも白色で発光するタイプです。
SPIとI2Cの有効化

sudo raspi-configコマンド->Interface OptionsのSPIから有効に、またはGUIならメインメニューのRaspberry Piの設定->インターフェイスでSPIを有効、にしておきます。
同じようにI2Cも有効にしておきました。再起動すれば準備完了です。
0.91インチの方はI2Cのみで動作します。
ライブラリのインストール
1.54インチから試してみます。
Waveshareの製品wikiページによると、bookwormを使用している場合はlgpioライブラリのみを使用でき、bcm2835とwiringPiはインストールして使用できないとありました。
bookwormで試しましたからlgpioライブリをインストールします。
lgpioライブラリ
GitHub
GitHub - gpiozero/lg: Linux C libraries and Python modules for manipulating GPIO Linux C libraries and Python modules for manipulating GPIO - gpiozero/lg
lgpioをダウンロードしてインストール
wget https://github.com/joan2937/lg/archive/master.zip
unzip master.zip
cd lg-master
sudo make install
GPIOに配線接続

写真のArgon製ケースは、蓋を取るとGPIO端子へアクセスできます。GPIOの番号も印字されていて便利なんですけど、ズレているから気をつけてください。 GPIO端子も増設変換されているタイプなので色分けされています。これは分かりやすい。
1.54インチ

0.91インチ


なるべくコネクタケーブルが付いている製品が良いでしょう。今回はどちらもコネクタケーブル付きのタイプです。

縦の解像度は0.91が1.54のちょうど半分です。しかし、microSDカードと比べると小ささが分かりますね。
■Pi 5は8GBモデルがオススメ
サンプルデモを実行
デモ用のサンプルファイルをダウンロードします。 通常のRaspberry Pi OSなら、7zipは既にインストールされています。
sudo wget https://files.waveshare.com/upload/2/2c/OLED_Module_Code.7z
7z x OLED_Module_Code.7z
cd OLED_Module_Code/RaspberryPi
Config.pyでインターフェイスを選択する設定は、デフォルトでSPIが有効になっているからそのままで構いません。
~/OLED_Module_Code/RaspberryPi/python/lib/waveshare_OLED
Device_SPI = 1
Device_I2C = 0
Note: Switch SPI/I2C modified here.
Pythonの環境もRaspberry Pi OSなら既にインストールされていますから、いきなりサンプルプログラムが動作します。
サンプルの場所はcd ~/OLED_Module_Code/RaspberryPi/python/example
それぞれインチサイズにあったPythonプログラムを実行します。
sudo python3 OLED_1in54test.py
sudo python3 OLED_0in91_test.py
エラー
もしも次のような入出力エラーなら、SPIが有効になっていないか、デモプログラムのconfig.pyでSPIが有効になっていないかでしょう。
1.54inch OLED
INFO:root:[Errno 5] Input/output error
1.54インチの実行結果
最終的にこんな感じ。

1.54インチの画面上部が線のように点灯していないのは、少し破損してしまったせいと思われます。(?)それとも何か間違っているか不明(?)
試しにレタングルで塗りつぶししてみると8行くらい点灯していない。

0.91インチの実行結果
0.91インチはI2Cなので、同じサンプルプログラムを使ったため、先程のconfig.pyをI2Cを有効に書き換えてから実行します。

今回は別のサンプルプログラムでも試しました。

結構、綺麗ですよね。
カスタマイズ
私はプログラムを書けないため、サンプルプログラムを少しイジった程度です。
OLED_1in54test.pyの中で、表示させている箇所を改変していきます。
try:
disp = OLED_1in54.OLED_1in54()
logging.info("\r1.54inch OLED ")
# Initialize library.
disp.Init()
# Clear display.
logging.info("clear display")
disp.clear()
# Create blank image for drawing.
image1 = Image.new('1', (disp.width, disp.height), "WHITE")
draw = ImageDraw.Draw(image1)
font1 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 18)
font2 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 24)
logging.info ("***draw line")
draw.line([(0,0),(127,0)], fill = 0)
draw.line([(0,0),(0,63)], fill = 0)
draw.line([(0,63),(127,63)], fill = 0)
draw.line([(127,0),(127,63)], fill = 0)
logging.info ("***draw text")
draw.text((20,0), 'Waveshare ', font = font1, fill = 0)
draw.text((20,24), u'微雪电子 ', font = font2, fill = 0)
image1 = image1.rotate(180)
disp.ShowImage(disp.getbuffer(image1))
time.sleep(3)
logging.info ("***draw image")
Himage2 = Image.new('1', (disp.width, disp.height), 255) # 255: clear the frame
bmp = Image.open(os.path.join(picdir, 'waveshare.bmp'))
Himage2.paste(bmp, (0,0))
Himage2=Himage2.rotate(180)
disp.ShowImage(disp.getbuffer(Himage2))
time.sleep(3)
disp.clear()
テキスト部分のdraw.text((20,0), 'Waveshare ', font = font1, fill = 0)を書き換えます。
(20,0)は座標、デモのフォントは中国フォントのWenQuanYi Micro Hei RegularとWenQuanYi Micro Mono Regularです。fill = “0” は、線の色が白であることを意味します。このOLEDはカラーではないためWhiteしかありません。
文字数的に(10,0)から描画させました。
日本語にはu''で括ります。
draw.text((10,0), 'raspida ', font = font1, fill = 0)
draw.text((10,24), u'ラズパイダ ', font = font2, fill = 0)

文字数が異なるから位置はまだズレているのとカタカナの下部も欠けています。 一番上のラインが引けていないのは破損しているからでしょう。プログラム的には線が引かれているハズ。
他のフォントも使用できるので試してみます。ttc形式だけでなく、ttf、otfでも大丈夫です。 フォント名の変数や名前は適当です。これを指定されていたディレクトリ/picへコピーしました。
font1 = ImageFont.truetype(os.path.join(picdir, 'Font02.ttf'), 18)
font2 = ImageFont.truetype(os.path.join(picdir, 'Font03.otf'), 24)
結果としてこんな感じ。

Raspberry Piにインストールされているフォントを使うこともできます。 その場合はフォントまでのパスを入れればOKです。
font3 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 24)
最終的には位置を合わせてこうしました。

文字数
フォントサイズ最少が8ptみたいなので、それを並べてみるとフォントによるものの、かなり桁数は入りますね。どちらも8ポイントです。

画像の表示
デモでは、テキスト表示後に画像を表示して終わります。
画像は~/OLED_Module_Code/RaspberryPi/python/picにあり、それぞれ使用されている画像は次の通りです。
1.54インチはwaveshare.bmpで128x64ピクセルサイズ

0.91インチは0in91.bmpで128x32ピクセルサイズ

このディスプレイはWhiteカラーなので、それぞれのピクセルサイズに合わせ、色空間はGray、アルファチャンネルはNOのbmpで作成すれば良さそうです。
カラーモードRGBのbmpだとこんなになってしまう。

拡張子pbmのグレースケールに変換後に表示してみるとイイ感じ。
画面上部が線のように点灯していないのは、冒頭のお知らせしたように恐らく破損(?)
システム情報の表示
システム情報を取得して表示させてみます。IPアドレス、CPU使用量、メモリー量、ディスク使用量です。

コマンド結果を表示させるもので、subprocessを宣言してから、サンプルプログラムのテキスト表示部分を置き換えました。
import subprocess
fontは9ポイントのDejaVuSans.ttfです。ちょうど読みやすく収まりました。
font3 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 9)
置き換え部分は次から持ってきました。
GitHub
Adafruit_CircuitPython_SSD1306/examples/ssd1306_stats.py at main · adafruit/Adafruit_CircuitPython_S… Adafruit CircuitPython framebuf driver for SSD1306 or SSD1305 OLED displays. Not for use with displayio. See README. - adafruit/Adafruit_CircuitPython_SSD1306
logging.info ("***draw info")
cmd = "hostname -I | cut -d' ' -f1"
IP = subprocess.check_output(cmd, shell=True).decode("utf-8")
cmd = 'cut -f 1 -d " " /proc/loadavg'
CPU = subprocess.check_output(cmd, shell=True).decode("utf-8")
cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%s MB %.2f%%\", $3,$2,$3*100/$2 }'"
MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8")
cmd = 'df -h | awk \'$NF=="/"{printf "Disk: %d/%d GB %s", $3,$2,$5}\''
Disk = subprocess.check_output(cmd, shell=True).decode("utf-8")
# display
draw.text((0, 16), "IP: " + IP, font=font3, fill=0)
draw.text((0, 24), "CPU load: " + CPU, font=font3, fill=0)
draw.text((0, 32), MemUsage, font=font3, fill=0)
draw.text((0, 40), Disk, font=font3, fill=0)
0.91インチは別サンプルで試す
0.91インチの方はI2Cのみで動作します。
こちらもサンプルプログラムを用意して試してみます。ドライバSSD1306ですからちょうどいいです。
git clone https://github.com/kotamorishi/rpi-ssd1306-oled.git
この方は有名なYouTuberさんですね。
GitHub
GitHub - kotamorishi/rpi-ssd1306-oled: Example of how to use SSD1306 based OLED monitor Example of how to use SSD1306 based OLED monitor. Contribute to kotamorishi/rpi-ssd1306-oled development by creating an account on GitHub.
実行すると、Heyの後にHelloの文字が一文字ずつ順番に表示されます。
Hey
H
He
Hel
Hell
Hello
コードも非常にシンプル分かりやすいから、ここからイジっていくのは良さそうです。フォント32ポイントだと2行が綺麗に表示できます。
他にもイメージファイルの表示用、アニメーションさせるパターンの3つサンプルがありました。参考になります。
何に使うか?
OLEDなら、モニターに繋いで居ないRaspberry Piの情報を表示させておきたいですね。IPアドレスまさにそうで、自分が知りたい情報がいくつかあると便利でしょう。
あと、moodeaudioなどのMPDが動作しているRaspberry Piに演奏中の曲名などを表示しておきたいですね。
公開は少し古いですが、MPDを同じ128x64のOLEDで表示するプロジェクトを2つ発見しました。参考になります。
イイねGitHub
GitHub - ngc6589/moodeAudioPlayer_OLED_Display: ラズパイ DAC で OLED 液晶画面に曲名などを表示する py… ラズパイ DAC で OLED 液晶画面に曲名などを表示する python スクリプト(moode audio player専用) - ngc6589/moodeAudioPlayer_OLED_Display
GitHub
GitHub - antiprism/mpd_oled: MPD, Volumio, RuneAudio and Moode OLED status and spectrum display for … MPD, Volumio, RuneAudio and Moode OLED status and spectrum display for Raspberry Pi (and similar) - antiprism/mpd_oled
私はC言語などはからっきしダメですから、まだ容易な部類のPythonで試せるのは助かります。OLEDのように、結果が分かりやすいパーツはプログラミングの練習として最適だと思います。
最近はOLEDのカラーも安価になってきましたし、透過OLEDディスプレイも登場しています。基本は同じようにSPI接続ですし、ドライバがSSD1306、SSD1309なので同じように試せますよ。
3Dプリンターでケースを作る人も多くなりました。小さいディスプレイに最適です。
Raspberry Pi 4とOLEDディスプレイでした。



