ESP32-WROOM-32 の SPIFFS を使って、日本語漢字 美咲フォント を読み込む

ESP32 ( ESP-WROOM-32 )

micro SDHC カードのフォントをSPIFFS ファイルシステムでコピーする

Arduino - ESP32 SPIFFS アップローダー プラグインが使えるようになりました。
micro SDカード要らずで、Windows PC から直接アップロードできるようになりました。
以下の記事も合わせて参照してください。
ESP32-WROOM-32 SPIFFS アップローダープラグインの使い方
(2017/10/15)

では、micro SDHC カードに保存したフォントファイルを現状の Arduino core for ESP の SPIFFS ファイルシステムで ESP32-WROOM-32 のフラッシュにコピーしていきます。

Arduino IDE で以下のスケッチを入力してください。
基本的に Arduino core for ESP32 の「スケッチの例」にある、SPIFFS_Test を参考にしています。

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

#include "FS.h"
#include <SPIFFS.h>
#include <SD.h>
#include <SPI.h>

const char* UTF8SJIS_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル
const char* MISAKI_Zen_Font_file = "/font/MSKG13KU.FNT"; //美咲全角フォントファイル
const char* MISAKI_mgotec_Font_file = "/font/mgotec48.FNT"; //半角フォントファイル

//********************************************************************
void setup() {  
  Serial.begin(115200);

  if (!SPIFFS.begin()) { //マウントできない場合は begin(true) としてみてください。
    Serial.println("SPIFFS Mount Failed");
    return;
  }
  delay(100);

  SD.begin(5, SPI, 20000000, "/sd"); //CSピン #5 SPI周波数 20MHz

  listDir(SPIFFS, "/", 0); //SPIFFSフラッシュ ルートのファイルリスト表示
  delay(100);
/*
  deleteFile(SPIFFS, "/MSKG13KU.FNT");
  deleteFile(SPIFFS, "/Utf8Sjis.tbl");
  deleteFile(SPIFFS, "/mgotec48.FNT");
*/
  listDir(SPIFFS, "/", 0);

  SDcopySPIFFS(UTF8SJIS_file, "/Utf8Sjis.tbl");
  SDcopySPIFFS(MISAKI_Zen_Font_file, "/MSKG13KU.FNT");
  SDcopySPIFFS(MISAKI_mgotec_Font_file, "/mgotec48.FNT");

  delay(10);

  listDir(SPIFFS, "/", 0);

  SPIFFS.end();
}
//********************************************************************
void loop() {

}
//********************************************************************
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
  Serial.printf("\nListing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(file.name());
      if (levels) {
        listDir(fs, file.name(), levels - 1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}
//********************************************************************
void deleteFile(fs::FS &fs, const char * path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}
//********************************************************************
void SDcopySPIFFS(const char *SDfilename, const char *SpiffsFilename){
  File SDfile = SD.open(SDfilename, FILE_READ);

  Serial.println();

  if (!SDfile) {
    Serial.print(SDfilename);
    Serial.println(" File not found");
    return;
  }else{
    Serial.print(SDfilename);
    Serial.println(" File read OK!");
  }

  File SpiffsFile = SPIFFS.open(SpiffsFilename, FILE_WRITE);
  if (!SpiffsFile) {
    Serial.println("Failed to open file for writing");
    return;
  }

  byte b;
  uint32_t LastTime = millis();

  if(SDfile){
    if (SpiffsFile) {
      while(SDfile.available()){
        b = SDfile.read();
        SpiffsFile.write(b);
        if((millis()-LastTime) > 10){
          delay(1);
          LastTime = millis();
        }
      }

      delay(10);
      SDfile.close();
      Serial.print(SDfilename);
      Serial.println("-------------SD card file closed");
      delay(10);

      SpiffsFile.close();
      Serial.print(SDfilename);
      Serial.println("---------SPIFFS file closed");
      delay(10);
    }
  }
}

【解説】

●6-8行:
micro SDHC カードのファイル名を定義しています。
micro SDHC のルートにファイルがある場合は、font/ を削除して、
/Utf8Sjis.tbl
としてください。

●14行:
もし、マウントに失敗して、シリアルモニターでエラーが出る場合は、
SPIFFS.begin(true)
としてみてください。
これはフォーマット失敗した場合に true とするようです。
デフォルトでは false になっています。
通常は SPIFFS.begin() のままで良いです。
一度 true モードで初期化したら、その後は true を無しにしてみてください。

●20行:
ここで、SDカードを SPI 通信として、CS ( チップセレクト )ピンを5番としています。
クロック周波数は 20MHz としています。

●22行:
46-75行の関数で、SPIFFS フラッシュの中のファイル名をリストアップします。
サンプルスケッチそのまま使用しています。

●24-28行:
もし、予め SPIFFS フラッシュの中に不要なファイルがあったら、このコメントを外してファイル名を書き換えて、不要なファイルを削除できます。

●29行:
ファイルを削除した場合、その後のリストアップです。

●31-33行:
86-132行で定義されている、micro SDHC カードから SPIFFS フラッシュへファイルをコピーする関数です。
これは私が作りました。
ファイルサイズが大きいと、結構時間がかかります。

●46-75行:
SPIFFS フラッシュ内のファイル名をシリアルモニターにリストアップする関数です。
サンプルスケッチそのままです。

●77-84行:
SPIFFS フラッシュ内のファイルを削除する関数です。

●86-132行:
micro SDHC カードのファイルから、SPIFFSフラッシュへコピーする関数です。
自作です。
まず、micro SDHC カードのファイルを開き、その後、SPIFFSフラッシュのファイルを開いて、micro SDHCカードのファイルを読み込みながら、SPIFFSフラッシュへ書き込みます。
この時、アクセスが長期間連続してしまうと ESP32 のウォッチドッグタイマが作動できなくて、エラーになってしまうので、10ms 毎に delay(1)の休止期間を設けて、ウォッチドッグタイマを動作させています。

●121,126行;
書き込み終わったら、必ずファイルをクローズしておきます。

micro SDHC → SPIFFS フラッシュファイルコピー実行

では、micro SDHC カードスロットにフォントファイルを保存した micro SDHC カードを挿入してください。

Arduino IDE でコンパイルする前に、下図のようにフラッシュサイズを 4MB (32Mbit)に設定しておきます。

では、上記のスケッチをコンパイル書き込み実行させてください。

115200 bps でシリアルモニターを起動すると下図の様になればOKです。
Utf8Sjis ファイルはサイズが大きいので、書き込みに少々時間がかかります。

フルカラー有機EL ( OLED )ディスプレイを接続する

では、今度は SPIFFSフラッシュに保存したフォントファイルを読み出して、フルカラーの有機EL ディスプレイに表示させてみます。
まずは、下図の様に、OLED SSD1331 モジュールを HSPI接続します。

Pmod OLEDを使った場合は下図の様になります。

ここで注目して欲しいのは、今までの私のブログ記事で紹介していた OLED SSD1331 ディスプレイの接続方法と1か所変えています。
それは、D/C 端子を GPIO #21 に変えたことです。
この GPIO #21 は、Arduino core for ESPのページの図を参照すると、Wire SDA とあります。
つまり、I2C 通信端子になっています。
今後、I2C通信と併用したい場合は問題になりそうですね。
しかし、私が I2C 通信のセンサー BME280 で試したところ、GPIO #22 が使えれば、#21 は #25に代用できたので、遠慮なく #21 を使うことにしました。
それと、こちらの記事のようにピンソケット部分にシールド(モジュール)っぽくマウントしようとすると、どうしても #21 を使うしかなかったのです。
micro SDスロット用の VSPIピンも空けておきたかったというのもあります。

そこで、スイッチサイエンスさんで販売している、ESPr® Developer用バニラシールドを購入してみました。

他の片面ユニバーサル基板で作ったりもしましたが、ランドが剥がれたりして品質がイマイチでした。
でも、これは両面スルーホール基板になっていて、とても品質が良く、ランドが剥がれるようなことはありません。
ESPr Developer 32 と形状や色もとても良くマッチしますのでお勧めです。

ESPr® Developer用バニラシールド

配線は下図の様にします。

私の場合は、ピンヘッダからハンダ付けして、下図の様にジャンパー線をハンダ付けします。
表面と裏面にもジャンパーしたりしています。
即席のハンダ付けで、下手クソでスイマセン。

最後に OLED SSD1331 モジュールにピンヘッダをハンダ付けし、それごとバニラシールドへハンダ付けします。
すると、下図の様になります。

この SSD1331 モジュールは、インダクターなどのパーツの高さがあるので、結構隙間をあけなければなりません。
真横から見るとこんな感じの隙間です。

ESPr Developer 32 にマウントするとこんな感じです。

コメント

  1. いなり より:

    MAX7219制御の8x32のマトリックスLEDに美咲フォントを表示さしたいです。どうすればいいかわからないのでご教授願いたいです

    • mgo-tec mgo-tec より:

      いなりさん

      記事をご覧いただき、ありがとうございます。

      残念ながら、MAX7219は使ったことが無いので、まったく分かりません。

      ご気分を害されるかもしれませんが、正直にお答えしたいと思います。
      私がその美咲フォントを表示させるためには、それぞれの部品を購入し、1から回路を作成し、各パーツのデータシートを熟読し、オシロスコープ等で波形を確認しながらプログラミングすることになります。
      他の仕事をしないで、それにかかりきりになれば、1か月くらいでできるのではないかと思います。
      また、それができたとして、お教えするためにはブログに記事をアップするなどの、原稿執筆の時間が更に半月くらいかかります。

      今現在の私の場合は、他の本業の仕事と家庭の仕事があり、更に次の新規記事の編集を抱えていますので、その倍以上の日数がかかります。
      その期間の生活費や賃金をお支払い頂かないと、とてもご依頼にお答えすることはできません。
      以上、ご要望にお応えできず、誠に申し訳ございませんが、ご理解くださいませ。

  2. いなり より:

    丁寧な返信をしていただきありがとうございます。これからデータシートとにらめっこしながら自分で開発していきたいと思います。これからもこのブログを読ませていただくので更新頑張ってください。

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