GPIO 増設した ESP-WROOM-02 ( ESP8266 )で、8bitモードのグラフィックディスプレイ を制御してみた

記事公開日:2016年10月24日
最終修正日:2018年9月6日

こんばんは。

前回の記事では、ESPr Developer ( ESP-WROOM-02, ESP8266 ) のGPIOを増設して、キャラクタディスプレイを8bitモードで制御してみました。

今回は、そのディスプレイを100×16ドットのグラフィックモードにして、同じく8bitモードで制御してみようと思います。

この有機EL ( OLED )グラフィックディスプレイ

ストロベリーリナックス ( Strawberry Linux )
グラフィック有機ELモジュール100x16

は、数ある電子工作用途の有機ELグラフィックディスプレイの中で、最もドットが大きいものです。
ある程度遠くからでも文字を視認できる電光掲示板を作るには、LEDマトリックスよりも簡単に実現できるものです。
今となっては極小ドットのディスプレイは沢山ありますが、大きいドット(ピクセル)というものはなかなか見当たりません。
他のメーカーさんもどんどんこういうタイプのディスプレイは取り扱っていただきたいと個人的には思いますね。

では、これのグラフィックモードの使い方について説明します。

スポンサーリンク

1.使うもの

8ビット SPI I/Oエキスパンダ MCP23S08-E/P
Character_spi_01
秋月電子通商さんで販売しています。
Microchip製です。
これは5V駆動ですのでご注意ください
SPI通信の最大速度は10MHz です。
ESPr Developer ( ESP-WROOM-02, ESP8266 )ではGPIOピンが少ないので、これを使って増設します。
これで8bitモードパラレルのディスプレイが制御できます。

グラフィック有機ELモジュール100x16
Character_spi_08
ストロベリーリナックス ( Strawberry Linux )さんで販売しています。
コントローラーは WS0010 を使ってます。
キャラクタモードとグラフィックモードを切り替えできます。

ESPr Developer ( ESP-WROOM-02 開発ボード )
スイッチサイエンス製
Amazon.co.jp

これについては何度も当ブログで紹介しておりますが、日本の電波法をクリアした技適認証済み Wi-Fi モジュールです。ESP-WROOM-02 が安定して動作して、とても使いやすいです。
Arduino IDE で開発ができて、とてもお勧めです。
これの使い方については以下のページを参照してください。
https://www.mgo-tec.com/blog-entry-ss-wroom-howto01.html

0.1uF セラミックコンデンサー
I/Oエクスパンダの MCP23S08 チップの電源誤作動を防ぐためのパスコンです。
積層セラミックでも良いです。

サンハヤト製ニューブレッドボード 【SAD-101】
このブレッドボードがお勧めです。

2.組み立て、接続、設定等

前回の記事の2~4まで予め設定を済ませておいてください。

3.Arduino IDEのスケッチ入力

では、以下のスケッチを入力してみてください。

/* ESPr Developer or ESP-WROOM-02 or ESP8266
 * GPIO Expander = MCP23S08 ( Microchip )
 * OLED = WS0010 ( Strawberry Linux )
 */
#include <SPI.h>

//GPIOエクスパンダ MCP23S08 のSPIインターフェースピン設定
const uint8_t sclk = 14; //SPIクロック出力ピン
const uint8_t mosi =13; //Master Output Slave Input ESP8266=Master,MCP23S08=slave 
const uint8_t MCP_CS = 0; //MCP23S08 CSピン(Chip Select)
const uint8_t MCP_RST_pin =  4; //MCP23S08 リセットピン
//OLED ピン設定 (8bitモード用)
const uint8_t OLED_RS_pin = 2; //設定コマンド or データコマンドのモード選択ピン
const uint8_t OLED_RW_pin =  5; //書込み or 読み取りモード選択ぴん
const uint8_t OLED_E_pin = 16; //データ確定のEnterピン

int i;

