Raspberry Pi PR

RaspsberryPi 5でOLEDディスプレイにIPを表示する Python/Blinka/SSD1306

記事内に商品プロモーションを含む場合があります

はじめに

RaspberryPi5で、OLEDディスプレイを使う方法について解説します。

言語は「Python(CPython)」、ライブラリは「adafruit-circuitpython-ssd1306」を使用します。

実は今回使う「adafruit-circuitpython-ssd1306」は、RaspberryPi Picoなど、CircuitPythonで動くマイコン用のライブラリで、そのままではノーマルのRaspberryPiの「Python(CPython)」では使えません。

ですが、同じくAdafruit製の「Blinka」というライブラリ(ミドルウェア)を使えば、ノーマルのRaspberryPiからCircuitPython用のライブラリが使えるようになります。

このBlinkaの仕組みが結構おもしろかったので、今回は「Brinka」と「CircuitPython用のライブラリ」を使って、OLEDに表示RaspberryPiのIPアドレスを表示してみたいと思います。

Brinka(ブリンカ)

Adafruitより引用

アメリカのAdafruit Industries社が開発した、CPythonからCircuitPython(Micro Python)を動かすための、特殊なライブラリ(ミドルウェア)です。

「トランスパイラ」というツールを備えており、CircuitPythonのコードを普通のPython(CPython)コードに変換することができます。

上記の返還をかけることで、普通のPythonしか使えないノーマルのRaspbrryPiや、Jetsonのようなシングルボードコンピュータ(SBC)でも、CircuitPythonを動かすことができます。

ちなみに「RaspberryPiにCircitPythonをインストールしちゃえば?」と思われるかもしれませんが、CircuitPythonは、OSがないマイコンで使われることを前提にした環境です。

そのため、「RaspberryPiのOS」と「CircuitPython」は同居することはできず、Brinkaのようなミドルウェアが必要になります。

Blinkaが対応しているSBC一覧:https://circuitpython.org/blinka

なぜIPアドレスを表示?

RaspberryPiを無線LANでのログインで使っていると、IPアドレスを忘れたり、IPが変わってしまってログインできなくなることがありますよね。

固定IP設定や、設定したIPのメモを作ればいいのですが、ディスプレイ上でIPアドレスを表示がでるようにしておけば、固定IPやメモも不要になります。

ということで、今回ディスプレイにIPアドレスを表示することにしてみました。

環境

この記事で使用する環境は以下の通りです。

環境 内容 備考
OS RaspberryPi OS bookworm
言語 Python Ver.3.11.2
ライブラリ adafruit-circuitpython-ssd1306 Ver.2.12.17
adafruit-circuitpython-framebuf Ver.1.6.5
ミドルウェア Adafruit-blinka Ver.8.85.0
ボード RaspberryPi 5

RaspberryPi 5とOLEDディスプレイの接続

RaspberryPi 5とOLEDディスプレイを以下のように接続します。

RaspberryPi5とOLEDディスプレイの接続方法を解説
配線イメージ

ピンアサイン

RaspberryPi 公式のGitHubより引用

使用する部品

RaspberryPi5

RaspberryPi 5技適も取得されて、国内販売品もだいぶ出回るようになりました。マイクロSDも忘れずに用意してください。

RaspberryPi 5 電源

RaspberryP 5は、5v5Aという特殊な仕様の電源アダプタが必要です。公式は少し高いので私はPSEマーク付きのこちらのものを使っています。

OLEDディスプレイ

I2C接続のOLEDディスプレイです。SSD1306チップを搭載しています。

OLEDディスプレイ(HATタイプ)

少し高くなりますが、HATタイプもあります。Amazonがなぜかすごく高いので、代わりのショップ(2500円~3000円程)も載せておきます。

ブレッドボード(ハーフサイズ)

サンハヤト製のブレッドボードです。今回は簡単な回路なので小さいサイズのものを使っています。

ジャンパワイヤ(オス-メスタイプ)

RaspberryPiとブレッドボードで使うなら、以下のオス-メスタイプを使います。

プログラム概要

今回のプログラムの概要は以下の通りです。

  • IPアドレスを取得する
  • OLEDにIPアドレスを表示する

「CircuitPython」と「Blinka」のインストール

