ラズパイPicoでSSD1306有機ELディスプレイの使い方 CircuitPython編

ラズパイPicoでSSD1306の使い方 CircuitPython編

「Raspberry Pi Pico」で有機ELディスプレイ「SSD1306」を使う方法を紹介します。
以前「ArduinoIDE」を使用した「C言語」での使用方法と「Thonny」を使用した「MicroPython」での使用方法を紹介しましたが、今回は開発環境「Tonny」を使用した「CircuitPython」での使用方法を紹介します。

図形の描画について、今回使用したライブラリでは円はありますが塗り潰し円と三角の標準関数がなかったため、自作関数で描画してます。

「CircuitPython」の特徴(MicroPythonとの違い)は、ラズパイ本体をパソコンと接続することでUSBメモリのように認識されて、ラズパイ本体内のデータを操作できることです。
ラズパイ本体内のデータをフォルダとして開いて操作できるため、メモ帳や他のエディタで作成したプログラムを直接このフォルダ内に置くことで実行できたり、ライブラリや参照データを保存したりすることができて便利です。

「Raspberry Pi Pico」の使い方や開発環境「Thonny」のインストール方法、初期設定については以下のリンクで詳しく紹介しています。

ラズパイPico/PicoWの使い方を3つの開発環境Python、ArduinoIDE、PlatformIOで紹介
Raspberry Pi Pico/Pico Wの使い方を端子配列からPython(MicroPython)とC言語の開発環境、Lチカ方法まで紹介。PythonはTonny、C言語はArduinoIDEとPlatformIOの3種類で詳しく紹介します。
ラズパイPicoの使い方 CircuitPython&開発環境Thonny
Raspberry Pi PicoでCircuitPythonを使ったプログラミング方法を開発環境Thonnyを使用してインストールからライブラリの追加、サンプルプログラム(コピペ)による動作確認(液晶表示SSD1306を例に)まで詳しく紹介します。

「MicroPython」や「C言語」でのSSD1306の使用方法も以下のリンクで詳しく紹介しています。

ラズパイPicoでSSD1306有機ELディスプレイの使い方 MicroPython編
液晶表示器のないRaspberry Pi PicoでOLED SSD1306の使い方をMicroPythonのサンプルプログラムで紹介。開発環境はTonnyを使用します。

https://logikara.blog/raspi_pico_oled_c/

スポンサーリンク

1.有機ELディスプレイ SSD1306について

SSD1306は有機ELディスプレイ(OLED)と呼ばれる表示器です。

画面サイズ違いで2種類(128×64、128×32)あり、比較的安価(どちらも500~700円程)で購入できます。
I2C通信とSPI通信に対応したものがありますが、I2C通信の方が通信線が2本で電源線と合わせても全部で4本のため扱いやすいので、今回はI2C通信のものを使用します。

外観は下画像のようになります。4つの端子(GND、電源3.3~5V、SCL、SDA)があります。
付属品として4ピンのピンヘッダが付属しているのではんだ付けして使用できます。

上画像の左が「128×64」で右が「128×32」です。
どちらも使い方は一緒で画面の高さ(Height)の設定(64か32)を変えるだけです。

上画像は基板の裏側で部品が剥き出しです。
金属に触れると壊れる可能性があるのでビニール絶縁テープ等を貼っておくのがおすすめです。

SSD1306については以下のリンクでもっと詳しく紹介しています。

SSD1306有機ELディスプレイOLEDの使い方、簡単2画面表示の方法も紹介
SSD1306はライブラリを準備してI2C通信と簡単なコマンドで表示可能。ATOM LITEやESP32、Arduino等に表示器を追加したい時に手軽に安価で実現できるのでとても便利です。
スポンサーリンク

2.配線方法

