ラズパイ5でOLEDディスプレイを使ってみました。
RUIZHI 0.96インチI2C 128×64 SSD1315
3個で¥1,200くらいでアマゾンで購入。
配線は以下の通り
VCC:1番ピン(3.3V)
GND:9番ピン(0V)
SDA:3番ピン(SDA)
SCL:5番ピン(SCL)

まずはモジュールをインストールします。
仮想環境を作成する際に、
python -m venv venv --system-site-packages
で作成します。GPIOZEROを使用するときと同じですね。
そして、仮想環境下でモジュールをインストールします。
pip install adafruit-circuitpython-ssd1306 pillow
コードはこちら
import board import busio import adafruit_ssd1306 from PIL import Image, ImageDraw, ImageFont i2c = busio.I2C(board.SCL, board.SDA) WIDTH = 128 HEIGHT = 64 oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C) try: oled.fill(0) oled.show() image = Image.new("1", (WIDTH, HEIGHT)) draw = ImageDraw.Draw(image) draw.text((0, 0), "OLED OK!", fill=255) oled.image(image) oled.show() print("Display test completed successfully.") input("Press Enter to clear the display and exit...") finally: oled.fill(0) oled.show()
実行すると文字が表示されました。
ENTERで終了します。終了時に何もしないと表示が残ったままで気持ち悪いので、最後に塗りつぶしています。

今回かなりハマってしまい、実行すると「OSError: [Errno 121] Remote I/O error」が出てしまい、何も表示されないトラブルが発生してしまいました。
ChatGPTにいろいろ質問すると、配線は問題なくI2C通信がうまくいってないからだと言われ、いろいろ対策を考えてもらいましたが何をしても直りません。
しまいにはOSがTrixieだからだと言われる始末。
結局ディスプレイを交換したところあっさり表示され、ハードウェアの故障という事が判明しました。
今回購入した3個のうち2個が故障していて、非常にガッカリしました。この辺はアマゾンで購入したのが間違いだったのでしょう。
表示できる事が確認されたので、CPU情報を表示してみました。
import time import subprocess import psutil import board import busio import adafruit_ssd1306 from PIL import Image, ImageDraw, ImageFont import atexit # ========================= # OLED 初期化 # ========================= i2c = busio.I2C(board.SCL, board.SDA) WIDTH = 128 HEIGHT = 32 oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C) oled.fill(0) oled.show() def _clear_on_exit(): oled.fill(0) oled.show() atexit.register(_clear_on_exit) # 描画用 image = Image.new("1", (WIDTH, HEIGHT)) draw = ImageDraw.Draw(image) # ========================= # 情報取得関数 # ========================= def get_cpu_temp(): with open("/sys/class/thermal/thermal_zone0/temp") as f: return float(f.read()) / 1000.0 def get_cpu_freq(): with open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq") as f: return float(f.read()) / 1_000_000 def get_gpu_temp(): try: out = subprocess.check_output(["vcgencmd", "measure_temp"]).decode() return float(out.split('=')[1].split("'")[0]) except: return 0.0 def get_gpu_freq(): try: out = subprocess.check_output(["vcgencmd", "measure_clock", "core"]).decode() return float(out.split('=')[1]) / 1_000_000 except: return 0.0 # ========================= # メイン表示ループ # ========================= try: while True: cpu_f = get_cpu_freq() cpu_t = get_cpu_temp() gpu_f = get_gpu_freq() gpu_t = get_gpu_temp() load = psutil.cpu_percent() draw.rectangle((0, 0, WIDTH, HEIGHT), outline=0, fill=0) draw.text((0, 0), f"CPU {cpu_f:.2f}GHz {cpu_t:.1f}C", fill=255) draw.text((0, 10), f"Load {load:.0f}%", fill=255) draw.text((0, 20), f"GPU {int(gpu_f)}MHz {gpu_t:.1f}C", fill=255) oled.image(image) oled.show() time.sleep(0.5) except KeyboardInterrupt: oled.fill(0) oled.show()

0.5秒ごとに情報を更新しています。負荷がかかると数字が上がってきてテンションも上がりますね。
もっとラズパイを動かしてあげたくなります。