● 実験テーマ167

「QVGAカラー液晶_ILI9328(ESP32S3 Dev ModuleにSPI接続)を試す_その3」
(シリアルモニターにSDカード内のファイル名リストを表示するテストと液晶に内容表示するテスト)

■ 2026.2.9
  ・
今日から「SDカードテスト:ESP32S3_SD_TEST.ino」開始
   最初に回路図からと思って、aitendoのキャリーボード上に実装されている横長のカードスロットと
   SD側の9pinコネクタ間の接続状況をテスターにて確認した。(aitendoさんは回路の記載無し。コネクタのピンアサインのみ記載)
   ボード上にはチップ抵抗が数個実装されていた。これらはSPI各信号のプルアップ抵抗:10kΩということが分かった。
   ※ テスターで接続(ピンアサイン)を確認してたら、基板上のピンの信号名シルクと、aitedo当該製品ページのピンアサインの
   信号名がテレコになっていることが判明した。
   基板上のシルクが正しい→ 5pin= SD_DO, 6pin= SD_SCK
   aitedo当該製品ページのピンアサインは誤記→ × テレコになっている(5pin= SD_SCK, 6pin= SD_DO)
   最初に気が付いて良かった。

  ・水魚堂にて実験回路図作成済


■ 2026.2.10
  ・ハードウエア準備
   キャリーボードのSD側のランドに、9pinコネクタを実装しESP32S3モジュールとジャンパ線で接続。
   液晶側に接続されているコネクタは外しておく。(下の写真は外す前)
   



  ・SDカードがFAT32でフォーマットされているか
   → プロパティで確認「FAT]になってた。たぶんMSDOS FATのことで、FAT32と同じと思われる。
      mp3ファイルが収録されている「8MB SDカード」が手元にあるので、それで試す。

  ---------------------------------------------------------------------------------------------------

<「SDカードテスト:ESP32S3_SD_TEST.ino」を検討>
 (1) 予めCopilotへ聞いておいた。:260205
   Q1.「ESP32S3-DEV-モジュールとILI9328液晶(SDカードスロット付き)の組合せで、
      SDカードにアクセスしてArduino IDEのシリアルモニターにSDの内容を表示するサンプルスケッチを書いてください。」

   A1.① 必要なライブラリと設定
      ・SDカードへのアクセスには、標準のSD.hライブラリを使用します。

      ② ハードウェア接続

SDカード信号

ESP32S3ピン (一般的なSPI接続例)

備考

CS (Chip Select)  GPIO10 他のGPIOピンに変更可能
SCK (Serial Clock)  GPIO12  
MOSI (Master Out Slave In) GPIO13  
MISO (Master In Slave Out) GPIO11  
VCC 3.3V  
GND GND  

       ・重要:ESP32S3では、SDカード用のSPI通信はどのGPIOポートでも設定可能ですが、上記は一般的な例です。
            液晶モジュールとSDカードで同じSPIバス(SCK, MOSI, MISO)を共有し、CSピンのみを別々に指定します。

    ③ サンプルスケッチ:SDカード内容の表示
     ・このスケッチはSDカードのルートディレクトリの内容をリスト表示し、
      test.txtというファイルを作成・書き込み・読み込みます。

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

// SDカードのCSピンを定義します。接続に合わせて変更してください。
#define SD_CS 10

void setup() {
  Serial.begin(115200);
  while (!Serial); // シリアルモニターが開くまで待機

  Serial.println("\nInitializing SD card...");

  // SDカードの初期化時にCSピンを指定
  if (!SD.begin(SD_CS)) {
    Serial.println("Card Mount Failed");
    return;
  }
  Serial.println("Card Mounted Successfully");

  // SDカードの容量情報を表示
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  // ルートディレクトリの内容をリスト表示
  Serial.println("\nListing files in root directory:");
  listDir(SD, "/", 0);

  // ファイルへの書き込みと読み込みの例
  createFile(SD, "/test.txt");
  appendFile(SD, "/test.txt", "Hello ESP32S3 and ILI9328 combo!");
  readFile(SD, "/test.txt");
}

void loop() {
  // 特に実行することはない
}

void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);
  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  f (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  ile 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 createFile(fs::FS &fs, const char * path) {
  Serial.printf("Creating File: %s\n", path);
  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print("Initial content")) {
    Serial.println("File written");
  } else {
      Serial.println("Write failed");
  }
  file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Appending to File: %s\n", path);
  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
      Serial.println("Append failed");
  }
  file.close();
}

