フルカラー有機EL ( OLED ) に倍角日本語フォントを縦横でスクロールさせてみた ( ESP32 , SSD1331 使用)

ESP32 ( ESP-WROOM-32 )

スケッチの入力

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

縦方向スクロールの場合、全角のみ対応です。
どうしても半角を表示させたい場合、半角1文字の場合は半角スペースを挿入して半角2文字にするなどしてみてください。

【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#include "ESP32_SSD1331.h" //Beta ver 1.6
#include "ESP32_SPIFFS_ShinonomeFNT.h" //Beta ver 1.2
#include "ESP32_SPIFFS_UTF8toSJIS.h" //Beta ver 1.1

const char* UTF8SJIS_file = "/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
const char* Shino_Zen_Font_file = "/shnmk16.bdf"; //全角フォントファイル名を定義
const char* Shino_Half_Font_file = "/shnm8x16.bdf"; //半角フォントファイル名を定義

const uint8_t SCLK_OLED =  14; //SCLK
const uint8_t MOSI_OLED =  13; //MOSI (Master Output Slave Input)
const uint8_t MISO_OLED =  12; //これは実際は使っていない。MISO (Master Input Slave Output)
const uint8_t DC_OLED =  21; //OLED DC(Data/Command)
const uint8_t RST_OLED =  4; //OLED Reset
const uint8_t CS1_OLED = 15; //CS (Chip Select ピン)

ESP32_SSD1331 ssd1331(SCLK_OLED, MISO_OLED, MOSI_OLED, CS1_OLED, DC_OLED, RST_OLED);
ESP32_SPIFFS_ShinonomeFNT SFR;

//※文字列の最大数は6
enum { Display_Max_num = 6, MaxTxtByte = 100 ,cash = 2};

uint8_t sj_txt[Display_Max_num][MaxTxtByte] = {0}; //Shift_JISコード格納
uint16_t sj_length[Display_Max_num] = {0}; //Shift_JISコードの長さ
uint16_t sj_cnt[Display_Max_num] = {0}; //Shift_JISコード半角文字数カウント
uint8_t disp_buf[Display_Max_num][16][16] = {0}; //ディスプレイに表示させるフォントバッファ
boolean fnt_read_ok[Display_Max_num] = {true, true, true, true};
boolean FontReakOK[Display_Max_num] = {false, false, false, false};
uint8_t Zen_or_Han[cash][Display_Max_num] = {0}; //全角半角判断数値

//疑似キャッシュフォント定義-------------------------------------
uint8_t cash_font_cnt[Display_Max_num] = {0}; //キャッシュフォント数カウント
uint8_t cash_font_read_cnt[Display_Max_num] = {0}; //キャッスフォント読み込みカウント
uint8_t CashFont[cash][Display_Max_num][2][16] = {0}; //キャッシュに格納するフォント
//-------------------------------------------------------------

uint32_t SclTime1 = 0;
uint8_t H_Size, V_Size; //水平サイズ:H_Size(1,2,4)  垂直サイズ:V_Size(1,2,4)
uint8_t X0, X1, Y0, Y1; //ディスプレイ表示座標位置
uint8_t red, green, blue; //256color, Max red=7, green=7, blue=3