void setup() {
  delay(1000); //電源起動後、動作が安定するまで1秒待つ

  MCP23S08_Ini(); //GPIOエクスパンダ初期化  
  OLED_Graphic_Ini(); //OLED初期化
  
  OLED_XYset(0, 0);
  OLED_DataWrite(B11111111);
  OLED_XYset(0, 1);
  OLED_DataWrite(B01010101);

  OLED_XYset(32, 0);
  for(i=0; i<8; i++){
    OLED_DataWrite(B00000001<<i); //ビットを左へiずつ移動
  }
  OLED_XYset(32, 1);
  for(i=0; i<8; i++){
    OLED_DataWrite(B10000000>>i); //ビットを右へiずつ移動
  }
}

void loop() {
  byte Xplot = 48;
  
  for(i=0; i<8; i++){
    OLED_XYset(Xplot + i, 0);
    OLED_DataWrite(B00000001<<i); //ビットを左へiずつ移動
    if(i>=0){
      OLED_XYset(Xplot + (i-1), 0);
      OLED_DataWrite(0); //ドットを消す
    }
    delay(50);
  }
  OLED_XYset(Xplot+7, 0);
  OLED_DataWrite(0); //ドットを消す
  for(i=0; i<8; i++){
    OLED_XYset(Xplot+8+i, 1);
    OLED_DataWrite(B00000001<<i); //ビットを左へiずつ移動
    if(i>=0){
      OLED_XYset(Xplot+8+(i-1), 1);
      OLED_DataWrite(0); //ドットを消す
    }
    delay(50);
  }
  OLED_XYset(Xplot+8+7, 1);
  OLED_DataWrite(0); //ドットを消す
}

void MCP23S08_Ini(){ //GPIOエクスパンダ MCP23S08初期化
  pinMode(MCP_CS, OUTPUT);
  pinMode(MCP_RST_pin, OUTPUT);
  
  SPI.begin();
  SPI.setFrequency(10000000); //MCP23S08 Max 10MHz
  SPI.setDataMode(SPI_MODE0);

  digitalWrite(MCP_RST_pin, HIGH);
  delay(100);
  digitalWrite(MCP_RST_pin, LOW);
  delay(100);
  digitalWrite(MCP_RST_pin, HIGH);
  delay(100);
  
  digitalWrite(MCP_CS, LOW);
    delay(1);
    SPI.write(B01000000); //デバイスオペコードB01000000 & チップaddress 000
    SPI.write(0x05); //MCP設定レジスタIOCON 
    SPI.write(B00100000); //シーケンシャル動作禁止、SDAスルーレート許可、ハードウェアアドレスピン禁止、INT出力LOW、アクティブドライブ
    delay(1);
  digitalWrite(MCP_CS, HIGH);
  
  digitalWrite(MCP_CS, LOW);
    delay(1);
    SPI.write(B01000000); //デバイスオペコードB01000000 & チップaddress 000
    SPI.write(0x00); // I/O方向レジスタ(IODIR)設定
    SPI.write(B00000000); //8pin ALL OUTPUT
    delay(1);
  digitalWrite(MCP_CS, HIGH);
}

void OLED_Graphic_Ini(){ //OLED WS0010 初期化
  pinMode(OLED_RW_pin, OUTPUT);
  pinMode(OLED_RS_pin, OUTPUT);
  pinMode(OLED_E_pin, OUTPUT);
  
  digitalWrite(OLED_E_pin, LOW);
  digitalWrite(OLED_RW_pin, LOW);
  digitalWrite(OLED_RS_pin, LOW);

  //OLEDリセット
  delayMicroseconds(10);
  OLED_CommandWrite(B00000001);//Display Clear
  delay(10);
  OLED_CommandWrite(B00010011);//Character MODE ON, Power is turned OFF
  delay(10); //リセットは一旦電源を切るべし
  OLED_CommandWrite(B00001000);//Display OFF, Cursor OFF, Brinking OFF 
  delay(1000);
  //ここからディスプレイ初期化設定
  OLED_CommandWrite(B00011111);//Graphics MODE ON, Power is turned ON
  delay(10);
  OLED_CommandWrite(B00111000);//Function Set 8bit-mode 2Line-display
  delay(10);
  OLED_CommandWrite(B00001111);//Display On, Cursor ON, Brinking on 
  delay(10);
  OLED_CommandWrite(B00000001);//Display Clear
  delay(10);
  OLED_CommandWrite(B00000010);//Return HOME
  delay(10);
  OLED_CommandWrite(B00000110);//Entry Mode Set, Increment, No-Shift
  delay(10);
}

