桜のはなびらブログロゴ

桜のはなびらブログ

Raspberry Pi2でSSD1331搭載0.95インチカラー有機ELを制御

皆様ご無沙汰しております。Sakura87です。
最近は天候にも恵まれずいくつか購入したものもありますがリアルも多忙だったのでブログを書く機会がなかったです。

いくつか購入したものに関しては今後公開する予定ですが、とりあえず今日はこの前購入した小型のカラー有機ELディスプレイを制御してみたいと思います。

購入したものは秋月電子で買える上記のものですがSSD1331というコントローラを搭載した96×64ピクセルのカラー有機ELであれば同様に処理が可能です。

製品の写真

購入した有機ELはこのようなパッケージに入ってきました。

製品の正面。
特に何の変哲もない有機ELモジュールです。

裏面。こちらに有機ELの制御に必要なものが設置されているようです。

接続

この有機ELモジュールはリセット信号とデータ・コマンドのセレクトピンがある以外はSPI信号そのままで使えます。ピンはこのモジュールの描画面を表にして左から以下のようになっています。

ピン番号名称役割
1GNDGND
2VCC3.3V入力
3SCLシリアルクロック
4SDAデータ転送ピン
5RESリセット信号
6DCデータ・コマンドコントロール
7CSチップセレクト

このようになっていて、リセット信号はセオリー通りに使うのであればGPIOで制御する必要がありますが、基本的にはVCCにつないでおけばよく、多くのネット作例を見てみても両者半々くらいで存在しているようです。

今回はめんどくさいのでリセット信号は常時VCCに接続しておくことにしました。一応テスト段階ではちゃんと描画開始アドレスを描画前に送っておけば特に画面が乱れることはありませんでした。

Raspberry Pi側の接続ですが、SPIの信号はピンが決まっていますので以下の画像を参考に接続します。

上の画像はラズベリーパイ2・3(4も?)のUSBやLANのコネクタがある方を下にした場合のピン配列で、17~26番のピンを使用します。接続の対応表は以下の通りです。

有機ELRaspberry Pi有機EL
名称No名称No No名称No名称
VCC/RES2/53.3V17 18GPIO 24 
SDA4MOSI19 20GND1GND
 MISO21 22GPIO 256DC
SCL3SCLK23 24CE.17CS

MISOとGPIO24番は未使用です。GPIO24はリセット信号を処理する場合には活用出来そうです。MISOは基本的に空きポートになると思います。

電源やGND、GPIOに関してはあいているところであればどこでもよいですが、以上の接続であれば使用するピンが一カ所に集中するのですっきりすると思います。

特に有機ELディスプレイは他のデバイスをつないでその情報を表示する事にも使うと思いますのでまとめることで他のデバイスとの接続性もよくなります。SPIは一つのポートにたくさん数珠つなぎをしてCE信号を切り替えることによって複数使用することが可能ですので。接続に関しては各自が使用する他のデバイスとの兼ね合いで決めてください。

コーディング

さて、それではコードを書いていくのですが。今回はGPIOも標準命令を使用するので追加のライブラリは不要です。ただしテキストを使用する場合は以下のFONT-X読み込みライブラリを使用します。また、こちらで紹介するコードもすべてそのライブラリを使用する体で書いてあります。

なお、前回まではC言語で書いてきましたが、最近は仕事などでC++を利用する機会が多いことから、今回からC++で書いています。ただしC++らしいコードはあまり使っていないので、インクルードを調整すればC言語でもほぼそのままで使えると思います。

大まかな制御方法

この有機ELモジュールは以下のように制御することで動かすことが出来ます。

  1. GPIO・SPI信号を初期化する
  2. DCピンをコマンドモードに設定
  3. ディスプレイモードを設定する
  4. Remapと色深度を設定する
  5. ディスプレイをオンにする
  6. その他必要な設定を行う
  7. DCピンをデータモードに設定
  8. 液晶に表示するデータを転送

以上が一連の大まかな制御方法です。

特に気にするべき所はディスプレイをオンにする所とDCピンの制御ですね。それ以外は難しいものでもないです。

必要なインクルードなどの定義

今回使用するのに必要なインクルードなどの定義を行います。

インクルードはもしかしたら不要な部分もあるかもしれませんが、これでよいです。

FONTXの部分はこの前使用して気に入ったぱうフォントを使用するように設定しています。他のフォント似する場合は11・12行目をそのフォントに合わせて修正するかフォントのファイル名をこちらに入れ替えてください。

この2行の後にFONTXのライブラリをインクルードしています。

