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

記事公開日:2017年9月28日


スポンサーリンク

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

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

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

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

#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)に設定しておきます。

esp32_spiffs_misaki30.jpg


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

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

esp32_spiffs_misaki10.jpg


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

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

esp32_spiffs_misaki11.jpg


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

esp32_spiffs_misaki12.jpg


ここで注目して欲しいのは、今までの私のブログ記事で紹介していた 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用バニラシールドを購入してみました。

esp32_spiffs_misaki13_01.jpg


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

Amazon.co.jp
ESPr® Developer用バニラシールド
スイッチサイエンス

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

esp32_spiffs_misaki13.jpg


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

esp32_spiffs_misaki14.jpg


esp32_spiffs_misaki15.jpg


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

esp32_spiffs_misaki16.jpg


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

esp32_spiffs_misaki17.jpg


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

esp32_spiffs_misaki18.jpg



スポンサーリンク


コメントを残す

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

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