2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

共立・シリコンハウスのOLEDディスプレイをSPIで動かす

Last updated at Posted at 2020-04-29

#OLEDディスプレイ

大阪日本橋にある共立電子の「シリコンハウス」「デジット」は、
言ってみれば関西の秋月電子的なポジションです。
そんなお店で売っている魅力的なデバイスの一つに、
「OLEDディスプレイ」があります。
https://eleshop.jp/shop/g/gDAV411/

コントローラはWS0010です。
いくつか種類がありますが、とてもくっきり表示されるのがポイント。
オーソドックスな制御法だと、4bit方式とか8bit方式とか、
まぁ線の多さが目立つわけです。
(べつにこのディスプレイに限った話ではありませんが)

あまりメジャーではありませんが、SPI通信で制御する方法があり、
そうすることで配線をかなり減らせます。
ちなみに、SPIでは10bitでデータを送る必要があります。
(ArduinoとかであればデフォのSPIは8bitで送受信されるらしい)

OLEDディスプレイ+SPI化のタッグの良いところは
1.もともとOLEDディスプレイは表示の更新が早い(複雑な図形は困難)
2.配線線が少ない(MOSI、CS、CLKのみ)
なんといってもこの2つ。

オリジナルで10bit送信可能なSPIっぽいプログラムをしている人を見かけたので、
それに習って動作検証しました。
もともと生粋のプログラマではありませんが、
なにかのヒントになれば幸いです。

#デバイスをSPIモードに改造する
デバイス背面のチップ抵抗をいじって、SPIモードにする必要があります。
基本、購入した際についてくる資料のとおりに改造すればSPIモードになります。
今回使用した20桁x4行タイプは下記のとおりに改造しました。
※SPI改造は自己責任でお願いします

画像はSPI改造後です。赤丸のところを修正してください。
こちらで使用したボードはArduino Micro。
また、20桁x4行タイプOLEDのピンアサインは下記のとおりにしました。

1 2 12 14 15
GND 5V CLK MOSI CS

下記ソースのとおりに配線して頂ければ動くはず。
動検用のソースなので、だいぶ荒っぽい書き方をしてしまいました笑
あくまで参考までにお願いします笑

oled_display.ino
#include <SPI.h>

#define cs_pin 10
#define clk_pin 13
#define MOSI_pin 11

int spiSend(unsigned int rs, unsigned char data);

void setup()
{
  // put your setup code here, to run once
  Serial.begin(9600); // 9600bpsでポートを開く
  pinMode(cs_pin, OUTPUT);
  pinMode(MOSI_pin, OUTPUT);
  pinMode(clk_pin, OUTPUT);
  digitalWrite(cs_pin, 1);
  digitalWrite(clk_pin, 1);
  delay(100);
  displayWrite(0, 0);
  displayWrite(0, 0);
  displayWrite(0, 0);
  displayWrite(0, 0);
  displayWrite(0, 0);
  delay(10);
  displayWrite(0, 0b00111000);//function set
  delay(10);
  displayWrite(0, 0b00001100);//display set
  delay(10);
  displayWrite(0, 0b00000001);//clear disp
  delay(10);
  displayWrite(0, 0b00000010);//return home
  delay(10);
  displayWrite(0, 0b00000110);//Entry 

  delay(200);
  char chara[4] ={'S','A','K','U'};

  displayWrite(0,0b10000000);//カーソルを1行目トップへ
  displayWrite(1, chara[0]);
  displayWrite(0,0b11000000);//カーソルを2行目トップへ
  displayWrite(1, chara[1]);
  displayWrite(0,0b10010100);//カーソルを3行目トップへ
  displayWrite(1, chara[2]);
  displayWrite(0,0b11010100);//カーソルを4行目トップへ
  displayWrite(1, chara[3]);

  delay(10);

}

void loop()
{
  
}

void displayWrite(unsigned int rs, unsigned char data){
  int i = 10;//10bit send
  rs = int(rs << 9) | int(data);

  digitalWrite(cs_pin, 0);
  while (i--)
  {
    digitalWrite(MOSI_pin, (rs >> i) & 1);
    digitalWrite(clk_pin, 0);
    digitalWrite(clk_pin, 1);
  }
  digitalWrite(cs_pin, 1); 
}

※ソース参考 https://sakura87.net/archives/4389

#ディスプレイへのコマンド
ソースを見ていただくと、イニシャライズの際や、
実際に文字表示させている際に得体のしれないコマンドを発行しています。
これは仕様書に書かれている内容を反映したものです。
(英語が苦手な私には苦行でした・・・)

イニシャライズの際は、このコマンド発行の順番も大事なのでしょうが、
ひとまず動いてしまったので公開しています。
また、displayWrite関数では8bitのコマンドを指定すると、
頭に2bitRS、R/WBを追加して送信しています。

##クリアディスプレイ
簡単に言えば、ディスプレイ上の表示をすべて消します。
仕様書には下記のように10bit送るよう、記されています。

RS R/WB D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 0 0 0 1

よってサンプルコードのコマンドで下記を送信します。
RS→0   R/WB→0
DB7~DB0→0b00000001