「Raspberry Pi Pico」の端子配列は以下のようになります。(公式サイトより抜粋

ラズパイ(Raspberry Pi) Pico 端子配列

配線方法はブレッドボードを使用して下画像のように行いました。

ラズパイPicoでSSD1306の使い方 CircuitPython編

「Raspberry Pi Pico」本体の1番端子とブレッドボードの1番ピンを合わせておくと端子番号の確認がしやすいです。
「SSD1306」と「Raspberry Pi Pico」は以下表のように接続します。

SSD1306Raspberry Pi Pico
VCC3V3(OUT)
GNDGND
SDAGP16
SCLGP17

「タクトスイッチ青」は「Raspberry Pi Pico」の「GP11(15)ーGND(13)」間に接続、
「タクトスイッチ赤」は「Raspberry Pi Pico」の「GP15(20)ーGND(18)」間に接続します。


今回使用したブレッドボードはサンハヤト製の6連結ピンのものです。
安価なものはありますが 5連結ピンのものが多く、ピンが少ないため今回のような使い方はできません。少し割高ですが6連結ピンの方が自由度があっておすすめです。

タクトスイッチは端子が4つのものが多く2つづつペアで内部で繋がっているため、ボタンを押した時にどことどこが繋がるのか確認してから使用しましょう。色違いのものがあるとわかりやすくて便利です。

SSD1306は今回は画面サイズ「128×64」のものを使用しました。
個人的には表示色は白色が一番見やすくて綺麗と思います。

「Raspberry Pi Pico」は単体で買うと端子がついていません。
ピンヘッダーを別で買ってはんだ付けする必要がありますが、ピンヘッダーは細ピンヘッダーが差しやすくて使いやすいです。
ハンダ付が不安な方はハンダ付け済みのものを購入しましょう。

スポンサーリンク

3.サンプル画面の紹介

サンプル画面として、いつも使用しているデモ画面とフォントデータの文字一覧表示の2種類準備しました。

・デモ画面

基本的な表示が確認できるように下画像のようなサンプル画面を準備しました。

表示のテストには一通りの表示方法が確認できるため、毎回この表示で確認しています。
ラズパイPicoでSSD1306の使い方 CircuitPython編

①タイトル表示
②ボタンの動作で内容が変化
③ボタンを押した回数を表示
④指定した座標から平行線
⑤始点終点を座標で指定した線
⑥指定した座標から垂線
⑦円と塗り潰し円
⑧三角と塗り潰し三角
⑨四角と塗り潰し四角

動作紹介

青と赤のボタンを押した時の動作は下画像のようになります。

ラズパイPicoでSSD1306の使い方 CircuitPython編

「青ボタン」を押すと画面の「BTN = OFF」が「BTN = ON」に変わります。

ラズパイPicoでSSD1306の使い方 CircuitPython編

「赤ボタン」を押すと画面の「CNT=0000」の数値がボタンを押すごとに1づつ増えていくカウンタとして動作します。

図形の描画で自作関数を使用しているものは時間がかかるため表示画面の更新が遅いです。
ボタンを押す時は1秒程度押さないと画面は更新されません。

・登録文字一覧表示

文字を表示する関数の中で”文字列”ではなくchr型で「数値」を指定することで文字を表示させることができます。

サンプルプログラムでは、文字をchar(0)〜chr(254)まで文字サイズ2倍で順番に表示し、最後に文字サイズ1倍で一覧表示しています。

文字サイズ2倍で順番に表示

ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧

文字サイズ1倍で一覧表示

ラズパイPicoでSSD1306 CircuitPython 文字一覧
ラズパイPicoでSSD1306 CircuitPython 文字一覧
表示できる文字はASCII文字以外にもたくさんありますが、使えそうなものは一部かと・・・
三角や矢印は図形で描画するより簡単なので使えそうです。あとは「¥」や「μ」「φ」「±」「Ω」「°」なんかは使えそうですね。

4.サンプルプログラム(コピペ)

・デモ画面

デモ画面を表示するプログラムは以下のようになります。
「Thonny」に「コピペ」して実行してください。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

import board
import busio
import digitalio
import adafruit_ssd1306
import math

# I2C 通信設定
i2c = busio.I2C(board.GP17, board.GP16)  # (SCL, SDA)17,16
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)