void readFile(fs::FS &fs, const char * path) {
  Serial.printf("Reading file: %s\n", path);
  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }
  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  Serial.println();
  file.close();
}

-----------------------------------------------------------------------------

  ・関数類はプロタイプ宣言しておく。後は変数型の書き方は、Arduinoの流儀に従ってみる。
  ・ピン定義はCSのみだが、他はしなくてもよいのか?とりあえずサンプルのままにしてみる。

  ・スケッチ作成後、コンパイルしてみた。
  → イージーミスが一か所有ったが、コンパイルは通過した。

     最大1310720バイトのフラッシュメモリのうち、スケッチが369875バイト(28%)を使っています。
     最大327680バイトのRAMのうち、グローバル変数が20944バイト(6%)を使っていて、ローカル変数で306736バイト使うことができます。

  → コンパイル~RUNも一発OKになる。Copilotさん、やるじゃない!!

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2820,len:0x116c
load:0x403c8700,len:0xc2c
load:0x403cb700,len:0x3108
entry 0x403c88b8

Initializing SD card...
Card Mounted Successfully
SD Card Size: 6MB

Listing files in root directory:
Listing directory: /
FILE: test.txt SIZE: 47
FILE: CHK_INFO.mp3 SIZE: 423188
FILE: LCH_CHK.mp3 SIZE: 203760
FILE: RCH_CHK.mp3 SIZE: 199162
FILE: MONO_CHK.mp3 SIZE: 283590
FILE: SN_C_INF.mp3 SIZE: 475433
FILE: SN_ODB.mp3 SIZE: 378467
FILE: SN_40DB.mp3 SIZE: 364674
FILE: SN_60DB.mp3 SIZE: 821921
FILE: VIB_INFO.mp3 SIZE: 258142
FILE: VIB_500.mp3 SIZE: 199612
FILE: VIB_250.mp3 SIZE: 200030
FILE: VIB_100.mp3 SIZE: 197104
FILE: VIB_50.mp3 SIZE: 197522
FILE: VIB_25.mp3 SIZE: 205881
FILE: RNG_INFO.mp3 SIZE: 451208
FILE: 20_20K_C.mp3 SIZE: 957774
DIR : System Volume Information
Creating File: /test.txt
File written
Appending to File: /test.txt
Message appended
Reading file: /test.txt
Read from file: Initial contentHello ESP32S3 and ILI9328 combo!

-----------------------------------------------------------------------------

  ・次は液晶との連携(SD_ADD_LCD_TESTプロジェクト)を試す。
   Copilotとコンタクトしている途中でまた通信が途絶えた。
   明日へ続く。


■ 2026.2.11
  
<新たにCopilotに聞いてみた。>
   ※ 途中から再開した。
     「SDカード内のファイル名(テキストやMP3)を液晶に一覧表示する」ステップから再開

   Q1.SDカード内のファイル名(テキストやMP3)を液晶に一覧表示するサンプルコードをお願いします。
   A1.以下に、ESP32のSDライブラリを使用して、ルートディレクトリにあるファイルを取得する基本的なロジックを提示します。

#include "SD.h"