ソコソコ時間がかかるコマンドなので、
定常的な表示ではなかなか使わないかも知れませんね。
状態遷移の際等に使うことになると思います。

##Return Home(カーソルをホームへ)
カーソルを0行目0列へ移動させます。
後で記述するSet DDRAM Addressとも関係しますが、
手っ取り早くホームへ戻るならこのコマンド。

RS R/WB D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 0 0 1 0
**RS→0   R/WB→0
DB7~DB0→0b000000010**

##ディスプレイOnOff設定

RS R/WB D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 1 D C B

さて出てきました、設定パラメータD,C,B。
要は設定パラメータをそれぞれ0か1か決めてコマンドを送るわけです。
D:DISPLAY ON/OFF BIT
これは簡単。Dが0だとディスプレイが消えます。
C:CURSOR DISPLAY CONTROL BIT
デバッグしているときは役に立つかもしれません。
この手のディスプレイにはカーソルという概念があります。
Microsoft Wordのカーソルとほぼ同じもので、
文字表示コマンドを送ると、カーソルがある場所に表示されます。
言ってみればディスプレイは何処に何を表示させるかを制御しなければならないので、
いまカーソルがどこにあるかってのが見えたほうが、
コーディングしやすいように思います。
不要であれば0を指定しOFFにしましょう。

B:BLINKING CONTROL BIT
先ほどのカーソルを点滅させることができます。
そのほうが見やすければ1を指定してONにしましょう。

##カーソルのシフト、ディスプレイ内容のシフト
カーソルの1桁左右シフト、もしくは
ディスプレイされている内容の全体左右シフトです。

##ファンクション設定

RS R/WB D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 1 DL N F FT1 FT0
ディスプレイの様々な設定をセットします。
フォント、ディスプレイの行など。

###DL:INTERFACD DATA LENGTH CONTROL BIT
データを8ビットで送るか4ビットで送るかなんですが、
ぶっちゃけよくわからん・・・
ひとまず8bitに設定しています・・・

###N:NUMBER OF DSPLAY LINE
OLEDディスプレイが1行か2行かを選べます
2行もしくは4行の場合は1に設定してください。

###F:CHARACTER FONT SET
表示させる文字のフォントサイズを選びます。
5x8か5x10の2通りですが、
これはディスプレイの仕様にのっとり5x8を選ぶので、
0を設定します。

###FT1、FT2:FONT TABLE SELECTION
表示させるフォントの種類を選びます。

FT1,FT0の設定 キャラクターテーブル
0,0 英語と日本語のフォントを選択
0,1 ウェスタンヨーロピアン1
1,0 英語とロシア語のフォントを選択
1,1 ウェスタンヨーロピアン2

0,0の組み合わせ以外は使うことがないと思います。。。
と思ったけど顔文字使うならロシア語フォント必要か?!

##DDRAMアドレス設定

RS R/WB D7 D6 D5 D4 D3 D2 D1 D0
0 0 1 ADD ADD ADD ADD ADD ADD ADD

カーソルを任意の位置へ持っていくときに使えます。
要は7桁のADDが7bitの座標、つまり128桁分の座標に相当します。
###1行のディスプレイの場合
左から順番に0000000、0000001、0000010・・・となります。
16桁までのディスプレイであれば、
それ以降の座標に文字を設定しても表示はされません。
ただ、表示されずとも設定は可能なので、
例えばスクロールさせる際などに使われることになるでしょう。
###2行のディスプレイの場合
1行目左から0000000、0000001、0000010・・・

2行目左から1000000、1000001、1000010・・・となります。
アドレスの最大サイズは128桁分と変わらず、
64桁で2つに分解しているということですね。
ちなみに1行目と2行目は独立しておらず

あくまでメモリ上では128桁として扱われています。
なのでスクロールしたりすると、行が異なっても全体がスクロールします。
###4行のディスプレイの場合
1行目左から0000000、0000001、0000010・・・
2行目左から1000000、1000001、1000010・・・
3行目左から0010100、0010101、0010110・・・
4行目左から1010100、1010101、1010110・・・
これは2行ディスプレイをさらに2分割して4行対応させています。
128桁をきれいに4分割している訳ではないので注意です!
1行目は20桁
2行目も20桁
3行目は44桁
4行目も44桁
です。
また、メモリのアドレスとしては1行目の次が3行目と飛んでいます。
1行目→3行目→2行目→4行目
ですのでご注意ください。
念の為、2行タイプと4行タイプのアドレス一覧表(10進数表記)を載せておきます。

##文字表示

RS R/WB D7 D6 D5 D4 D3 D2 D1 D0
1 0 WD WD WD WD WD WD WD WD
文字表示はRSが1なので注意です!
WD8bitを設定することで任意の文字を指定できます。
詳しくは仕様書のキャラクターテーブルをご覧ください。
ただ、アスキーコードと対応している様なので、
Char型でそのまま送れば英数記号は表示できると思います。

##エントリー設定
あんま使わなさそうだから解析保留。
##その他もろもろ
私は使ってないので追々追記します笑

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?