OLED SSD1306 で点、線、四角形、円を描く ( ESP32 , ESP8266 , Wire ライブラリのみ使用 )

記事公開日:2017年10月18日

スポンサーリンク

こんばんは。

前回の記事に引き続き、再検証した I2C通信の小型 有機EL ディスプレイ ( OLED ) SSD1306 で、グラフィカルな点、線、四角形、円を描いてみたいと思います。
Adafruit さんや、他の流通しているライブラリは一切使いません。
Arduino core for ESP32 および ESP8266 標準の Wire ライブラリのみ使います
プロのプログラマーのようなコードとはいきませんが、アマチュアの私なりに試行錯誤してみました。

前回でも言いましたが、OLED SSD1306 はグラフィック描画には不向きです。
Pixel 単位指定ではなく、Segment / Common 方式だからです。

でも、ちょっと工夫すると、何とか描けるもんです。
予め、画面すべての Segment 用配列を用意するというものです。
メモリを食うことになるのですがが、私の頭ではこれしかないように思います。
結局、Adafruit さんのライブラリでも、PROGMEM を使ったり、FLASH に保存したりしているようです。
外付け SRAM に置くのもイイかも知れません。

今回は分かりやすく、グローバル変数領域に置いて、グラフィック描画をしてみたいと思います。

使うもの

複数紹介していますが、どの組み合わせでも動作確認しております。
中国の販売店によっては仕様が変わっている場合がありますのでご注意ください。

I2C通信用 OLED SSD1396 ディスプレイモジュール


ESP-WROOM-32 ( ESP32 )開発ボード


ESP-WROOM-02 ( ESP8266 ) 開発ボード

ブレッドボード 及び ジャンパーワイヤー等

Arduino core for ESP32 または ESP8266 の設定

Arduino IDE は 1.8.5 で動作確認しております。

ESP-WROOM-32 ( ESP32 )の場合は、Arduino core for ESP32 を予めインストールしておいてください。
Arduino core for ESP32 は必ず最新版を使用してください
インストール方法は以下の記事を参照してください。

Arduino core for the ESP32 のインストール方法

ESP-WROOM-02 ( ESP8266 )の場合は、Arduino core for the ESP8266 をインストールしておいてください。
インストール方法は以下の記事を参照してください。

Arduino IDE に Stable ( Staging )版 ESP8266 ボードをインストールする方法

接続する

前回の記事と同じなのでそれを参照してください。

Segment/Common方式のグラフィック描画方法

では、普通のグラフィックディスプレイとは異なる、厄介な Segment/Common方式のディスプレイ描画方法を私なりの視点で紹介してみたいと思います。
恐らく、Adafruit さんのライブラリでも同じようなことをやっていると思われます。

前回の記事で紹介したように、SSD1306 の初期化で、事前に左上端を始点(0 , 0)として設定してあるものとします。

Segment が最少単位ですので、画面すべての segment を配列で割り当てるという方式をやってみました。
Segment は横に0~127 まであり、Page は 0~7 までなので、簡単に分かりやすいように、グローバル変数領域で

uint8_t segment[128][8] = { 0 };

とします。
{ 0 } は {} でも良いのですが、分かりやすいように { 0 }を使っています。
配列の全てを一気にゼロで初期化するという意味です。

そうすると、下図の様に座標に近い感じで  segment ごとに割り当てることができます。

ESP32_SSD1306_Graphic01

こうすると、SRAMメモリを 128×8 = 1024 byte を消費することになります。
Arduino UNO や ESP8266 にはちょっと辛いですね。
でも、ESP32 なら余裕があるかと思います。
もし、SRAMを消費したくなければ、PROGMEMなどを使って FLASH へ保存するしかありません。
ただ、その分、読み書きが遅くなります。

例えば、座標 ( 11 , 3 )から、座標( 11,  10 ) までの単独の一本の水平線を描きたいとします。
すると、Page1 の3番目の segment  00001000 というビットを書き込み、それを10番目の segment まで連続書き込みすれば良いわけです。
つまり、

segment[3][1] = 0b00001000;
segment[4][1] = 0b00001000;

というように書き込んで、それを SSD1306 へ送信すれば水平線が表示されます。

ESP32_SSD1306_Graphic02

では、この直線を消さずに新たに Page1 に水平線を描きたい場合はどうするか・・・。

例えば、座標 (3, 9) ~座標(10, 9) へ水平線を描きたいとします。
その場合は、

segment[3][1] = segment[3][1] | 0b00000010;
segment[4][1] = segment[4][1] | 0b00000010;

というように前に記憶したバイトを OR演算すれば、前のバイトは消えません。

ESP32_SSD1306_Graphic03

では、Page を跨ぐ、(3 , 5)~(3 , 17)という垂直線はどうかというと、たとえば下図の様な感じです。

ESP32_SSD1306_Graphic04

Page1 の segment[3][1] は 0xFF( 11111111 ) で簡単ですが、その上下はとても難しいですね。
座標値をビットシフトと反転を使って計算するのですが、かなり数学的な頭を使って疲れ果ててしまいました。
アマチュアの私なりに考えたプログラムは後で紹介します。
もっと良い方法があるかも知れません。

斜線は更に難しくなります。
斜線の場合は点描画を連続させる方法しか思いつきませんでした。
ただ、それでも角度によっては、X軸とY軸方向のどちらを優先して分割するかとか、難解でした。

というわけで、これを一から説明するのはとても時間が足りないので、申し訳ないですが割愛させていただきます。
後で紹介するプログラムを解明していただければと思います。

ということで、この SSD1306 の OLED ディスプレイでグラフィック描画することはとても厄介だということがお分かりいただけましたでしょうか?

SSD1306 を使うならば、文字表示に特化した方がいいと思いますし、ESP32と合体したボードを販売するならば SSD1331 にした方が絶対に良いと思いますよ。

でも、よくこれで、ゲームとか作る人がいるなぁ・・と感心してしまいます。

でも、私なりに Adafruitさんのライブラリに頼らずに、独自でグラフィック描画に挑戦してみましたので、次をご覧ください。

スポンサーリンク


mgo-tec電子工作 関連コンテンツ ( 広告含む )

投稿者:

mgo-tec

Arduino , ESP32 ( ESP-WROOM-32 ) , ESP8266 ( ESP-WROOM-02 )等を使って、主にスマホと連携した電子工作やプログラミング記事を書いてます。ライブラリも作ったりしてます。趣味、独学でやってますので、動作保証はしません。
電子回路やプログラミングの専門家ではありません。
畑違いの仕事をしてます。
でも、少しだけ電気の知識が必要な仕事なので、電気工事士や工事担任者等の資格は持ってます。

コメントを残す

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

*画像の文字を入力してください。(スパム防止の為)