.. include:: /index.rst
:start-after: start_hello_message
:end-before: end_hello_message
.. _py_oled:
1.10 OLEDディスプレイ
===========================================
**はじめに**
このプロジェクトでは、Raspberry PiでI2C通信を使用してSSD1306ベースのOLEDディスプレイを接続する方法を学びます。OLED(Organic Light-Emitting Diode)ディスプレイは、高コントラスト、広い視野角、低消費電力という特長を持っています。このプロジェクトでは、ディスプレイの初期化、基本図形の描画、テキストの表示方法を紹介します。
----------------------------------------------
**必要なもの**
このプロジェクトを行うには、以下のコンポーネントが必要です。
.. list-table::
:widths: 30 20
:header-rows: 1
* - COMPONENT
- PURCHASE LINK
* - :ref:`cpn_oled`
- \-
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_fusion_hat`
- \-
* - Raspberry Pi
- \-
----------------------------------------------
**配線図**
以下の手順に従って回路を組み立ててください。
1. OLEDディスプレイのVCCピンをFusion HAT+の3.3Vに接続します
2. OLEDディスプレイのGNDピンをFusion HAT+のGNDに接続します
3. OLEDディスプレイのSCLピンをFusion HAT+のSCL(GPIO 3)に接続します
4. OLEDディスプレイのSDAピンをFusion HAT+のSDA(GPIO 2)に接続します
.. image:: img/fzz/1.10_oled_bb.png
:width: 70%
:align: center
----------------------------------------------
**セットアップ手順**
#. SSD1306ドライバライブラリをインストールします:
このライブラリを使用すると、PythonからSSD1306 OLEDディスプレイと通信できるようになります。
.. raw:: html
.. code-block:: shell
sudo pip3 install adafruit-circuitpython-ssd1306 --break
#. すべてのサンプルプログラムは ``ai-lab-kit`` ディレクトリに含まれています。以下のようにOLEDのサンプルを実行してください。
.. raw:: html
.. code-block:: shell
cd ~/ai-lab-kit/python/
sudo python3 1.10_OLED_Display.py
#. サンプルを実行すると、OLED画面には枠線付きのボックスが表示され、その中央に **「Hello World!」** という文字が表示されます。
これは、ディスプレイがI2C経由で正常に通信しており、テキストやグラフィックスを正しく描画できることを示しています。
----------------------------------------------
**コード**
以下のPythonコードは、OLEDディスプレイを初期化し、「Hello World!」という文字を描画します。
.. raw:: html
.. code-block:: python
import board
import digitalio
from PIL import Image, ImageDraw, ImageFont
import adafruit_ssd1306
# Initialize OLED display dimensions
WIDTH = 128
HEIGHT = 64
# Set up I2C communication with the OLED display
i2c = board.I2C() # Utilizes board's SCL and SDA pins
oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C)
# Clear the OLED display
oled.fill(0)
oled.show()
# Create a new image with 1-bit color for drawing
image = Image.new("1", (oled.width, oled.height))
# Obtain a drawing object to manipulate the image
draw = ImageDraw.Draw(image)
# Draw a filled white rectangle as the background
draw.rectangle((0, 0, oled.width, oled.height), outline=255, fill=255)
# Define border size for an inner rectangle
BORDER = 5
# Draw a smaller black rectangle inside the larger one
draw.rectangle(
(BORDER, BORDER, oled.width - BORDER - 1, oled.height - BORDER - 1),
outline=0,
fill=0,
)
# Load the default font for text
font = ImageFont.load_default()
def getfontsize(font, text):
# Calculate the size of the text in pixels
left, top, right, bottom = font.getbbox(text)
return right - left, bottom - top
# Define the text to be displayed
text = "Hello World!"
# Get the width and height of the text in pixels
(font_width, font_height) = getfontsize(font, text)
# Draw the text, centered on the display
draw.text(
(oled.width // 2 - font_width // 2, oled.height // 2 - font_height // 2),
text,
font=font,
fill=255,
)
# Send the image to the OLED display
oled.image(image)
oled.show()
このPythonスクリプトは、SSD1306 OLEDディスプレイに「Hello World!」を表示します。実行すると、次の処理が行われます。
1. OLEDディスプレイとのI2C通信を初期化します
2. 描画用の白黒画像バッファを作成します
3. 白い背景と黒い枠付き長方形を描画します
4. 「Hello World!」が中央に表示されるようにテキスト位置を計算します
5. 最終的な画像をOLEDディスプレイに描画します
6. 電源が切られるか、表示内容が更新されるまでテキストが表示され続けます
----------------------------------------------
**コードの解説**
1. **ライブラリのインポート**
ディスプレイ制御と画像処理に必要なライブラリをインポートします。
.. code-block:: python
import board
import digitalio
from PIL import Image, ImageDraw, ImageFont
import adafruit_ssd1306
2. **ディスプレイの初期化**
指定した解像度とI2Cアドレスを使用してOLEDディスプレイを初期化します。
.. code-block:: python
WIDTH = 128
HEIGHT = 64
i2c = board.I2C()
oled = adafruit_ssd1306.SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C)
3. **ディスプレイのクリア**
画面を0(黒)で塗りつぶして更新し、ディスプレイをクリアします。
.. code-block:: python
oled.fill(0)
oled.show()
4. **画像バッファの作成**
描画処理用に1ビットカラーの画像バッファを作成します。
.. code-block:: python
image = Image.new("1", (oled.width, oled.height))
draw = ImageDraw.Draw(image)
5. **描画処理**
画像バッファ上に長方形やテキストを描画します。
.. code-block:: python
# Background rectangle
draw.rectangle((0, 0, oled.width, oled.height), outline=255, fill=255)
# Inner bordered rectangle
draw.rectangle((BORDER, BORDER, oled.width - BORDER - 1, oled.height - BORDER - 1), outline=0, fill=0)
6. **テキストの描画**
フォント情報を利用して、テキストをディスプレイの中央に配置します。
.. code-block:: python
font = ImageFont.load_default()
(font_width, font_height) = getfontsize(font, text)
draw.text((oled.width // 2 - font_width // 2, oled.height // 2 - font_height // 2), text, font=font, fill=255)
7. **ディスプレイの更新**
最終的な画像をOLEDディスプレイに送信して表示します。
.. code-block:: python
oled.image(image)
oled.show()
----------------------------------------------
**トラブルシューティング**
1. **ディスプレイに何も表示されない**
- **原因**: I2Cアドレスが正しくない、配線に問題がある、またはI2Cが有効になっていない可能性があります。
- **対処方法**: I2Cアドレス(0x3Cまたは0x3D)を確認し、すべての接続をチェックしてください。また、Raspberry Piの設定(``sudo raspi-config``)でI2Cを有効にしてください。
2. **I2C通信エラー**
- **原因**: I2Cバスに問題がある、またはデバイスが検出されていない可能性があります。
- **対処方法**: ``i2cdetect -y 1`` コマンドを使ってデバイスが検出されるか確認してください。また、I2Cバス上で他のデバイスと競合していないことを確認してください。
3. **テキストやグラフィックスが正しく表示されない**
- **原因**: 色の値や座標の設定が正しくない可能性があります。
- **対処方法**: 1ビットカラーモードでは、0が黒、255が白であることを確認してください。また、座標がディスプレイの範囲内(幅0~127、高さ0~63)に収まっていることを確認してください。
4. **ライブラリのインポートエラー**
- **原因**: 依存ライブラリが不足している、またはインストールが正しく行われていない可能性があります。
- **対処方法**: 必要なライブラリが正しい環境にインストールされていることを確認し、権限の問題がある場合は ``sudo`` を付けて実行してください。
----------------------------------------------
**拡張アイデア**
1. **システム情報の表示**
CPU使用率、メモリ使用率、温度をリアルタイムで表示するシステムモニターを作成できます。
.. code-block:: python
import psutil
import time
while True:
# Clear and redraw
draw.rectangle((0, 0, oled.width, oled.height), fill=0)
# Get system info
cpu_percent = psutil.cpu_percent()
memory = psutil.virtual_memory()
temp = psutil.sensors_temperatures()['cpu_thermal'][0].current
# Display info
draw.text((0, 0), f"CPU: {cpu_percent}%", font=font, fill=255)
draw.text((0, 16), f"RAM: {memory.percent}%", font=font, fill=255)
draw.text((0, 32), f"Temp: {temp}C", font=font, fill=255)
oled.image(image)
oled.show()
time.sleep(2)
2. **スクロールテキスト**
長いメッセージを表示するためのスクロールテキスト効果を作成できます。
.. code-block:: python
text = "This is a scrolling text message!"
text_width = getfontsize(font, text)[0]
for x in range(oled.width, -text_width, -1):
draw.rectangle((0, 0, oled.width, oled.height), fill=0)
draw.text((x, oled.height//2), text, font=font, fill=255)
oled.image(image)
oled.show()
time.sleep(0.05)
3. **アニメーション表示**
基本図形を使ってシンプルなアニメーションを作成できます。
.. code-block:: python
for i in range(0, oled.width-10, 5):
draw.rectangle((0, 0, oled.width, oled.height), fill=0)
draw.rectangle((i, 20, i+10, 30), fill=255) # Moving rectangle
oled.image(image)
oled.show()
time.sleep(0.1)
4. **複数ページ表示**
ボタン操作でページを切り替えるマルチページ表示を作成できます。
.. code-block:: python
pages = ["Page 1: Info", "Page 2: Stats", "Page 3: Graph"]
current_page = 0
# Use buttons to change pages
def next_page():
global current_page
current_page = (current_page + 1) % len(pages)
update_display()
5. **カスタムフォント**
見た目をより魅力的にするために、さまざまなフォントを使用できます。
.. code-block:: python
# Load custom font (requires font file)
try:
custom_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 12)
except:
custom_font = ImageFont.load_default()
6. **グラフとチャート**
シンプルな棒グラフやチャートを表示できます。
.. code-block:: python
data = [10, 25, 45, 30, 60, 15]
for i, value in enumerate(data):
x = i * 20 + 5
height = int(value / 100 * oled.height)
draw.rectangle((x, oled.height-height, x+15, oled.height), fill=255)
----------------------------------------------
**まとめ**
このプロジェクトでは、Raspberry PiでI2C通信を使用してSSD1306 OLEDディスプレイを接続する方法を紹介しました。OLEDディスプレイは、システムモニタリング、ユーザーインターフェース、情報表示など、さまざまな用途に適した鮮明で高コントラストな表示を提供します。テキスト、図形、グラフィックスを組み合わせることで、情報量が多く視覚的にも魅力的な表示を作成できます。ここで学んだ内容は、より高度なユーザーインターフェース、データ可視化、リアルタイム監視システムの構築にも応用できます。