以下のコマンドてCircuitPython・Blinka、IPを簡単に取得するためのライブラリ「Ipget」をインストールします。

CircuitPython、Blinkaのセットアップ方法については、公式の以下のページをベースにしています。

パッケージ管理ソフトを更新する

以下のコマンドで、まずはapt-getなどのパッケージ管理ソフトを最新にします。

sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get install python3-pip
sudo apt install --upgrade python3-setuptools

Python仮想環境の構築

アップデートが完了したら、以下のコマンドでPythonの仮想環境を構築します。

cd ~/
python3 -m venv env --system-site-packages

構築完了後、以下のコマンドで仮想環境を有効化してください。

source ~/env/bin/activate

コマンドの実行後、以下のように「(env)」と表示されれば有効化は完了です。そのままの状態でライブラリのインストールに進んでください。

esu@raspberrypi:~ $ source ~/env/bin/activate
(env) esu@raspberrypi:~ $

前述の仮想環境の有効化後に端末を閉じてしまったり、中断してライブラリのインストールを再開した時は、再度以下のコマンドを実行してから、インストールを再開してください。

source ~/env/bin/activate

仮想環境を終了したい時は、以下の「deactivate」コマンドで終了できます。

(env) esu@raspberrypi:~ $ deactivate
esu@raspberrypi:~ $

Blinkaのインストール

以下のコマンドで、Blinkaをインストールします(数分かかります)。

cd ~
pip3 install --upgrade adafruit-python-shell
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
sudo -E env PATH=$PATH python3 raspi-blinka.py

最後のほうで、以下のように再起動の確認が表示されるので「Y」を入力します。

Settings take effect on next boot.

REBOOT NOW? [Y/n] Y

RaspberryPiが自動的に再起動する(再起動完了後のメッセージなどはありません)ので、際ログイン後または、端末から以下のコマンド実行します。

ls /dev/i2c* /dev/spi*

下のように表示されたら、Blinkaのインストールは完了です。

/dev/i2c-1  /dev/i2c-11  /dev/i2c-12  /dev/spidev0.0  /dev/spidev0.1  /dev/spidev10.0

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

OLEDに必要なライブラリをインストールします。Pythonの仮想環境を有効化した状態で作業してください。

CircuitPython-ssd1306のインストール

以下のコマンドで「adafruit-circuitpython-ssd1306」をインストールします。

source ~/env/bin/activate
pip3 install adafruit-circuitpython-ssd1306

adafruit-circuitpython-framebufのインストール

OLEDで文字表示を行う際に必要な「adafruit-circuitpython-framebuf」をインストールします。

pip3 install adafruit-circuitpython-framebuf

フォントファイルのインストール

以下の場所から、文字表示用のフォントファイルをダウンロードします。

下記のリンク先のダウンロードボタンからファイルをダウンロードし、後述するプログラムと同じ場所に保存してください。

右クリック・保存などでダウンロードすると、コードを実行する際にエラーになることがあります。必ず上記ページのダウンロードボタン(下矢印(↓)のボタン)でダウンロードしてください。

ipgetのインストール

以下のコマンドで「ipget」をインストールします。ipgetがインストールできたらライブラリのインストールは完了です。

pip3 install ipget

実行結果

後述するコードを実行すると、以下のようにOLEDディスプレイにRaspberryPi5のIPアドレスが表示されます。

解説するプログラムを実行した結果を説明
実行結果

全体コード

全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。

# CircuitPythonの各モジュールをインポートします
from board import SCL, SDA
import busio

# CircuitPython-ssd1306ライブラリをインポートします
import adafruit_ssd1306

# ipgetをインポートします
import ipget

# i2c通信用のオブジェクトを生成します
i2c = busio.I2C(SCL, SDA)

# OLEDディスプレイ用のオブジェクトを生成します
# 引数は横のピクセル数、縦のピクセル数、I2C通信用のオブジェクトです
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)

# ディスプレイの表示内容を初期化します
display.fill(0)
display.show()

# ipget用のオブジェクト生成します
ip = ipget.ipget()

# 無線LANのIPアドレスを取得します
ip_str = ip.ipaddr("wlan0")

# お使いの環境に合わせて修正してください。
font_path = "/home/esu/src_python/font5x8.bin"