void listFilesToTFT(File dir, int x, int y) {
int line = 0;
  while (true) {
    File entry = dir.openNextFile();
    if (!entry) break; // ファイルがなくなったら終了

    // 液晶のy座標を一行(12ピクセル等)ずつ下げて表示
    // 自作のANK表示関数(例: drawString)を使用
    myDrawString(x, y + (line * 14), entry.name()); 

    entry.close();
    line++;
    if (line > 15) break; // 画面内に収めるための制限
  }
}

    ・表示上の注意点までアドバイスしてくれた。
     ① ファイル名の長さ: entry.name() はフルパスを含む場合があります。液晶の幅に合わせて、
        一定の文字数でクリップ(切り捨て)する処理を入れると表示が崩れません。

     ② 描画の更新: 新しいファイル一覧を表示する前に、背景色で一度塗りつぶし(矩形塗り)を行わないと、
        前の文字が残って重なってしまいます。

     ③ MP3やテキストの判別
       ③-1.ファイル名を表示する際、拡張子を見て「アイコン」を添えたり色を変えたりすると使い勝手が良くなります。
           ・String name = entry.name();
           ・if (name.endsWith(".mp3")) { /* 青色で表示 */ }
           ・if (name.endsWith(".txt")) { /* 白色で表示 */ }
           ・まずは、「ファイル名を1つ取得して液晶に1行表示する」ところから試されるのがスムーズかと思います。

     ④ ルートディレクトリのみに絞れば、再帰処理(フォルダの中をさらに探す処理)が不要になるため、
        コードが非常にシンプルになり、メモリ消費や動作の安定性も向上します。
        実装の際は、SD.open("/") で開いたルート直下を openNextFile() で順次読み出す形になります。
        ESP32のSDライブラリの openNextFile() を使えば、ファイルもディレクトリも区別なく順番に取得できるので、今のフェーズには最適です。

       自作のANK表示関数(12x12フォント)をお持ちとのことですので、
       ファイル名の文字列長に合わせて表示領域をはみ出さないようにガード(例えば、20文字以降は表示しない等)
       を入れておくと、予期せぬ描画崩れを防げます。

     ⑤ まとめ(スケッチ検討のヒント)
      ・SDカードからファイル名を取得する際の最小限の構成です:
        ① SD.begin(CS_PIN) で初期化。
        ② root = SD.open("/") でルートを開く
        ③ file = root.openNextFile() をループさせ、file.name() を自作のANK表示関数に渡す。

      ※ 主要な関数の簡易メモ
        ・スケッチ検討の際、以下の3つをまず押さえておくとスムーズです。

         ① SD.begin(ssPin, SPI, frequency)
           ・戻り値:成功なら true
           ・ssPin はCSピン番号。

         ② SD.open(path, mode)
           ・戻り値:File オブジェクト
           ・mode は FILE_READ(読み込み)や FILE_WRITE(追記)を指定。

         ③ file.openNextFile()
           ・戻り値:次の File オブジェクト(なければ false)
           ・ディレクトリ内のスキャンに使用。


■ 2026.2.12
  ・Copilotから以下の「ファイル一覧取得のサンプルコード:LCDにファイルリストを表示」を提示して頂いた。
   サンプルコードは、ファイル名のシリアルモニターへの出力も書いてありますが、私の場合、液晶のみなので
   そこはコメントアウトにしてあります。
   また、サンプルコードは、サブディレクトリも対象に含まれていますが、私の場合は、ルートディレクトリのみを
   対象にする考えなので、ここもコメントアウトしてあります。
   その他は、サンプルコードのまま一回試してみることにしました。

void listRootFiles()
{
  // 1. ルートディレクトリを開く
   File root = SD.open("/");
    if (!root) {
     Serial.println("ルートディレクトリが開けません"); // シリアルモニタに出力
      return;
   }
    if (!root.isDirectory()) {
      Serial.println("ディレクトリではありません"); // シリアルモニタに出力
        return;
    }

    // 2. ループで次々とファイルを取得
    File file = root.openNextFile();
    int lineCount = 0;
    int yOffset = 0;

    while (file) {
     
  /*
      
if (file.isDirectory()) {
        // ディレクトリの場合の処理(今回はスルーでもOK)
        Serial.print(" DIR : ");
        Serial.println(file.name());
       } else {
    */
         
// ファイルの場合(ファイル名取得)
      const char* fileName = file.name();
      // Serial.print(" FILE: ");
      // Serial.println(fileName);

      // 3. 自作の液晶表示関数に渡す例
      // 12x12フォントであれば、y座標を14〜16ピクセルずつずらしていく
      // myDrawString(0, yOffset, fileName);
      // yOffset += 14;
    /*
      /// 液晶の1画面にファイル名リストを表示 
     for(j=0; j<17; j++){ // 1画面:26文字/行 * 17文字/列=442キャラクタ
        for(i=0; i<26; i++){
        LCD_DrawString(0, j, fileName, WHITE, BLACK); // 液晶にファイル名を表示
      }
    } 
    */

   LCD_DrawString(0, yOffset, fileName, WHITE, BLACK); // 液晶にファイル名を表示
   yOffset += 16; 

   // 次のファイルへ
   file = root.openNextFile();
   lineCount++;

   // 液晶の表示範囲を超えないためのガード(17行まで)
   if (lineCount >= 16) break; 

   } // END WHILE

   root.close();
}

 NOTE1.<重要なポイントと補足>
     ① file.name() の戻り値:
      ・ESP32のSDライブラリのバージョンによっては、file.name() が「フルパス(/test.txt)」で返る場合と
       「ファイル名のみ(test.txt)」で返る場合があります。
      ・もし / が邪魔な場合は、if (fileName[0] == '/') fileName++; のようにして先頭を一文字飛ばすと綺麗に表示できます。

     ② メモリ管理
      ・openNextFile() で開いた file オブジェクトは、ループの終わりや次に進む際に適切に閉じることが推奨されますが、
       file = root.openNextFile() と上書き代入する際に古いオブジェクトは自動で破棄(クローズ)される仕組みになっています。

     ③ SD.begin の注意点:
      ・ESP32S3で自前のSPIピンを指定している場合は、SD.begin(CS_PIN, spiInstance) のように、
       使用するSPIバスのインスタンスを渡す必要があるかもしれません。

 NOTE2.紹介したLang-ship:ESP32でSDカードを利用するのサイトに、
      「ファイル名取得時の挙動の違い」などの細かい注意点も載っていますので、スケッチ作成時に横に開いておくと非常に役立つはずです。