#  出力端子設定(LED)
LED = digitalio.DigitalInOut(board.GP25)   # GP25をLEDとして出力設定
LED.direction = digitalio.Direction.OUTPUT
#  入力端子設定(ボタン1,2)
BTN1 = digitalio.DigitalInOut(board.GP11)  # GP11をBTN1として 入力設定
BTN1.direction = digitalio.Direction.INPUT
BTN1.pull = digitalio.Pull.UP
BTN2 = digitalio.DigitalInOut(board.GP15)  # GP15をBTN2として入力設定
BTN2.direction = digitalio.Direction.INPUT
BTN2.pull = digitalio.Pull.UP

state = False  # ボタン状態保持用
cnt = 0        # ボタン2 ON回数カウント用

# 塗り潰し円描画関数(円を半径を変えて複数描画)
def fill_circle(x, y, l, color):
    for r in range(l+1):
        display.circle(x, y, r, color)

# 三角描画関数(線で描画)
def triangle(x1, y1, x2, y2, x3, y3, color):
    display.line(x1, y1, x2, y2, color)  # 指定座標から指定座標までの線
    display.line(x2, y2, x3, y3, color)  # 指定座標から指定座標までの線
    display.line(x1, y1, x3, y3, color)  # 指定座標から指定座標までの線

# 塗り潰し三角(正三角形)描画関数(三角関数を使用)
def fill_triangle(x, y, l, color):
    for i in range(int(l/2 * math.tan(math.radians(60)))):
        h = l/2 * math.tan(math.radians(60))  # 高さ
        display.hline(x + math.ceil((i*l/h)/2), y - i, l - math.ceil(i*l/h), color) # 指定座標から塗り潰し三角

while True: # ずっと繰り返し
    # 表示内容設定
    display.fill(0) # 表示内容消去
    
    # 文字表示("表示内容", x, y, 色, フォント, サイズ)
    display.text("OLED", 3, 0, True, font_name="font5x8.bin", size=1)
    display.text("TEST", 3, 9, True, font_name="font5x8.bin", size=1)
    display.text("SSD1306", 38, 0, True, font_name="font5x8.bin", size=2)
    
    # ボタン1処理(ON/OFF)
    if BTN1.value == False: # BTN1がONなら
        display.text("BTN = ON", 2, 25, True, font_name="font5x8.bin", size=1)  # 文字表示
        LED.value = True    # LED点灯
    else:                   # BTN1がONでなければ
        display.text("BTN = OFF", 2, 25, True, font_name="font5x8.bin", size=1) # 文字表示
        LED.value = False   # LED消灯
        
    # ボタン2処理(カウンタ)
    if BTN2.value == False and state == False: # BTN2がONかつボタン状態Falseなら
        state = True                           # ボタン状態True
        cnt = cnt + 1                          # カウント+1
    if BTN2.value == True:                     # BTN2がOFFなら
        state = False                          # ボタン状態False
    display.text("CNT = {:04}".format(cnt), 66, 25, True, font_name="font5x8.bin", size=1) # 文字表示
    
    # 図形描画
    display.hline(0, 18, 128, True)          # (x, y, 長さ, 色) 指定座標から横線
    display.vline(62, 18, 18, True)          # (x, y, 長さ, 色) 指定座標から 縦線
    display.line(0, 36, 128, 36, True)       # (x1, y1, x2, y2, 色) 指定座標1から指定座標2までの線
    display.circle(10, 52, 10, True)         # (x, y, 半径, 色) 指定座標を中心に指定半径の円
    display.rect(86, 43, 18, 18, True)       # (x, y, 幅, 高さ, 色)指定座標に四角
    display.fill_rect(106, 43, 18, 18, True) # (x, y, 幅, 高さ, 色)指定座標に 塗り潰し四角
    
    # 以下自作関数で描画
    fill_circle(31, 52, 10, True)           # (x, y, 半径, 色) 塗り潰し円を描画関数呼び出し
    triangle(41, 60, 51, 44, 61, 60, True) # (x1, y1, x1, y1, x1, y1, 色) 三角描画関数呼び出し
    fill_triangle(64, 60, 20, True)        # (x, y, 底辺長さ, 色) 塗り潰し三角(※正三角形)

    # 設定した内容を表示
    display.show()