# 取得したIPアドレスの表示を準備します
display.text("My IP Addr is", 0, 10 ,1,font_name=font_path)
display.text(ip_str, 0, 20 ,1, font_name=font_path)

# 準備した内容を表示します
display.show()

プログラムの実行方法

Pythonの仮想環境を有効化して、以下のコマンドを実行します。

source ~/env/bin/activate
python3 pi_circuitpython_ssd1306.py

コードのポイント

SSD1306オブジェクトの作成

OLEDディスプレイ用のオブジェクトを生成します。

引数には、ディスプレイの縦横のピクセル数とi2c通信用のオブジェクトを渡します。

# OLEDディスプレイ用のオブジェクトを生成します
# 引数は横のピクセル数、縦のピクセル数、I2C通信用のオブジェクトです
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)

OLEDディスプレイの初期化

ディスプレイの表示内容を初期化(クリアします)。

ディスプレイの表示は「追記」の形式で行われるため、初期化せずに描画を行ってしまうと、前回の表示内容と、今回の表示内容が混ざってしまいます。

そのため、全体を埋めるfill関数に0(黒)を渡して、ディスプレイのクリアを行います。

# ディスプレイの表示内容を初期化します
display.fill(0)
display.show()

IPアドレスの取得と表示

取得するネットワークの名前を指定して、IPアドレスを取得します。

ネットワーク名は「ifconfig」のコマンドなどで確認できますが、基本的に無線LANを使う場合は「wlan0」と指定すれば問題ないはずです。

# 無線LANのIPアドレスを取得します
ip_str = ip.ipaddr("wlan0")

text関数とフォントファイルの指定

文字列の表示は、text関数で文字列(英数字・記号)、表示する場所のX座標(横位置 )Y座標(縦の位置)をピクセルで指定します。

プログラム単体を手動実行する場合、フォントファイルの場所を省略しても、プログラムと同じ場所を参照してくれます。

しかし、後述する自動起動の場合は、カレントは参照されず、ライブラリ内部でエラーが発生してしまうため、フォントファイルの絶対パスでの指定が必要です。

フォントファイルの絶対パスは、お使いの環境に合わせて変更してください。

# お使いの環境に合わせて修正してください。
font_path = "/home/esu/src_python/font5x8.bin"

# 取得したIPアドレスの表示を準備します
display.text("My IP Addr is", 0, 10 ,1,font_name=font_path)
display.text(ip_str, 0, 20 ,1, font_name=font_path)

起動時に自動でPythonプログラムを起動する

プログラムが作成できたら、RaspberryPiの起動時にIPを確認できるように、自動実行の設定を行います。

シェルスクリプトの作成

Python仮想環境下でプログラムを実行する、下記のシェルスクリプトを作成します。

※ ディレクトリ名などは、お使いの環境に合わせて変更してください。

#!/bin/sh
/home/esu/env/bin/python3 /home/esu/src_python/circuit-python_ssd1306.py

実行権限の付与

シェルスクリプトが作成できたら、以下のコマンドで実行権限を付与します。

chmod 775 oled_ip.sh

systemd用サービスの作成

RaspberryPi OSでは、デフォルトでsystemdというシステムを使って起動時に実行するプログラムを管理しています。systemdが実行するプログラムは「サービス」と呼ばれ、下記の内容を作成、登録することで、systemdが処理を実行してくれるようになります。

今回のIP表示では、以下の「oled_ip.service」を作成します。

※ ディレクトリ名はお使いの環境に合わせて適宜変更してください。

[Unit]
# この設定の説明です
Description=Display IP on oled.
# いつ実行するかを指定します(ネットワーク確立後の指定)
After=network-online.target

[Service]
# サービスの種類です。
Type=oneshot
# 実行したプログラムが終了しても、サービスをアクティブと見なすか
RemainAfterExit=yes
# 実行するコマンド
ExecStart=/home/esu/src_python/oled_ip.sh

[Install]
WantedBy=network-online.target
WantedBy=multi-user.target

サービスファイルは作成後、以下のコマンドで以下の場所に保存します。

sudo cp oled_ip.service /etc/systemd/system/

networkd設定の有効化

serviceファイルに記載した「network-online.target」は、デフォルトで無効化されているため、以下の二つのコマンドで有効化を行います。