■ 2026.2.13
  ・SD_ADD_LCD_TESTプロジェクト開始
   (1) 動作仕様
    ① SDカードをスロットに挿入し、ESP32S3ボードの電源を入れる。
    ② SDカードのルートディレクトリを開く。
    ③ オープン失敗の場合、シリアルモニターに"ルートディレクトリが開けません" を表示
    ④ オープン成功の場合、液晶の1画面に、SDカードのルートディレクトリに有るファイルリストを表示

   (2) 大筋のスケッチ
     注意:SDとLCD共通のSPIポートを使用するため、それぞれにアクセスする時は次のようにする。
      <SDにアクセス時>
       ・実行前に、D_CS= HIGH(ノンアクティブ)/ SD_CS= LOW(アクティブ)にしてアクセス
      <LCDにアクセス時>
       ・実行前に、SD_CS= HIGH(ノンアクティブ)/ D_CS= LOW(アクティブ)にしてアクセス

------------------------------------------------------------------------------------------------------

  <ファイル一覧取得のサンプルコード:LCDにファイルリストを表示:Copilotによる、まとめ
  ・以下のコードは、ルートディレクトリにあるファイル名を取得し、シリアルモニタと(想定される)自作関数へ渡す流れをまとめたものです。

#include "FS.h"
#include "SD.h"
#include "SPI.h"

// 自作のANK表示関数のプロトタイプ宣言(引数はご自身の環境に合わせて調整してください)
// 例: void myDrawString(int x, int y, const char* text);

  void listRootFiles()
  {
  // 1. ルートディレクトリを開く
  File root = SD.open("/");
  if (!root) {
    Serial.println("ルートディレクトリが開けません"); // シリアルモニタに出力
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("ディレクトリではありません"); // シリアルモニタに出力
    return;
  }

  // 2. ループで次々とファイルを取得
  File file = root.openNextFile();
  int lineCount = 0;
  int yOffset = 0;

  while (file) {
    /// ファイル名取得
    const char* fileName = file.name();

    /// ファイル名の文字フォントデータを液晶表示関数に渡す。
    /// 12x12フォントなので、y座標を16ピクセルずつずらしていく。
    /// 液晶の1画面にファイル名リストを表示:1画面:26文字/行 * 17文字/列=442キャラクタ
   LCD_DrawString(0, yOffset, fileName, WHITE, BLACK); // 液晶にファイル名を表示
    yOffset += 16; 

    // 次のファイルへ
    file = root.openNextFile();
    lineCount++;

    // 液晶の表示範囲を超えないためのガード(17行まで)
    if (lineCount >= 16) break; 

  } // END WHILE

root.close();
}

・ステッチ書き上げた。
→ さてコンパイル結果は?
  イージーなのは無くしたが、未だエラーある。明日に続く


■ 2026.2.14
  <Copilotからのアドバイス:2160210より>
  ※ 重要なポイントと補足
   ① file.name() の戻り値
    ・ESP32のSDライブラリのバージョンによっては、file.name() が「フルパス(/test.txt)」で返る場合と
     「ファイル名のみ(test.txt)」で返る場合があります。
     もし / が邪魔な場合は、if (fileName[0] == '/') fileName++; のようにして先頭を一文字飛ばすと綺麗に表示できます。

   ② メモリ管理
    ・openNextFile() で開いた file オブジェクトは、ループの終わりや次に進む際に適切に閉じることが推奨されますが、
     file = root.openNextFile() と上書き代入する際に古いオブジェクトは自動で破棄(クローズ)される仕組みになっています。

   ③ SD.begin の注意点
    ・ESP32S3で自前のSPIピンを指定している場合は、SD.begin(CS_PIN, spiInstance) のように、
     使用するSPIバスのインスタンスを渡す必要があるかもしれません。

   ④ 紹介したLang-ship:ESP32でSDカードを利用するのサイトに、
     「ファイル名取得時の挙動の違い」などの細かい注意点も載っていますので、
     スケッチ作成時に横に開いておくと非常に役立つはずです。

  ※ 明日の実装に向けたアドバイス
    シリアル出力を液晶表示に切り替える際、以下の「自作関数への渡し方」だけ気をつけておくとスムーズです。
     ① 型の一致: file.name() は const char* を返すことが多いため、
        自作の表示関数がString 型を求めているか、char* を求めているかに合わせて微調整してください。

     ② 画面のクリア: ファイル一覧を再描画する際、全画面クリア(塗りつぶし)をするとチラつくことがあります。
        文字を表示する領域だけを黒塗りにする「部分更新」を検討されると、より本格的なMP3プレーヤーに近づきます。

