Step2: M5StickC Plus2 SDカード読み込みテスト

Step 1で作成したCSVデータ(led15_log.csv)をSDカードに保存したら、次はM5StickC Plus2側でそれを読み込めるかテストします。

いきなりLEDを光らせるのではなく、まずは「SDカードリーダーが正しく認識されているか」「ファイル一覧が読み取れるか」を確認する診断プログラムを動かしましょう。

このステップの目的

  • M5StickC Plus2に接続したSDカードリーダーが、ハードウェアとして認識されているか確認する。
  • SDカード内のルートディレクトリにあるファイル名を表示し、パスやフォーマットに問題がないか確認する。

必要なハードウェア

M5StickC Plus2にはSDカードスロットがないため、SDカードソケットを使用します。

標準的なSDカードソケットを使用する場合、以下のピン配置で接続されます。

信号線機能 (SPI)M5StickC Plus2 GPIO役割
SCKClockG0通信のタイミング同期
MISOMaster In Slave OutG36データ受信(SD→M5)
MOSIMaster Out Slave OutG26データ送信(M5→SD)
CSChip SelectG33通信相手の選択

この辺り差し間違いなどでエラーが多発しそうで、最悪M5StickC Plus2が壊れる可能性が拭えなかったため、こちらでプリント基板を用意しました。

さてここで、1年生時の説明画像をここに再掲します。

ブレッドボードでも良いのですが、今回はせっかくなので腕時計型で完結したいところです。

そこで、ユニバーサル基板(左側)で作っても良いのですが、授業時間を考慮すると時間が足りそうにないです。なのでプリント基板を作成しました。

回路図は以下でで、交差する線が多いです。(番号でわかりにくくすみませ、右側がM5の差し口と対応してます)。

これを元に基板を設計して、ELECROWFusion PCBなどで発注すれば1000円くらいで10枚(1枚あたり20個)ほど作れて、1週間くらいで届きます。

結構簡単に基板作れるので、興味がある方は是非オリジナル基板の作成にチャレンジしてみてください。
※私はKiCadというソフトを使っています。チュートリアルはこれがわかりやすいかと思います。

組み立て

以下の画像のように、SDカードソケットとM5StickC Plus2を繋げてみましょう。基板の側面に赤色のペンで塗ったので、そちら側に詰めてさしてください。

以下のように赤色じゃないほうに刺さってない箇所が一つ見えるのが正解です。

ここまで来るとあとは楽でLEDを差し込みます。

余っている赤色のコードを先ほどの空いているところに差し込みましょう

ここまで出来たら組み立ては完成です。※腕に巻くとこの後が面倒なので、巻かなくて大丈夫です。

テスト用コード

以下のコードをArduino IDEにコピーし、M5StickC Plus2に書き込んでください。

コード(m5_sd_list_files.ino)
#include <M5StickCPlus2.h>  // M5StickC Plus2 用ライブラリ
#include <SPI.h>             // SPI通信
#include <SD.h>              // SDカード操作

#define SD_CS 33             // SDカードCSピン(G33)

// ★重要ポイント:LCDとは別のSPIバス(HSPI)を使用する定義
SPIClass SPI_SD(HSPI);       

void setup() {
  M5.begin();                // 本体初期化
  M5.Lcd.setRotation(3);     // 画面の回転方向(横向き)
  M5.Lcd.fillScreen(BLACK);  // 画面クリア
  M5.Lcd.setTextSize(2);     // 文字サイズ設定

  // 1. SPI通信の開始設定
  // 引数: (SCK, MISO, MOSI, CS) -> Hatのピン配置に合わせる
  SPI_SD.begin(0, 36, 26, SD_CS);  
  
  pinMode(SD_CS, OUTPUT);          
  digitalWrite(SD_CS, HIGH);       // 初期状態はOFF(HIGH)

  // 2. SDカードの初期化
  // 第2引数に先ほど設定した SPI_SD を渡すことで、正しいピンで通信させる
  if (!SD.begin(SD_CS, SPI_SD)) {  
    M5.Lcd.setTextColor(RED);
    M5.Lcd.print("SD Init NG");    // 認識失敗
    return;
  }

  M5.Lcd.println("SD Init OK");    // 認識成功

  // 3. ルートディレクトリを開く
  File root = SD.open("/");        
  if (!root) {                     
    M5.Lcd.print("open fail");     
    return;
  }

  // 4. ファイル一覧を表示
  File f = root.openNextFile();    // 最初のファイルを取得
  while (f) {                      // ファイルが存在する限り繰り返す
    M5.Lcd.println(f.name());      // ファイル名を表示
    f = root.openNextFile();       // 次のファイルを取得
  }

  M5.Lcd.setTextColor(GREEN);
  M5.Lcd.println("Done");          // 完了表示
}

void loop() {
  // テストなのでループ処理はなし
}

コード解説

※ 大まかなイメージ図です。細かい名前(GNDがPNO)などが間違っていますがイメージを掴むために。

このプログラムで重要なのは、「SPI通信の分離」です。

  • SPIClass SPI_SD(HSPI);
    • M5StickC Plus2の画面(LCD)も、内部でSPIという通信方式を使っています。
    • SDカードも同じSPIを使いますが、同じ通信レーンを使うと競合してエラーになることがあります。
    • そこで、HSPI という別の通信レーンをSDカード専用に割り当てるためのインスタンス(SPI_SD)を作成しています。
  • SPI_SD.begin(0, 36, 26, SD_CS);
    • 標準のSPIピンではなく、SD Hatが物理的に接続されているピン番号(0, 36, 26)を明示的に指定して通信を開始します。
  • SD.begin(SD_CS, SPI_SD)
    • SDカードライブラリの開始時に、第2引数としてカスタマイズした設定(SPI_SD)を渡すことで、指定したピンでの読み書きが可能になります。

動作確認

以下のような形でM5StickC Plus2の画面上にファイルが表示されていれば、SDカードソケットとの通信が成功しています。