・登録文字一覧表示

文字の一覧を表示させるサンプルプログラムは以下になります。
「Thonny」に「コピペ」して実行してください。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

import board
import busio
import digitalio
import adafruit_ssd1306
import time

# I2C 通信設定
i2c = busio.I2C(board.GP17, board.GP16)  # (SCL, SDA)17,16
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)

#  登録文字順番に表示(文字サイズ1)
display.fill(0)                      # 画面消去
char_width = 12                      # 文字幅
char_height = 16                     # 文字高さ
chars_per_line = display.width // 12 # 1行の文字数
num = 0                              # 表示座標初期化用
for i in range(255):
    x = char_width * ((i-num) % chars_per_line)   # 文字表示x座標
    y = char_height * ((i-num) // chars_per_line) # 文字表示y座標
    display.text(chr(i), x, y, 1, font_name="font5x8.bin", size=2) # 文字表示
    if i%40 == 39: # iが40カウントごとに文字を出力。座標修正
        display.show()  # 表示出力
        time.sleep(2)   # 表示時間
        display.fill(0) # 画面消去
        num = num + 40  # 表示座標を(0,0)へ
display.show()
time.sleep(1)

#  登録文字一覧表示(文字サイズ1)
display.fill(0)
char_width = 6
char_height = 8
chars_per_line = display.width // 6
for i in range(168): # 1ページ文の文字を表示
    x = char_width * (i % chars_per_line)
    y = char_height * (i // chars_per_line)
    display.text(chr(i), x, y, 1, font_name="font5x8.bin", size=1)
display.show()
time.sleep(2)

display.fill(0)
for i in range(168,255): # 残りの文字を表示
    x = char_width * ((i-168) % chars_per_line)
    y = char_height * ((i-168) // chars_per_line)
    display.text(chr(i), x, y, 1, font_name="font5x8.bin", size=1)
display.show()

5.必要なライブラリのインストール方法

ライブラリのインストールは「Thonny」からもできますがエラーが出ることが多いため、ライブラリファイルをダウンロードしてラズパイ本体内の「lib」フォルダにコピーした方が良いと思います。

ライブラリファイルは以下の「Adafruit社」のライブラリダウンロードページからダウンロードできます。

CircuitPython - Libraries
The easiest way to program microcontrollers
ダウンロードするファイルのバージョンはラズパイPico側の「Circuitpython」と同じものをダウンロードする必要があります。

今回のSSD1306を使用するために必要なライブラリは以下になります。

①adafruit_ssd1306
②adafruit_framebuf
③font5x8.bin(ライブラリではなく文字フォントデータです)

①と②をダウンロードしたライブラリファイル(libフォルダ)の中から探して、ラズパイ本体内の「lib」フォルダにコピーします。
③はライブラリファイルではなく文字フォントデータです。これは実行するプログラム「code.py」と同じ場所に置きます。

「CircuitPython」のライブラリの追加方法は以下のリンクで詳しく紹介しています。

ラズパイPicoの使い方 CircuitPython&開発環境Thonny
Raspberry Pi PicoでCircuitPythonを使ったプログラミング方法を開発環境Thonnyを使用してインストールからライブラリの追加、サンプルプログラム(コピペ)による動作確認(液晶表示SSD1306を例に)まで詳しく紹介します。

6.基本的な表示方法の紹介

文字や図形等の基本的な表示は以下のように表示位置をx, y座標で指定して行います。

塗り潰し円と三角については標準関数が無いため自作してます。上のサンプルプログラムを参照してください。
# 表示内容消去
display.fill(0)

# 色指定のTrue[1]は白、False[0]で黒
# 文字列表示(フォントとsizeは省略可)
display.text("表示内容", x, y, 色, font_name="フォントデータ", size=倍率)

# 1文字表示(iで数値指定[0〜254]、フォントとsizeは省略可)
display.text(chr(i), x, y, 色, font_name="フォントデータ", size=倍率)
    
# 図形描画
display.hline(x, y, 長さ, 色)          # 指定座標から横線
display.vline(x, y, 長さ, 色)          # 指定座標から縦線
display.line(x1, y1, x2, x2, 色)      # 指定座標1から指定座標2までの線
display.circle(x, y, 半径, 色)         # 指定座標を中心に指定半径の円
display.rect(x, y, 幅, 高さ, 色)       # 指定座標に四角
display.fill_rect(x, y, 幅, 高さ, 色)  # 指定座標に 塗り潰し四角
display.pixel(x, y, 色)               # 座標を指定した点
display.scroll(x, y)                  # 指定座標へ全画面スクロール

# 設定した内容を表示
display.show()

以下のGitHubでも液晶表示ライブラリ「Adafruit_CircuitPython_SSD1306」の使用例が紹介されています。

Adafruit_CircuitPython_SSD1306/examples at main · adafruit/Adafruit_CircuitPython_SSD1306
Adafruit CircuitPython framebuf driver for SSD1306 or SSD1305 OLED displays. Not for use with displayio. See README. - adafruit/Adafruit_CircuitPython_SSD1306

7.まとめ

「Raspberry Pi Pico」で「CircuitPython」を使用した有機ELディスプレイ(OLED)SSD1306の使い方を紹介しました。

「MicroPython」のライブラリ(micropython-ssd1306)では文字サイズの指定ができなかったり、円を描くコマンドが無かったりしましたが「Circuit Python」のライブラリ(adafruit-circuitpython-ssd1306)では円の標準関数もあり、文字も倍率だけですが指定できるため画面の自由度は高いと思います。

しかし、画面の描画速度は「CircuitPython」の方が遅いように感じました。頻繁に数値を更新するような画面の場合は「MicroPython」の方がいいように感じました。

「MicroPython」を使用したSSD1306の使用方法は以下のリンクで詳しく紹介しています。

ラズパイPicoでSSD1306有機ELディスプレイの使い方 MicroPython編
液晶表示器のないRaspberry Pi PicoでOLED SSD1306の使い方をMicroPythonのサンプルプログラムで紹介。開発環境はTonnyを使用します。

コメント

  1. テラ より:

    ここで解説されている プログラムは CircuitPython の環境ではなく MicroPython の環境では、動作しませんか? 私は二倍文字を使ってみたいと考えてます。

    • logikara より:

      ここで紹介しているサンプルプログラムはMicroPythonでは動作しません。
      文字サイズの変更は私もMicroPythonでの方法を探りましたが、簡単にできる方法が見つからなかったのでCircuitPythonでの方法で紹介しています。
      こちら(https://logikara.blog/pico_thonny_micropy/)でCircuitPythonの使い方も紹介していますので、CircuitPythonでお試しください。

  2. テラ より:

    回答 ありがとうございました。CircuitPython を使うには、多分、pico 内部のファームウェアも、それ用に変更しなければならない? のかな、ちょっと面倒だなあと思いました。

    • logikara より:

      確かにファームウェアの書き換えは面倒ですね^^;
      私は結構頻繁に書き替えます。Thonyを使えば簡単なので是非お試しください。
      Pico内部のデータは消えるのでバックアップをお忘れなく。
      USBメモリ感覚で好きなデータ入れて参照して使えるので慣れるとコッチの方が便利です。

  3. テラ より:

    MicroPython 版 と CircuitPython 版 でちらも ssd1306 表示プログラム 動作確認できました。参考になりました、ありがとうございました。

    • logikara より:

      MicroPython と CircuitPython はどちらがいいというわけでもなく、状況によって使い分けるといいと思うので、両方で動作確認できてよかったです^^

タイトルとURLをコピーしました