GPIO関係の処理がその後にあります。

20行のDefineがDCピンのIO番号を指定する箇所になります。ここを自由に変更することで他のピンに設定することも可能です。
なお、こちらのプログラムは先ほど掲示したIOリストの「OS標準」のGPIO番号を指定します。

GPIO関連の関数

ということでGPIOを制御する関数を作ります。
関数はGPIOを初期化する関数、クローズする関数、実際にIOを変更する関数の3つを作ります。

GPIO初期化関数

やっていることはGPIO番号を付与したアドレスをsprintfで生成してOpenし、設定値を設定しているだけです。sprintfは脆弱性の元にもなるようですが、ここでは固定値しか扱わないので使いやすい方を選びました。

GPIOの初期化方法は基本的にはだーいぶ前に紹介したコンソールで処理する方法をそのまま行います。

https://sakura87.net/archives/1442

open命令でオープンしたファイルに、上の記事の通りに制御して設定してあげればよいのですが、最初の初期化の後命令が完了しても処理に少し時間がかかる場合があるようで、その後21行と27行の2つのOpenはWhileで-1以外の数値が返るまで続けています。今のところここでデッドロックするようなことはないですが、心配ならば1万回くらいでやめるようにした方がいいかもしれません。ここで必要なのは一番最後に開いたものです。これだけReturnで返します。それ以外は設定を転送したらCloseしてOKです。

GPIOクローズ関数

次にGPIOをクローズする関数を作ります。
これも上の容量で作れます。基本的にはunexportファイルを開いてポート番号を投げてやればOKです。

クローズはまぁ説明は不要ですね。実はなくてもいいような気もします。

GPIO制御命令

次に一番使用するGPIO制御命令です。これでIOピンのH・Lを切り替えます。

単に先ほど初期化した最後のIOに値を書き込めばよいだけです。

以上でGPIOの必要な関数はすべてそろいました。
次にSPIの初期化を行いますが、ついでに以上のコマンドを使用してGPIOの解放と再取得を行います。

GPIOとSPI信号の取得

 

元々リセット信号も転送していたので関数名がそれに沿ったものになっていますが、やっているのはDCピン用GPIOの初期化とSPIの初期化です。

SPIの初期化はいつもやっているので割愛します。いつもと違うのはSPIのモードが3になるくらいですね。一応説明するとSPIのデバイスファイルをオープンしてioctlで設定を転送している感じです。

初期化されたら引数に指定した変数にデータを書き込むアドレスが帰ります。oledのほうにSPIを制御するアドレスを格納する変数。dcpinの方にDCコントロール信号を制御するアドレスを格納する変数を指定して実行するとアドレスが返ってきます。0?か負数であれば失敗です。

さて次は実際にコマンドやデータを転送する関数を作ります。

データ転送関数

 

今までやったことの寄せ集め。普段のSPI命令と違うところは、DCコントロールの制御が先頭に入っているという所だけ。また、今回は見込まれる最大転送サイズが12KBほどあり、ラズパイのSPIバッファを超えるため、2048バイトごとに区切って転送する処理もつけています。

spi_fdに初期化コマンドで引数oledの方に指定した変数で返ってきたSPIのアドレスを、dcpin_fdの方にdcpinで指定した変数に返ってきたDCピンのアドレスを指定し、modeにコマンド転送モードであれば0(L)をデータ転送モードであれば1(H)を指定します。

dataに転送するデータが格納された変数へのポインタを。sizeに転送するバイト数を指定します。

ここまで作ればあとは転送するコードを書き込めばOKです。

文字転送コード

次に文字を転送するコードを書きます。

やっていることは例のライブラリを使用して文字パターンを取得し、1bitカラーを16bitにかさ上げ、BMPファイルと同じように下から上に入れ替えているという処理です。

22行~32行までは描画範囲を指定するコマンドです。0x75コマンドが行、0x15コマンドが列の指定を行うコマンドです。
どちらが先に転送してもよいようですが、まぁ行列で転送しておくのがよいでしょう。

メイン関数

それではこれらを統合して制御するメイン関数を作成します。チョット長いですが。

 

転送などに使用するバッファを確保して有機ELをソフトウェア的に初期化するためのコマンドを転送します。

この部分が液晶初期化コマンドです。
まずはディスプレイモードをノーマルに設定します。次にRemapと色深度を指定するのですが、これは以下の通りになっています。