-----------------------------------------------------------------------------------------------------------------------

  ・現在のコンパイルエラー:Compilation error: 'SPI2' was not declared in this scope; did you mean 'SPI'?

-----------------------------------------------------------------------------------

  ① 'SPI2' was not declared in this scope; did you mean 'SPI'?
   → 冒頭の以下がコメントアウトされていたので解除

    // SPI2(FSPI)の名前を「SPI2」に統一して定義
    SPIClass SPI2(FSPI);

    // SPI2のMODE設定をグローバルに定義(液晶描画全関数で使用可能)
    SPISettings settings(10000000, MSBFIRST, SPI_MODE3);

----------------------------------------------------------------------------------- 

    ・エラーは減ったが未だある。
     Compilation error: 'CS' was not declared in this scope; did you mean 'SS'?
     (このスコープでは「CS」は宣言されていません。「SS」を意味していましたか?)

  ② CSのところを全て→ D_CSに修正
     まただいぶ減ったが、未だある。
     Compilation error: invalid conversion from 'const char*' to 'char*' [-fpermissive]
     (コンパイルエラー: 'const char*' から 'char*' への無効な変換 [-fpermissive])

  ③ void LCD_DrawString(int colum, int line, char *s, unsigned int color1, unsigned int color2)に対し、
     LCD_DrawString(0, yOffset, fileName, WHITE, BLACK); // 液晶にファイル名を表示

     これは、Copilotのコメントにある以下に相当
     型の一致: file.name() は const char* を返すことが多いため、
     自作の表示関数がString 型を求めているか、char* を求めているかに合わせて微調整してください

     フォントは、const charで定義されているので、これに合わす必要がある。
     → void LCD_DrawString(int colum, int line, char *s, unsigned int color1, unsigned int color2)
     これの引数:char *s → const char *sに修正してみた。

  → これでコンパイルエラー無しになった!!
     最大1310720バイトのフラッシュメモリのうち、スケッチが374255バイト(28%)を使っています。
     最大327680バイトのRAMのうち、グローバル変数が20984バイト(6%)を使っていて、ローカル変数で306696バイト使うことができます。

  → 書込み~ 動作確認してみた。
     ・まずは駄目。
      シリアルモニターにSDに関するメッセージが出てこない。以下参照。

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2820,len:0x116c
load:0x403c8700,len:0xc2c
load:0x403cb700,len:0x3108
entry 0x403c88b8

     ・ただ、最初の液晶画面クリアはOK
      その後、SDカードの"Card Mounted Successfully"等のメッセージが出てこない。

      本来は、冒頭のrst~entryメッセージ後、以下が出てくるが、出てこない。 

Initializing SD card...
Card Mounted Successfully


-----------------------------------------------------------------------------------

     ・この後、Copilotに相談した結果、SDマウントに成功した。Card Mounted Successfullyが出た。
      ただmp3ファイル名の液晶への表示は、一部しているが、未だおかしい。
      何故か、昨日SDカードに書込んだ、"test.txt"が頭に表示され、
      液晶の最下位行にmp3ファイルの一部の、"CHK_INFO.mp3"が表示しているだけ。



      たぶん行列の制御が上手く行ってないと思われる。明日追及する予定。


