💻

シンセ開発③:LovyanGFXでOLEDを制御する

2024/07/22に公開

本記事は、私が開発しているデジタルシンセサイザに関する内容の一部です。
自作デジタルシンセのまとめ記事はこちら。

自作シンセにディスプレイ

シンセサイザーは様々なパラメーターを弄って音作りをしていきます。
そのため、パラメーター情報が見れる表示器は必要不可欠です。
今回はボタンとディスプレイを実装して、UIを充実させていきたいと思います。

LovyanGFXでOLEDを制御する

表示器には様々な物がありますが、今回はOLED(有機EL)を選びました。
価格が高い上に画面サイズが小さい物が多いですが、このような小さな製品に取り付けるには丁度いい大きさだと思います。
バックライトが無く、自己発光するため低消費電力で視認性も良いです。

LovyanGFXとは?

https://github.com/lovyan03/LovyanGFX
AdafruitGFX や TFT_eSPI と互換性を持った、高機能グラフィックライブラリです。
様々な描画機能や画像処理機能を使うことができます。

使用するディスプレイモジュール

Raspberry Pi Picoで使えるI2CかSPIタイプのものを使います。
LovyanGFXに対応したOLEDには以下のようなものがあります。
https://akizukidenshi.com/catalog/g/g112031/
大きさが0.96インチのOLEDで、かなり小さいです。
制御チップはSSD1306です。
https://ja.aliexpress.com/item/1005004131362533.html
Aliexpressの商品ですが動作確認済みです。
1.3インチで0.96インチよりも断然見やすかったです。
制御チップはSH1106です。
※こちらはLovyanGFXで扱う場合オフセットの設定が必要です。

設定用のクラスを作る

LovyanGFXの設定用クラスを作ります。
こちらを参考にして、SSD1306用のコードを書いてみます。

lgfx_rp2040.h
#include <LovyanGFX.hpp>

class LGFXRP2040 : public lgfx::LGFX_Device {
    lgfx::Panel_SSD1306 _panel_instance;
    lgfx::Bus_I2C       _bus_instance;
public:
    LGFXRP2040(void) {
        {
            auto cfg = _bus_instance.config();
            cfg.i2c_port   = 0;      // 使用するI2Cポートを選択 (0 or 1)
            cfg.freq_write = 400000; // 送信時のクロック
            cfg.freq_read  = 400000; // 受信時のクロック
            cfg.pin_sda    = 16;     // SDAを接続しているピン番号
            cfg.pin_scl    = 17;     // SCLを接続しているピン番号
            cfg.i2c_addr   = 0x3C;   // I2Cデバイスのアドレス

            _bus_instance.config(cfg);
            _panel_instance.setBus(&_bus_instance);
        }

        {
            auto cfg = _panel_instance.config();
            cfg.pin_cs           =    -1; // CSが接続されているピン番号   (-1 = disable)
            cfg.pin_rst          =    -1; // RSTが接続されているピン番号  (-1 = disable)
            cfg.pin_busy         =    -1; // BUSYが接続されているピン番号 (-1 = disable)

            cfg.panel_width      =   128; // 実際に表示可能な幅
            cfg.panel_height     =    64; // 実際に表示可能な高さ
            cfg.offset_x         =     0; // パネルのX方向オフセット量
            cfg.offset_y         =     0; // パネルのY方向オフセット量
            cfg.offset_rotation  =     2; // 回転方向の値のオフセット 0~7 (4~7は上下反転)
            cfg.dummy_read_pixel =     8; // ピクセル読出し前のダミーリードのビット数
            cfg.dummy_read_bits  =     1; // ピクセル以外のデータ読出し前のダミーリードのビット数
            cfg.readable         = false; // データ読出しが可能な場合 trueに設定
            cfg.invert           = false; // パネルの明暗が反転してしまう場合 trueに設定
            cfg.rgb_order        = false; // パネルの赤と青が入れ替わってしまう場合 trueに設定
            cfg.dlen_16bit       = false; // 16bitパラレルやSPIでデータ長を16bit単位で送信するパネルの場合 trueに設定
            cfg.bus_shared       = false; // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います)

            _panel_instance.config(cfg);
        }

        setPanel(&_panel_instance);
    }
};

SH1106の場合は以下を変更します。

変更前
lgfx::Panel_SSD1306 _panel_instance;
cfg.offset_x = 0;
変更後
lgfx::Panel_SH110x _panel_instance; // SH110xです
cfg.offset_x = 2; // 描画ずれを修正

グラフィックを描画してみる

main.cppに文字を表示するためのコードを書きます。

main.cpp
#include <Arduino.h>
#include <lgfx_rp2040.h>

LGFXRP2040 display;
static LGFX_Sprite sprite(&display);

void setup() {
    display.init();
    display.fillScreen(TFT_BLACK);
    display.drawString("RP-DS16", 1, 1);
    display.drawString("GFX Testing.", 1, 10);
}

void loop() {
}

実行結果です。

白色のOLEDは発色が良く見やすいです。

図形描画やフォント描画などについては以下の記事を参考にして下さい。
https://lang-ship.com/blog/work/lovyangfx-1/

ユニバーサル基板に引っ越し

ブレッドボードでは配線も外れやすく安定しないため、こちらの記事で紹介されている基板を JLCPCB で注文し、はんだ付けをしてみました。
https://note.com/tsurumy/n/ne98d21d40311

思ったよりごちゃごちゃになってしまいました。(基板の大きさを調節しておくべきだった)

コネクタとケーブルだらけです。

DINコネクタとステレオミニジャックの両方を挿せるところがお気に入りです。

DIN変換基板とステレオミニジャック変換基板の両方に対応

ステレオミニプラグを使いたい時

DINケーブルを使いたい時


次の記事
https://zenn.dev/saisana299/articles/282e90d03b312f

Discussion