bit設定値説明
70カラーフォーマット
[7:6] 00 256色 01 65k色1 10 65k色2
61
51COM Split Enable(0:Disable 1:Enable)
41Scan from 0: COM0 to COM[N-1] 1: COM[N-1] to COM 0
30Left-Right Swapping on COM 0:Disable 1:Enable
20色情報のオーダー0: RGB 1:BGR
11RAM Column maps. 0: 0 to 95 1: 95 to 0
00Address Increment 0:Horizonal 1:Vertical

基本的には0x72が扱いやすいようです。7:6ビットの色情報は上の設定で今回は使用出来ましたが、どうやらSPIは8bitで転送するのでこちらでいいようです。5ビット目は0にすると間延びした画像になります。単純にデータを流すのであればこの設定がよいようです。
4ビット目は縦方向(横長で使う場合)をどう描画するかという設定で0にすれば上下反転(ピンヘッダがあるほうが下)します。
3ビット目はチョットよくわからないのですが。1にすると表示が乱れます。BMPファイルを扱う感覚で使用するのであれば0でいいようです。
2ビット目は色情報の記録方向でBMPファイルと同じにするのであればBGRを選択します。ただしバイトオーダーがIntel方式と異なるのでBGRを選択した後、バイトオーダーを反転させてあげる必要があります。
1ビット目はRAMのカラムアドレスを入れ替える設定の用です。
これを切り替えることで鏡文字にしたりしなかったり出来ます。1ビット目と4ビット目で表示方向を決定します。

0ビット目はアドレスのインクリメント方向の縦横で今回は横向きに使用するので0です。

最後にディスプレイをオンにする信号である0xAFを転送すればOKです。

あとは描画先の範囲を指定してデータを送り込んでやればOK。
この手のカラーディスプレイの特徴として、描画範囲を指定してデータ転送が出来るので、BMPファイルやフォントデータを色深度さえ合わせればそのまま転送出来て高速に転送することが可能だというところがあります。なのでマイコンで制御出来るカラー液晶・有機ELモジュールはカラーだからと難しく思えますが案外カラーの方がいろいろしなくていい分楽です。

以上ですべてのコードが出そろいました。結構長くなりましたが重要なのはこの項で説明した初期化関係とDataSendコマンドの中身です。
あとは教科書通りのSPI転送を行ってあげれば使えます。

コンパイル

コンパイルは今までgccを使用していましたが今回はC++で書いているのでg++コマンドを使用します。インストール方法や使用方法は基本的にはgccと同じです。

動作風景

有機ELを動作させたときの写真をいくつかあげておきます。
動作方法は最後に掲示する全体のコードをコンパイルして。そのファイルの最初の引数に「i」(画像)または「t」(テキスト)を指定して2番目の引数にファイルを指定してあげれば表示されます。

画像を表示してみた写真

照明の関係で少し色が薄いですが、本物はもう少し色鮮やかです。
表示している画像は16bit B5G6R5形式のBMPファイルです。これを作成するにはフォトレタッチソフトが必要で、大半の有名なレタッチソフトは作れると思います。

テキストを表示してみた写真

テキストを表示すると1行目が白、2行目が赤、3行目が緑、4行目が青で表示されます。表示色はメイン関数の68行目で変更することが出来ます。今回は行で色を変えていますが、もちろん文字単位での色指定も出来るようです。

終わりに

さて、今回はカラーの有機ELで遊んでみました。
少し駆け足で説明してしまったので、説明足らずやもっとこう言うところがほしいと言ったことがあればコメントへどうぞ。

最近はフルカラーが当たり前の世の中ですが、65,536色表示とはいえ流石有機ELという発色の良さです。画面サイズも少し小さめですが、16×16ピクセルフォントで6×4行の文字表示も可能なのでそれなりに情報も表示出来ますね。

まぁ1,000円程度ですので、チョット凝った数字二桁程度の表示(音量とか温度とか…)というのもいいと思いますし、4分の3をジャケット表示にしたプレイヤーなんかもアリだと思います。

ともかく小さいなりにいろいろと使えそうな有機ELモジュールだと思います。特にフォントを扱う場合は基本的に色深度をかさ上げして上げるだけでいいのでかなり楽です。

さて次回ですが、いくつかものを買っていますので小ネタをちょいちょい投稿していくことになると思います。

それでは。

全体のソースコード

繰り返しになりますが今回はC++で書いているのでg++を使ってコンパイルしてください。

 

更新履歴

  1. 令和元年10月16日(水)
    初版発行
  2. 令和元年10月25日(金)
    ラズベリーパイとの接続表が一部間違っていたのと、&や<>などの記号が化けていたで修正

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事