sudo systemctl enable systemd-networkd
sudo systemctl enable systemd-networkd-wait-online

サービスの再読み込み

サービスの作成と設定の有効化が終わったら、systemdに対してサービスの読み込みを行います。コマンドは以下の通りです。

sudo systemctl  daemon reload

サービスの手動実行

読み込みが終わったら、以下のコマンドでサービスを手動起動させます。

sudo systemctl start oled_ip

startの後は、サービスファイルのファイル名(拡張子を除いた部分)を指定してください。

例) oled_id.service → oled_ip

実行状態の確認

サービス実行時のエラーの有無は、以下のステータスコマンドで確認できます。

sudo systemctl status oled_ip

以下のように表示されていれば、正常実行されて、ディスプレイにIPが表示されているはずです。

esu@raspberrypi:~ $ sudo systemctl status oled_ip
● oled_ip.service - Display IP on oled.
     Loaded: loaded (/etc/systemd/system/oled_ip.service; enabled; preset: enabled)
     Active: active (exited) since Sun 2024-07-07 22:21:31 BST; 47s ago
    Process: 1953 ExecStart=/home/esu/src_python/oled_ip.sh (code=exited, status=0/SUCCESS)
   Main PID: 1953 (code=exited, status=0/SUCCESS)
        CPU: 123ms

Jul 07 22:21:31 raspberrypi systemd: Starting oled_ip.service - Display IP on oled....
Jul 07 22:21:31 raspberrypi systemd: Finished oled_ip.service - Display IP on oled..

自動実行の有効化

手動実行で動作が確認できたら、以下のコマンドで起動時の自動実行を有効化します。

sudo systemctl enable oled_ip

自動実行の確認

有効化が完了したら、RaspberryPiの電源をOFF・ONして自動実行を確認をします。

なお、今回のサービスの設定では、IPの取得のため「ネットワーク接続が確立されてからサービスを起動する」という設定になっています。

私の環境では電源ONから2分15秒ほどかかるので、しばらく待ってから確認するようにしてください。

解説するプログラムを実行した結果を説明
実行結果

しばらく待ってもIPが表示されない場合は、手動起動と同じく以下のコマンドで状態を確認してください。

sudo systemctl status oled_ip

今回使用した「ipget」は短いコードでIPが取得できますが、無線LANに未接続の状態で実行するとエラーになってしまい、ディスプレイ表示に失敗することが多々ありました。

コードをシンプルにするためこの記事では、networkdのサービス設定(ネットワークに接続してから実行)で回避していますが、より確実性を高めたい場合は

  • ライブラリを変更して接続完了まで待つコードを入れる
  • サービス設定内で失敗時のリトライを入れる

などで対策してみてください。

まとめ

raspberrypi5で、blinkaとCircuitPythonのライブラリを使って、OLEDディスプレイを使う方法を解説しました。

ライブラリのインストールや自動起動なので、記事自体は少々長くなってしまいましたが、Blinkaは、Picoなどのマイコン用のライブラリが、ノーマルのRaspberryPiでもそのまま使える、とても面白いカラクリです。

今回紹介したライブラリ以外にも、Blinkaが対応するライブラリはまだまだたくさんあるので、ぜひ皆さんも使ってみてください。

参考になればうれしいです。

おすすめの最新書籍

今月号の日経Interfaceは「Linuxチューニング術50」

今月号のInterfaceは『Linux チューニング術 50』です。

Linuxを組み込んだ機器を”本格的”に作ろうとすると「起動を早くしたい」「いきなり電源を切られてもデータを守りたい」など、対応が必要なチューニングはおおいですよね。

今回の記事は、「カーネルをいじらない」方法でチューニングを行う方法が解説されています。

こういった”実用的”な特集はレアですし、知っておいても損はない情報だと思います。

私も仕事でこの手の問題に何度も遭遇していますが、こういったOSレベルの難しそうな設定を、さらっとできちゃう人はかっこいいですよね。

興味のある方は、以下のリンクから確認できます。

質問・要望 大歓迎です

「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。

使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。

ABOUT ME
えす
現役のソフトウェアエンジニアです。 C++ C# Python を使ってます。10年ちょい設計/開発部門にいましたが、今はQAエンジニアっぽいことをしています。
Index