void OLED_XYset(uint8_t x, uint8_t y){
   OLED_CommandWrite(0x80 + x);  
   OLED_CommandWrite(0x40 + y);
}

void OLED_CommandWrite(uint8_t b){
  digitalWrite(OLED_RS_pin, LOW);
  MCP23S08_SpiCommandWrite(b);
  digitalWrite(OLED_E_pin, HIGH);//EピンをHIGH→LOWへ変化させると書き込み完了
  digitalWrite(OLED_E_pin, LOW);
}

void OLED_DataWrite(uint8_t b){
  digitalWrite(OLED_RS_pin, HIGH);
  MCP23S08_SpiCommandWrite(b);
  digitalWrite(OLED_E_pin, HIGH);//EピンをHIGH→LOWへ変化させると書き込み完了
  digitalWrite(OLED_E_pin, LOW);
}

void MCP23S08_SpiCommandWrite(uint8_t b){
  digitalWrite(MCP_CS, LOW);
    SPI.write(B01000000);
    SPI.write(0x0A);
    SPI.write(b);
  digitalWrite(MCP_CS, HIGH);
}

【解説】
前回の記事同様、WS0010のデータシートも合わせて参照してみてください。

●5行目:
ESP8266 core for Arduino のSPI標準ライブラリのインクルードです。

●8-11行:
GPIO エキスパンダ用のESPr Developer ( ESP-WROOM-02, ESP8266 )側のピン設定です。

●13-15行:
有機EL ( OLED )用のESPr Developer ( ESP-WROOM-02, ESP8266 )側のピン設定です。

●22行:
GPIO エキスパンダ MCP23S08 の初期化をします。
67-97行で関数化してます。
これの説明は前回の記事を参照してください。

●23行:
OLED (有機EL) ディスプレイをグラフィックモードにする初期化です。
99-129行で関数化してます。
前回の記事のキャラクタモードの初期化との違いは、117行目の第3ビットが1になっていることです。

0ビット目 = 1
1ビット目 = 1
2ビット目 = 電源ON
3ビット目 = グラフィックモードON

キャラクタモードの場合 = 00010111
グラフィックモード = 00011111

●25-28行:
25行で、OLED のドットを表示させる位置を決めます。
まず、原点を(0, 0) とします。
これは131-134行で関数化してます。
このディスプレイの座標は下図の様になってます。

Graphics_spi_01

なんか、ビットの並びが縦方向になっているディスプレイが多いですね。
日本語を扱うことが多い私にとっては、水平方向並びの方が扱いやすいのですが・・・。

26行目で、表示させる8ビットデータを送信してます。
143-148行でデータ送信を関数化してます。
この、コマンド送信関数とデータ送信関数の詳細は前回の記事を参照してください。
OLEDに設定コマンドとして0x80 に水平座標のx位置(0~100) を加算すれば、ビットを縦方向でズラッと表示してくれます。0が消灯で、1が点灯です。

●30-37行:
ここでは、連続してデータを送信した場合にどの様に表示されるかをテストしてます。
まず、30行目で表示開始位置を指定して、31-33行で表示ドットを毎回1ビットずつずらしていきます。
34行目でY座標を1にして(2行目に表示)、同じようにビットをずらしていきます。

●40-65行:
ここでは、ドットが時間とともに移動していく簡易アニメーション的なプログラムです。
delay(50)で50ms毎にずらしたビットを表示させてます。
ただ、ビットを移動させたら、直前に表示させたビットを消さないとアニメーションになりません。
このようにY座標をまたいでドットを移動させるにはちょっと面倒な工夫が必要になります。

4.コンパイル実行

では、Arduino IDEのスケッチをコンパイル実行させてみてください。
このように表示されればOKです。

いかがでしたでしょうか?
ここまでできれば、日本漢字フォントを表示させることも可能になります。
次回はいよいよ16×16ドットの漢字フォントを表示させてみたいと思います。

ではまた・・・。

スポンサーリンク

mgo-tec電子工作 関連コンテンツ ( 広告含む )
Amazon.co.jp 当ブログのおすすめ

投稿者:

mgo-tec

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

コメントを残す

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

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

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