■ 2026.2.15
  <sdのみで書込んだ、"test.txt"が頭に表示され、液晶の最下位行にmp3ファイルの一部の、"CHK_INFO.mp3"が表示しているだけ・・を追求する>
   (1) TESTに使ったSDカードに収録されているファイルは以下。更新が新しい順に整理した。
      test.txt
      CHK_INFO.mp3
      LCH_CHK.mp3
      MONO_CHK.mp3
      RCH_CHK.mp3
      20_20K_C.mp3
      RNG_INFO.mp3
      SN_40DB.mp3
      SN_60DB.mp3
      SN_C_INF.mp3
      SN_ODB.mp3
      VIB_25.mp3
      VIB_50.mp3
      VIB_100.mp3
      VIB_250.mp3
      VIB_500.mp3
      RNG_INFO.mp3

      なので、最初の2ファイルしか表示されてないことになる。
      しかも2つ目のファイルの表示位置が次の行ではなく、画面の最終行になっている。
      これが他のファイルが表示されてない理由と思われる。

   (2) 分かった。
     以下のコメントアウトしたところを修正で良いはず。yOffsetと、lineCountの2つで行制御してたのが問題。

void listRootFiles()
{
  // int lineCount = 0;
  // int yOffset = 0;

  int y= 0; 
     ・
  while (file) {
     ・
  // LCD_DrawString(0, yOffset, fileName, WHITE, BLACK); // 液晶にファイル名を表示
  // yOffset += 16; // この変数Copilotの参考コードのまま。たぶんドット単位の移動と勘違いしてる。

    LCD_DrawString(0, y, fileName, WHITE, BLACK); // 液晶にファイル名を表示 
    y++;

    digitalWrite(D_CS, HIGH);
    digitalWrite(SD_CS, LOW);
    // 次のファイルへ
    file = root.openNextFile();
    // lineCount++;

    // 液晶の表示範囲を超えないためのガード(17行まで)
    // if (lineCount >= 16) break; 
    if (y >= 16) break; 

  } // end while
}

→ これでOKになる。
→ 今の表示方向だと、SDカードスロットの位置が下になるが、今までの自作MP3と方向的には同じで自然(コントローラICのマスクテープ側が右側)
   なのでこのままにする。機構の工夫で何とかなる。まずはこの方向で考える。


■ 2026.2.16
  ・SDカードのSPI転送スピード:4MHzにしているが、実用上限の、40MHzにしてみる。
  → ビデオ撮った。video001.mp4/ 1.29MB 3秒 多少速くなった感じ。たぶん描画に時間のウエイトがかかっている。

  <参考:SDカードのSPI転送スピードについて:AI検索>
   ・ESP32-S3を使用してSDカードをSPIモードで制御する場合、通信クロックの上限(バススピード)は、
    一般的に最大40MHz〜80MHzの間で設定されます。

   (1) 通信クロック(SPI Clock Frequency)
    ① 物理的上限: ESP32-S3のハードウェアSPIは最大80MHzまで対応していますが、
       SDカードとの接続においては、安定動作と互換性の観点から、40MHzが現実的な上限となることが多いです。

    ② SDカード側の制限: 多くのSDカードは高速モード(High Speed mode)で最大50MHzまで対応していますが、
       SPIモードでの安定した動作や配線容量(AC Loading)を考慮し、
       ESP-IDFなどでは通常最大40MHz程度が上限として設計されます。

    ③ 設定値の目安: 安定性を重視する場合、20MHzまたは40MHzに設定します。 

   (2) 実効転送速度(Data Throughput)
     ※ 40MHzのクロックで動作させた場合でも、SPIモードの通信効率(コマンドのオーバーヘッドなど)により、
      実際のデータ転送速度は大幅に低下します。
    ① 実効速度目安: 数MB/s程度(例: 1MB/s〜4MB/s程度)
    ② 低速な環境: 劣悪な配線環境やSDカードの種類によっては、400KB/s程度まで低下する場合もあります。 
    ③ ライブラリ: Arduino環境ではSD.hよりもSdFatライブラリを使用すると、高速なファイル書き込みが期待できます。 

     ※ より高速な転送(20MB/s〜)が必要な場合は、SPIモード(1bit)ではなく、
        SDIOモード(4bit)での接続を推奨します。ESP32-S3はSDIOモードで高速な通信をサポートしています。 


<最終回路図>

・こちらからどうそ→ ESP32S3_SD_TEST回路図 (SDのみ接続)
                            ESP32S3_SD_ADD_LCD回路図 (SD+LCD接続)

<最終スケッチ>

こちらから、どうぞ→ ESP32S3_SD_TEST.ino (SDのみ接続)
                              SD_ADD_LCD_TEST.ino (SD+LCD接続)

             ASCII12dot.h (ASCII(ANK)文字データテーブル)  


← 実験テーマ1に戻る   TOP PAGEに戻る     実験テーマ168へ →