さくらのジャンク箱ロゴ

Sakura87がほぼ月刊でお届けするPCや電子工作と写真の備忘録てきなブログ @なんと20周年

Arduinoでキャラクター有機EL制御(SPI接続)

この記事は7年ほど前に投稿されました。内容が古くなっている可能性がありますので更新日時にご注意ください。

共立エレショップで売られているWinstarのキャラクター有機ELをSPI接続で使ってみたいと思います。

分量が少ないので本当はアンプ制作の記事にまとめようと思っていたのですが、ATTiny2313の2KBしかないフラッシュと戦っていますのでもう少し時間がかかるため、先に公開する事にしました。

はじめに

マイコンで情報を表示するアイテムとしては、主に液晶やLEDなどを使う事が多いと思いますが、今回はキャラクタータイプの有機ELディスプレイを使ってみたいと思います。

使った有機ELディスプレイは以下のものです。

こちらは緑文字で16桁1行表示のWEH001601AGPP5N00000というものになりますが、基本的に他の機種でも、例えばWEH001602Aのような、WEHからはじまってAGPP5Nが含まれているディスプレイであれば同じ操作で制御ができると思います。(実際に試したわけじゃないので保証はしません。また、一部レイアウトが違う場合があります。)

本体写真

見た目は普通のキャラクター液晶と同じような感じ。バックライトがない分ちょっと薄め。

裏側も至って普通。

今までいろいろなマイコンでキャラクター液晶を使ってきたのなら特に目新しいところはないと思います。

しかし液晶に比べて有機ELディスプレイが優れている点としては

  • 低消費電力(表示内容による)
  • 高輝度高コントラスト(黒が本当に黒なので)
  • 応答速度が高速
  • 広視野角(論理上180度以上の視野角がある。)

というところが多くあげられ、このディスプレイに関してもほぼ同じような比較となります。デメリットとしては寿命が短いのと焼き付きがあるくらいですが。キャラクタータイプであれば基本的に文字の輝度が使用していくうちにばらついてくる程度ですのであまり気にならないかもしれません。

制御方法について

この液晶は共立の表記によるとHD44780系とほぼ同じ操作性という事で、実際に少しイニシャライズが違うだけでほとんど差はありません。イニシャライズさえしてしまえば後は既存のキャラクター液晶のプログラムがほぼそのまま使えるでしょう。

また、同ページにあるようにこちらのディスプレイは4/8bitのパラレルインターフェイスが標準となっていますが。オプションでSPIモードにもできるようですので、今回はそちらを使ってみたいと思います。

※通常改造するとメーカー保証などがなくなりますが、共立で買う場合はそもそも最初からそんなのないので、気にしなくてよいです。

おそらくメーカーに発注する際にSPIモードを指定すればSPIの設定で売ってくれるのでしょうが。個人で買うのであれば改造するしか道はないですね。そこでいろいろ調べた結果、提供元は違うようですが、物は同じディスプレイをSPIモードに改造している人が居ましたので以下のページを参考に改造しました。

こちらのページによると、PSジャンパーの0Ωの抵抗をLポジションに移動させ、CSジャンパーにある抵抗を除去してJCSに取り付ける事で16番ピンがCSピンに変わってSPIで通信ができるようになるそうです。(Google先生がそう言ってました。)

結果的に上図の箇所を変更するようです。CSLの抵抗を除去、JCSをショート(CSLの抵抗が使える)PSHに乗っている抵抗をPSLに移動させるという作業ですね。IOピン近くのジャンパーは上のサイトでは変更する様に書いていますが、これは別の方法の手順のようですので、SPIモードに切り替える場合は裏返して左側の抵抗を変更すればよいという事になります。

少し画像が小さいですが、変更するとこのようになります。

あいにく0Ωの抵抗は遙か彼方に旅立ってしまったので、半田盛ってジャンパーとしました。

なお、この状態で配線は以下の通りになるようです。

PIN 名称 機能
1 GND GND端子
2 Vcc +5V電源
12 SCL SPIクロック
13 MISO SPIデータ出力 有機EL→マイコン
14 MOSI SPIデータ入力 有機EL←マイコン
16 CS SPI スレーブセレクト

今回データ入力は使わなかったので、上の写真では省略しています。

これで3線で液晶を制御できるようになるので、マイコンの選択の幅がかなり広がりますね。