void setup() {
  Serial.begin(115200);
  ssd1331.SSD1331_Init();
  ssd1331.Display_Clear(0, 0, 95, 63);
  //3つのSPIFFSファイルを同時オープン
  SFR.SPIFFS_Shinonome_Init3F(UTF8SJIS_file, Shino_Half_Font_file, Shino_Zen_Font_file); //ライブラリ初期化。2ファイル同時に開く
  Serial.println();

  String test_str[4];
  uint8_t test_buf[4][16][16] = {0};
  uint16_t test_sj_length[4];

  //16x16 東雲フォント 等倍表示
  test_str[0] = "2018年";
  X0 = 24; Y0 = 24; red = 7; green = 7; blue = 3;
  test_sj_length[0] = SFR.StrDirect_ShinoFNT_readALL(test_str[0], test_buf[0]);
  ssd1331.SSD1331_8x16_Font_DisplayOut(test_sj_length[0], X0, Y0, red, green, blue, test_buf[0]);
  delay(1500);
  ssd1331.Display_Clear(0, 0, 95, 63);

  //16x16 東雲フォント 縦長2倍角表示
  test_str[1] = "平成30年";
  H_Size = 1; V_Size = 2; X0 = 14; Y0 = 16; red = 7; green = 7; blue = 3;
  test_sj_length[1] = SFR.StrDirect_ShinoFNT_readALL(test_str[1], test_buf[1]);
  ssd1331.HVsizeUp_8x16_Font_DisplayOut(H_Size, V_Size, test_sj_length[1], X0, Y0, red, green, blue, test_buf[1]);
  delay(1500);
  ssd1331.Display_Clear(0, 0, 95, 63);

  //16x16 東雲フォント 縦長4倍角表示
  test_str[2] = "あけまして!";
  H_Size = 1; V_Size = 4; X0 = 0; Y0 = 0; red = 0; green = 7; blue = 0;
  test_sj_length[2] = SFR.StrDirect_ShinoFNT_readALL(test_str[2], test_buf[2]);
  ssd1331.HVsizeUp_8x16_Font_DisplayOut(H_Size, V_Size, test_sj_length[2], X0, Y0, red, green, blue, test_buf[2]);

  delay(1500);
  ssd1331.Display_Clear(0, 0, 95, 63);

  test_str[3] = "おめでとう!";
  H_Size = 1; V_Size = 4; X0 = 0; Y0 = 0; red = 7; green = 0; blue = 0;
  test_sj_length[3] = SFR.StrDirect_ShinoFNT_readALL(test_str[3], test_buf[3]);
  ssd1331.HVsizeUp_8x16_Font_DisplayOut(H_Size, V_Size, test_sj_length[3], X0, Y0, red, green, blue, test_buf[3]);

  delay(2000);
  ssd1331.Display_Clear(0, 0, 95, 63);

  //キャッシュバイトを使う場合、文字の最後に全角スペース適当に入れておけば、文字スクロール終了を検出する時に全てをスクロールし切ることができる
  //4倍角ならスペース5つ入力
  sj_length[0] = SFR.UTF8toSJIS_convert("★★★★★★A Happy New Year!  ", sj_txt[0]);
  sj_length[1] = SFR.UTF8toSJIS_convert("★謹賀新年", sj_txt[1]);
  sj_length[2] = SFR.UTF8toSJIS_convert("★★★★★★平成30年", sj_txt[2]);
  sj_length[3] = SFR.UTF8toSJIS_convert("★★★★★★2018年", sj_txt[3]);
  sj_length[4] = SFR.UTF8toSJIS_convert("★★★★★★皆さまにとって良い年でありますように!", sj_txt[4]);
  sj_length[5] = SFR.UTF8toSJIS_convert("スクロールがぎこちないですが、ご容赦ください!     ", sj_txt[5]);

  //マルチタスクでスムースにスクロールするための、キャッシュバイト2バイト事前読み込み
  for(int j=0; j<cash; j++){
    for(int str_number=0; str_number<Display_Max_num; str_number++){
      //Zen_or_Han[j][str_number] = SFR.Sjis_inc_FntRead_Rot(&sj_cnt[str_number], -90, 0, str_number, sj_txt[str_number], sj_length[str_number], CashFont[j][str_number]);
      Zen_or_Han[j][str_number] = SFR.Sjis_inc_FntRead(&sj_cnt[str_number], str_number, sj_txt[str_number], sj_length[str_number], CashFont[j][str_number]);
    }
  }

  TaskHandle_t th; //ESP32 マルチタスク ハンドル定義
  xTaskCreatePinnedToCore(Task1, "Task1", 4096, NULL, 5, &th, 0); //マルチタスク core 0 実行

  SclTime1 = millis();
}
//************** メインループ *******************
void loop() {
  int str_number;
  //1文字スクロールしたらフォントを読み込む
  for(str_number=0; str_number<Display_Max_num; str_number++){
    if(FontReakOK[str_number] == true) {
      Zen_or_Han[ cash_font_read_cnt[str_number] ][str_number] = SFR.Sjis_inc_FntRead(&sj_cnt[str_number], str_number, sj_txt[str_number], sj_length[str_number], CashFont[ cash_font_read_cnt[str_number] ][str_number]);
      cash_font_read_cnt[str_number]++;
      if(cash_font_read_cnt[str_number] >= cash) cash_font_read_cnt[str_number] = 0;
      FontReakOK[str_number] = false;
    }
  }
}
//************* マルチタスク **********************
void Task1(void *pvParameters){
  int str_number;
  while(1){
    if(millis() - SclTime1 > 10){ //スクロールインターバル 10ms
      if( sj_cnt[5] < (sj_length[5] - 2) ){ //スクロール終了検出はsj_lengthから全角2バイト分引く
        str_number=5;
        H_Size = 4; Y0 = 0; red = 7; green = 7; blue = 3;
        if(ssd1331.SizeUp_Scroller_8x16_RtoL(H_Size, Y0, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }
      }else{
        str_number=0;
        H_Size = 1; V_Size = 1; X0 = 0; X1 = 95; Y0 = 0; red = 7; green = 2; blue = 3;
        if(ssd1331.HVsizeUp_Scroller_8x16_RtoL(H_Size, V_Size, X0, X1, Y0, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }

        str_number=1;
        H_Size = 2; V_Size = 2; X0 = 16; X1 = 79; Y0 = 16; red = 7; green = 7; blue = 0;
        if(ssd1331.HVsizeUp_Scroller_8x16_RtoL(H_Size, V_Size, X0, X1, Y0, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }

        str_number=2;
        uint8_t Direction = 0; //縦方向スクロール 0:↑ 1:↓
        H_Size = 1; V_Size = 3; X0 = 0; Y0 = 16; Y1 = 63; red = 7; green = 0; blue = 0;
        if(ssd1331.HVsizeUp_Vscroller_16x16(H_Size, V_Size, Direction, X0, Y0, Y1, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }

        str_number=3;
        Direction = 1; //縦方向スクロール 0:↑ 1:↓
        H_Size = 1; V_Size = 3; X0 = 80; Y0 = 16; Y1 = 63; red = 0; green = 7; blue = 0;
        if(ssd1331.HVsizeUp_Vscroller_16x16(H_Size, V_Size, Direction, X0, Y0, Y1, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }

        str_number=4;
        H_Size = 1; V_Size = 1; X0 = 16; X1 = 79; Y0 = 48; red = 0; green = 7; blue = 3;
        if(ssd1331.HVsizeUp_Scroller_8x16_RtoL(H_Size, V_Size, X0, X1, Y0, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }
      }
      SclTime1 = millis();
    }
    delay(1);//マルチタスクのwhileループでは必ず必要
  }
}

【解説】

●1-3行目:
私の自作ライブラリのインストールです。
3行目の ESP32_SPIFFS_UTF8toSJIS はESP32_SPIFFS_ShinonomeFNTライブラリ内でインクルードされていますが、ここではライブラリのインストールを忘れない為に明示的にインクルードさせています。

●5-7行目:
SPIFFSファイルシステムでアップロードさせたフォントファイルとUTF8toSJIS変換テーブルファイルを定義しています。

●9-14行:
OLED SSD1331 と SPIインターフェースで接続する GPIOピン番号の定義です。

●16-17行:
自作ライブラリのクラス名定義です。

●20行:
ディスプレイに表示させる文字列は最大6列です。
それ以上にするとエラーになります。
MaxTxtByte はメモリの許す限り大きくできます。
cash 数は大きくしても意味ありません。

●31-33行:
疑似的にキャッシュっぽいことをやるための配列定義です。
各文字列毎に全角1文字分(半角2文字分)をSRAMの配列に格納しておき、半角1文字スクロールしている間に次の1文字をSPIFFSから読み込むためのものです。

●39行:
OLED SSD1331 では、今回は256色カラーにしています。
赤色は0~7、緑色は0~7、青色は0~3で設定します。
RGBを混ぜて色を作ります。

●46行:
ここで、SPIFFSファイルシステムで、3つのファイルを同時に開いておきます。

●54-84行:
ここでは、テスト用として、固定文字列を表示させています。
文字サイズの数値は、水平方向、垂直方向とも 0 , 2 , 4 のうちのいずれかを代入します。
横方向 0~96 pixel
縦方向 0~63 pixel
なので、サイズを大きくした場合に、その数値からはみ出ないように文字数やサイズを設定してください。
これを超えると、恐らくまともに動きません。

●88-93行:
ここで、String型UTF-8文字列を Shift_JISコードに変換します。
最大6列まで定義できます。
最後の文字列は、スクロール終了を検知の時に文字列を全部スクロールし切るために、文字列の最後の方に4倍角用のスペース5つを入力しています。

●96-101行:
ここで、各文字列の全角1文字を予めキャッシュ配列に読み込んでおきます。

●103-104行:
ESP32 のデュアルコアCPUを使うマルチタスク関数です。
メインループが Core 1 で、122行目以降のタスクが Core 0 です。
ESP32 のマルチタスクについては以下の記事を参照してください。

Arduino – ESP32 のマルチタスク ( Dual Core ) を試す

●112-119行:
CPU Core 1 のメインループです。
半角1文字スクロールしている間にフォントを読み込んでいます。
114行目の関数で、フォントを読み込んだ後、文字カウントを自動的に1増加させます。

●122-181行:
CPU Core 0 のマルチタスクループです。
125行目でスクロールスピードを設定していて、10ms インターバルを置いています。
この数値を少なくするほどスクロールは速くなりますが、SPIFFS のフォント読み込みが間に合わなくなりますので、あまり速くしない方が良いでしょう。

●126-133行:
フォントを縦横4倍角にして、文字をスクロールさせ、スクロールが全て完了し切ったら次の処理に移ります。
キャッシュフォントを設定しているため、126行では半角2文字分を引いて設定しないと、文字スクロール終了を検知しないので注意です。
先にも述べたように、すべての文字をスクロールし切ることを検知するためには、文字列の最後に全角スペースを5つ入力しておくことが必要です。(4倍角の場合)

●135-141行:
等倍フォントの水平スクロールです。

●143-149行:
縦横2倍角の水平スクロールです。

●151-158行:
横方向1倍、縦方向3倍角文字の垂直スクロールです。
Direction を0 にすると下から上へスクロールします。
垂直スクロールの場合、必ず全角文字にしてください。

●169-175行:
等倍文字の水平スクロールですが、表示させる範囲を狭くしています。

横長、縦長サイズアップフォントの縦横スクロール

2018/1/4 に自作ライブラリ、ESP32_SSD1331 を beta ver 1.7 にアップデートして、横長文字の縦スクロールができるようになりました。
そして、白黒反転文字スクロールもできるようになりました。
そのサンプルスケッチは以下の通りです。
縦方向スクロールの場合、全角のみ対応です。
どうしても半角を表示させたい場合、半角1文字の場合は半角スペースを挿入して半角2文字にするなどしてみてください。

【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#include "ESP32_SSD1331.h" //Beta ver 1.7
#include "ESP32_SPIFFS_ShinonomeFNT.h" //Beta ver 1.2
#include "ESP32_SPIFFS_UTF8toSJIS.h" //Beta ver 1.1

const char* UTF8SJIS_file = "/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
const char* Shino_Zen_Font_file = "/shnmk16.bdf"; //全角フォントファイル名を定義
const char* Shino_Half_Font_file = "/shnm8x16.bdf"; //半角フォントファイル名を定義

const uint8_t SCLK_OLED =  14; //SCLK
const uint8_t MOSI_OLED =  13; //MOSI (Master Output Slave Input)
const uint8_t MISO_OLED =  12; //これは実際は使っていない。MISO (Master Input Slave Output)
const uint8_t DC_OLED =  21; //OLED DC(Data/Command)
const uint8_t RST_OLED =  4; //OLED Reset
const uint8_t CS1_OLED = 15; //CS (Chip Select ピン)

ESP32_SSD1331 ssd1331(SCLK_OLED, MISO_OLED, MOSI_OLED, CS1_OLED, DC_OLED, RST_OLED);
ESP32_SPIFFS_ShinonomeFNT SFR;

//※文字列の最大数は6
enum { Display_Max_num = 4, MaxTxtByte = 100 ,cash = 2};

uint8_t sj_txt[Display_Max_num][MaxTxtByte] = {0}; //Shift_JISコード格納
uint16_t sj_length[Display_Max_num] = {0}; //Shift_JISコードの長さ
uint16_t sj_cnt[Display_Max_num] = {0}; //Shift_JISコード半角文字数カウント
uint8_t disp_buf[Display_Max_num][16][16] = {0}; //ディスプレイに表示させるフォントバッファ
boolean fnt_read_ok[Display_Max_num] = {true, true, true, true};
boolean FontReakOK[Display_Max_num] = {false, false, false, false};
uint8_t Zen_or_Han[cash][Display_Max_num] = {0}; //全角半角判断数値

//疑似キャッシュフォント定義-------------------------------------------------
uint8_t cash_font_cnt[Display_Max_num] = {0}; //キャッシュフォント数カウント
uint8_t cash_font_read_cnt[Display_Max_num] = {0}; //キャッスフォント読み込みカウント
uint8_t CashFont[cash][Display_Max_num][2][16] = {0}; //キャッシュに格納するフォント
//-------------------------------------------------------------

uint32_t SclTime1 = 0;

void setup() {
  Serial.begin(115200);
  ssd1331.SSD1331_Init();
  ssd1331.Display_Clear(0, 0, 95, 63);
  //3つのSPIFFSファイルを同時オープン
  SFR.SPIFFS_Shinonome_Init3F(UTF8SJIS_file, Shino_Half_Font_file, Shino_Zen_Font_file); //ライブラリ初期化。2ファイル同時に開く
  Serial.println();

  //キャッシュバイトを使う場合、文字の最後に全角スペース適当に入れておけば、文字スクロール終了を検出する時に全てをスクロールし切ることができる
  //4倍角ならスペース5つ入力
  sj_length[0] = SFR.UTF8toSJIS_convert("こんなのもできますよ~ん 縦長4倍角    ", sj_txt[0]);
  sj_length[1] = SFR.UTF8toSJIS_convert("すかさず横長6倍角ですよ★    ", sj_txt[1]);
  sj_length[2] = SFR.UTF8toSJIS_convert("こんなのもできますよ~ん!白黒反転    ", sj_txt[2]);
  sj_length[3] = SFR.UTF8toSJIS_convert("そしてすかさず横長6倍角 白黒反転★       ", sj_txt[3]);

  //マルチタスクでスムースにスクロールするための、キャッシュバイト2バイト事前読み込み
  for(int j=0; j<cash; j++){
    for(int str_number=0; str_number<Display_Max_num; str_number++){
      //Zen_or_Han[j][str_number] = SFR.Sjis_inc_FntRead_Rot(&sj_cnt[str_number], -90, 0, str_number, sj_txt[str_number], sj_length[str_number], CashFont[j][str_number]);
      Zen_or_Han[j][str_number] = SFR.Sjis_inc_FntRead(&sj_cnt[str_number], str_number, sj_txt[str_number], sj_length[str_number], CashFont[j][str_number]);
    }
  }

  TaskHandle_t th; //ESP32 マルチタスク ハンドル定義
  xTaskCreatePinnedToCore(Task1, "Task1", 4096, NULL, 5, &th, 0); //マルチタスク core 0 実行

  SclTime1 = millis();
}
//************** メインループ *******************
void loop() {
  int str_number;
  //1文字スクロールしたらフォントを読み込む
  for(str_number=0; str_number<Display_Max_num; str_number++){
    if(FontReakOK[str_number] == true) {
      Zen_or_Han[ cash_font_read_cnt[str_number] ][str_number] = SFR.Sjis_inc_FntRead(&sj_cnt[str_number], str_number, sj_txt[str_number], sj_length[str_number], CashFont[ cash_font_read_cnt[str_number] ][str_number]);
      cash_font_read_cnt[str_number]++;
      if(cash_font_read_cnt[str_number] >= cash) cash_font_read_cnt[str_number] = 0;
      FontReakOK[str_number] = false;
    }
  }
}
//************* マルチタスク ****************************************
void Task1(void *pvParameters){
  uint8_t H_Size, V_Size; //水平サイズ:H_Size(1,2,4)  垂直サイズ:V_Size(1,2,4)
  uint8_t X0 = 0, X1 = 95, Y0 = 0, Y1 = 63; //ディスプレイ表示座標位置
  uint8_t red, green, blue; //256color, Max red=7, green=7, blue=3
  int str_number;
  int Direction;

  while(1){
    if(millis() - SclTime1 > 7){ //スクロールインターバル 7ms
      if( sj_cnt[0] < (sj_length[0] - 2) ){ //スクロール終了検出はsj_lengthから全角2バイト分引く
        str_number=0;
        H_Size = 1; V_Size = 4; red = 7; green = 7; blue = 3;
        if(ssd1331.HVsizeUp_Scroller_8x16_RtoL(false, H_Size, V_Size, X0, X1, Y0, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }
      }else if( sj_cnt[1] < (sj_length[1] - 2) ){
        str_number=1;
        H_Size = 6; V_Size = 1; Direction = 0; red = 7; green = 0; blue = 0;
        if(ssd1331.HVsizeUp_Vscroller_16x16(false, H_Size, V_Size, Direction, X0, Y0, Y1, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }
      }else if( sj_cnt[2] < (sj_length[2] - 2) ){
        str_number=2;
        H_Size = 2; V_Size = 4; red = 0; green = 7; blue = 0;
        if(ssd1331.HVsizeUp_Scroller_8x16_RtoL(true, H_Size, V_Size, X0, X1, Y0, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }
      }else if( sj_cnt[3] < (sj_length[3] - 2) ){
        str_number=3;
        H_Size = 6; V_Size = 2; Direction = 1; red = 7; green = 0; blue = 0;
        if(ssd1331.HVsizeUp_Vscroller_16x16(true, H_Size, V_Size, Direction, X0, Y0, Y1, str_number, Zen_or_Han[cash_font_cnt[str_number]][str_number], CashFont[cash_font_cnt[str_number]][str_number], red, green, blue)){
          cash_font_cnt[str_number]++;
          if(cash_font_cnt[str_number] >= cash) cash_font_cnt[str_number] = 0;
          FontReakOK[str_number] = true;
        }
      }else{
        sj_cnt[0] = 0;
        sj_cnt[1] = 0;
        sj_cnt[2] = 0;
        sj_cnt[3] = 0;
      }

      SclTime1 = millis();
    }
    delay(1);//マルチタスクのwhileループでは必ず必要
  }
}

これの解説は省略させていただきます。

コンパイル書き込み実行

では、Arduino IDE でコンパイル書き込み実行してみてください。
最初に紹介した動画のように表示されればOKです。

まとめ

いかがでしたでしょうか。
うまく動きましたでしょうか?

これをうまく使えばフリーマーケットやコミケ、そのほか卓上展示会などで値札や製品アピールにつかえそうですね。

まだキャッシュ機能がうまくいってなくて、スクロールがイマイチなのが次回の課題ですね。
それよりも、microSDカードを使えばスクロールもスムースになるので、それを使えば良いかもしれません。
でも、SPIFFSを使う手軽さはなかなか捨て難いものがありますので、これをなんとかうまく使いたいですね。

以上、今回はここまでです。

本年も私なりにアマチュア精神でいろいろ挑戦したいと思っております。
素人ソースコードですが、素人なりに自由な発想で作っていきたいと思います。
その分、うまく動作しないということもあるかと思います。
その場合、コメント投稿等でご連絡いただければ、できる範囲で改善していきたいと思っております。
ということで、今年の目標として、無駄なことをやることに引け目を感じず、何か有意義なものを創造することができればと思っております。

本年も何卒よろしくお願いいたします。
m(_ _)m

みなさまにとっても良い年でありますように・・・

Amazon.co.jp 当ブログのおすすめ

M5Stack Basic
スイッチサイエンス
¥5,203(2021/09/09 23:54時点)
ESPr Developer 32
スイッチサイエンス(Switch Science)
¥2,200(2021/09/09 23:54時点)
ZEROPLUS ロジックアナライザ LAP-C(16032)
ZEROPLUS
¥15,728(2021/09/09 23:54時点)
Excelでわかるディープラーニング超入門
技術評論社
¥2,068(2021/09/09 23:54時点)

コメント

  1. あいむ より:

    はじめまして!&あけましておめでとうございます。
    おととしくらい(の頃)から、mgo-tecさんのページをいつも参考にさせてもらっています。

    KiCADを使ってオリジナルのESP32のマイコン基板を設計し、注文した回路基板が昨年の大晦日の日に届いたので、ESP32などの部品を付けて、動作確認のためにこのページのプログラムを動かしてみました。すんなりYouTubeの動画の通りに動いたので、ほっとしています。

    ちなみに、カラーOLEDはたぶん同じ仕様のものだと思いますがamazonで1050円で売っていたものを使いました。そのOLEDは現在売れ切れ中で、最初に買ったものは半田不良でちゃんと表示ができないものでしたが、今回は2回目に購入したものでちゃんと表示できてよかったです。

    と言うことで、今年もよろしくお願いいたします。

    • mgo-tec mgo-tec より:

      あいむさん

      ブログをご覧頂き、ありがとうございます。
      ESP32とOLED SSD1331 基板ですか・・。
      それはイイですね!
      SSD1306とのボードはあっても、フルカラー小型OLEDとのボードはまだありませんからね。
      このSSD1331は自由度が高いホントに良いディスプレイですよね。

      もし、WEB公開されているのでしたら、このコメント投稿で、http://のhを外したアドレスを掲載していただければ、拝見させていただきたいです。
      無理にとは申しません。

      ということで、嬉しい投稿ありがとうございました。
      今後とも当ブログをよろしくお願い致します。
      m(_ _)m

  2. あいむ より:

    mgo-tec様

    あいむです。お返事ありがとうございます。

    >拝見させていただきたいです。
    と言うとでしたので、動作した証拠のビデオとったのでYouTubeにあげておきました。
    https://www.youtube.com/watch?v=pJUf4fPeySI
    (もう何年も自分のホームページを更新していないので、久々に更新して、このビデオも載せようと思っています。http://im-aim.com/)

    今回のこのボードは、ESP32の汎用のボードとして作りました。SPIのピンの順番は、このカラーOLEDとSDカードモジュールにして、I2Cは1色のOLED(http://akizukidenshi.com/catalog/g/gP-12031/)のピンの順番にしました。まだやってませんが、SSD1306も動くと思います。

    今後、専用のESP32のプリント基板を作ろうと思っているので、mgo-tecさんがハーフピッチ のESP32の半田付けに挑戦する気があるなら、mgo-tec用の基板もできますよ。今は、海外のプリント基板屋(https://fusionpcb.jp/login.html など)に注文したら1000円もしないでできる時代なったことだし。

    • mgo-tec mgo-tec より:

      あいむさん

      ご無理とお手間をとらせしまって申し訳ございません。
      動画リンクを紹介していただき、誠にありがとうございます。
      会社の方だったのですね。
      アマチュアの私としては恐縮してしまいます。

      自分の作ったプログラムが他の方のボードで動作する動画は、なんか嬉しいですね。
      ちゃんと動いてくれるか心配なところもあったので・・・。

      SSD1306 に乗せ換えられる基板はスバラシイ!!
      あれだけの基板を設計できるのは羨ましいです。
      私は一旦挫折しました。
      設計する時間が無いのと、知識が乏しく、既製品ボード以上のことはとてもできないと悟ったためです。

      それと、私用の基板を作って頂くなんて、とてもとても恐れ多いです。
      そういうお声を頂戴しただけで、感謝感謝です。
      m(_ _)m
      でも、いつか、自分自身で基板設計に挑戦しようと思っておりますので、良い刺激をもらいました。
      いろいろありがとうございます。
      ESP32専用基板ができると面白そうなものになりそうですね。
      期待しております。
      がんばってください。

  3. マッキー(68歳ですw) より:

    あけましておめでとうございます。

    プログラムは全て動作しております。
    JJYの信号発生プログラムにこれを合体させ
    SHT21で温度を表示させるように改造しました。
    しかし全角半角混在では半角がうまく表示できません。
    美咲フォントバージョンを組み込んだ場合はうまく表示できました。
    MFR.StrDirect_MisakiFNT_readALL (“20″ + String(Year) + ” 年” + String(Month) + ” 月” + String(T_day) + ” 日” , font_buf);
    しかし字が小さく、この東雲バージョンで表示したく
    数値だけ変換テーブルでやったのですが、いまいちです。
    厚かましいお願いですがスマートに表示できるようなライブラリーをお願い申し上げます。

    • mgo-tec mgo-tec より:

      マッキーさん

      以前コメント頂いた方とは違う方ですか?
      だとしたら、初めまして。
      そしてあけましておめでとうございます。
      当ブログをご覧いただき、ありがとうございます。

      今、2018/1/9 朝6:00に動かしたところ、ESP32_SSD1331ライブラリをver1.6→1.7 にバージョンアップしたのに、サンプルスケッチが誤動作していました。
      見直していますので
      、しばらくお待ちください。

    • mgo-tec mgo-tec より:

      マッキーさん

      ESP32_SSD1331 の最新ライブラリはbeta ver 1.7 です。
      ブログ記事もそれ用のサンプルスケッチを1月7日に追記しています。

      ver1.7 では、縦方向の倍角文字スクロールが可能になりましたが、ver1.6時の解説でも記載しているとおり、縦方向スクロールは全角文字のみ対応です。
      半角文字混在は横方向スクロールのみです。
      縦方向の半角文字スクロールは、半角が2回連続で来る場合と、1回のみで終わる場合で表示が難しくなり、今は実装していません。
      全て全角に変換するか、または、半角1文字の場合は前に半角スペースを挿入して、半角文字をダブルにしてください。

      因みに、当方で以下のコードで実験してみました。
      (※抜粋です)

      uint8_t Year=18, Month=1, T_day=9;
      sj_length[0] = SFR.UTF8toSJIS_convert("20" + String(Year) + " 年" + String(Month) + " 月" + String(T_day) + " 日" + "     ", sj_txt[0]);
      -----以下省略-----

      こうすると、横方向スクロールは全く問題無く表示されますが、縦方向は対応していないのでうまくできません。
      そこで、半角1文字にスペースを挿入して、強制的に2文字にします。
      例えば、Arduino IDE の sprintf 関数を使います。
      これは、char型しか対応していませんので要注意です。

      uint8_t Year=18, Month=1, T_day=9;
        char Month_c[3], T_day_c[3];
        sprintf(Month_c, "%2d", Month);
        sprintf(T_day_c, "%2d", T_day);
        sj_length[0] = SFR.UTF8toSJIS_convert("20" + String(Year) + "年" + String(Month_c) + "月" + String(T_day_c) + "日" + "     ", sj_txt[0]);

      こうすれば、とりあえずは縦方向スクロールでもOKです。
      ただ、半角1文字は中央に配置したいと私は思っていますが、今後の課題です。

      以上、これで試してみて下さい。
      因みに、私は素人アマチュアで独学ですので、スマートなライブラリを作るには技術やスキルが足りません。
      今の私の頭ではこれが限界です。
      ご不便をおかけしますが、ご容赦くださいませ。
      m(_ _)m

    • mgo-tec mgo-tec より:

      あと、このブログ記事では、キャッシュバイトを設定していて、マルチタスクで動作させていますが、シングルタスクで、メインループ内で動作させればかなりシンプルなスケッチになります。
      ただ、その場合、スクロールがかなりカクカクします。

  4. マッキー より:

    早速のご返答ありがとうございました。
    コメント送信がすぐに反映されなかったので、うまく送信できなかったのかなと思い、何度もコメントしてすみませんでした。
    全て表示はできました。
    ありがとうございました。
    JJY+時刻と気温、湿度を表示させようと実験中です。
    BME280は手持ちがなかったので、代わりにSHT21を繋いでテストしましたが、コンパイルエラーは出ないのですがセンサー値を読み込むルーチンで停止します。
    やはりESP32用のライブラリーがいるようです。
    BME280は届き次第テストしてみます。
    今年もご活躍を期待しております。

    • mgo-tec mgo-tec より:

      マッキーさん

      重複したと思われるコメントはこちらで削除させていただきましたので、何も問題ありません。
      コメント送信が直ぐ反映されず、逆にお手数おかけしました。
      このブログはちょっと動作が重く、申し訳ございません。

      SPIFFS の読み取りに関しては、私の方の課題がたくさんありますが、表示できて良かったです。
      今後改善していきたいと思っています。

      BME280 の私の自作ライブラリは殆どメンテナンスしてないので、不具合ありましたらまたコメントいただけると幸いです。
      こちらこそ、今後も当ブログをよろしくお願いいたします。
      m(_ _)m

  5. マッキー より:

    さっそくBME280のI2Cで動作させました。
    なにも問題ありません。SPIは未確認です。
    今のところ問題なく動作しています。
    SHT21のライブラリー作者のフォーラムをみるとやはりESP8266では動作するけどESP32は応答がないとか言ってます。
    この人はライセンス条項で「License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license)」とか洒落たこと言ってます。
    わたしもmgo-tecさんにビールぐらいで良かったらおごりたい気分です。

    • mgo-tec mgo-tec より:

      マッキーさん

      動いてくれてホッとしました。
      何分、独学ですので、他の方の環境で動くかどうか自信が無いもので・・・。

      ビールライセンスは洒落てますね。
      そんな洒落たことを書ける余裕は今の私にはとてもありませんが・・・。

      私もおごられたい気分ですが、アマチュアコードですのでチョコチョコ不具合があると思います。
      今はブログをご覧いただけるだけで十分です。
      お気持ちだけ、有難く、ありがた~く頂戴いたします。
      m(_ _)m

タイトルとURLをコピーしました