コーディング

こちらのディスプレイをSPIモードで動作させる場合、先頭にRSとR/Wの信号をつけた、計10bitで制御するようです。手間的にはパラレルインターフェイスでも最初に同信号線を制御する必要がありますのであまり変わりませんが、今のところ標準のSPI命令が使えてないのでオリジナルで作る必要があるようです。(何かやりようがあるのかもしれませんが。)

まぁSPIは制御も単純なので、いろいろと試行錯誤をするよりはいっそオリジナル命令を作ってしまった方が良いのではないかと思います。というわけでオリジナル関数で制御できたのでそれ以上はやってません。

int spiSend(unsigned int rs,unsigned char data,int cs,int clk,int sdo){
  int i=10;
  rs = int(rs <<  9) | int(data);

 digitalWrite(cs,0);
  while(i--){
    digitalWrite(sdo,(rs >> i) & 1);
    digitalWrite(clk,0);digitalWrite(clk,1);
     }
  digitalWrite(cs,1);
  }

特に難しい事はしていません。今まで散々使ってきたビットシフトとIO制御でSPI信号を出力しています。

これを使って仕様書(共立のサイトからダウンロードできるページがたくさんある方。)に書いてある初期化信号(8bitのほう)を送る事でディスプレイを動かせます。

なお、同じく仕様書に書いてあるのですが、不安定や動作不良になった場合は、ディスプレイに「0」の信号を4回送ってリセットすると正常動作するようなので、最初の初期化の前にこの制御も含めるとよいと思います。

動作確認

無事有機ELキャラクターディスプレイをSPIで制御して当サイトのサイト名を表示する事ができました。見ての通り電源線を含めてたった5本のケーブルのみで制御が可能になっています。

なお、コマンド等については以下に上記表示を行った全コードを掲載しますのでそれを見て判断してください。基本的には共立で買ったときに点いてくる紙の通りに動かせば動きます。

#include <SPI.h>
int spiSend(unsigned int rs,unsigned char data,int cs,int clk,int sdo);

void setup() {
  // put your setup code here, to run once
Serial.begin(9600);  // 9600bpsでポートを開く
pinMode(10,OUTPUT);pinMode(11,OUTPUT);pinMode(13,OUTPUT);
 digitalWrite(10,1);digitalWrite(13,1);
delay(100);
spiSend(0,0,10,13,11);spiSend(0,0,10,13,11);spiSend(0,0,10,13,11);spiSend(0,0,10,13,11);spiSend(0,0,10,13,11);
delay(10);
spiSend(0,0b00111000,10,13,11);
delay(10);
spiSend(0,0b00001100,10,13,11);
delay(10);
spiSend(0,0b00000001,10,13,11);
delay(10);
spiSend(0,0b00000010,10,13,11);
delay(10);
spiSend(0,0b00000110,10,13,11);

delay(200);

spiSend(1,'S',10,13,11);
spiSend(1,'a',10,13,11);
spiSend(1,'k',10,13,11);
spiSend(1,'u',10,13,11);
spiSend(1,'r',10,13,11);
spiSend(1,'a',10,13,11);
spiSend(1,'8',10,13,11);
spiSend(1,'7',10,13,11);
spiSend(1,'.',10,13,11);
spiSend(1,'n',10,13,11);
spiSend(1,'e',10,13,11);
spiSend(1,'t',10,13,11);
spiSend(1,0xD5,10,13,11);spiSend(1,0xB3,10,13,11);spiSend(1,0xB7,10,13,11);


}

void loop() {
  // put your main code here, to run repeatedly:
}

int spiSend(unsigned int rs,unsigned char data,int cs,int clk,int sdo){
  int i=10;
  rs = int(rs <<  9) | int(data);

 digitalWrite(cs,0);
  while(i--){
    digitalWrite(sdo,(rs >> i) & 1);
    digitalWrite(clk,0);digitalWrite(clk,1);
     }
  digitalWrite(cs,1);
  }

元々違うプログラムを作っていたものの名残や、試行錯誤の残骸などがありますので適当に不要な箇所を省いてください。

ちなみに初期化のdelayはなくても動きます。

それでは簡単ですが以上となります。何かご質問等あればコメント欄によろしくお願いします。

ちなみにアンプの方は今年度中には完成しそうです。

総閲覧数:353 PV

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

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